[Change] Optimized ai API some.

[Fix] Few mem leaks.
This commit is contained in:
Allanis 2013-02-04 11:00:32 +00:00
parent f90a2a273c
commit 6a2f07b5b7
12 changed files with 145 additions and 44 deletions

View File

@ -64,7 +64,7 @@ face(number/Vec2 target, number invert)
-- Turn to face the current target. -- Turn to face the current target.
-- target pilot ID or Vec2 to face. -- target pilot ID or Vec2 to face.
-- invert face away if 1 -- invert face away if 1
-- return nil -- return number offset from target in grad
// ================ // ================
// MISC! // MISC!

View File

@ -1,6 +1,10 @@
function follow() function follow()
face(1,1) target = 1
accel(1) dir = face(target)
dist = getdist(getpos(target))
if dir < 10 and dist > 100 then
accel()
end
end end
function goto() function goto()

View File

@ -62,6 +62,12 @@ static Pilot* cur_pilot = NULL;
static double pilot_acc = 0.; static double pilot_acc = 0.;
static double pilot_turn = 0.; static double pilot_turn = 0.;
// Destroy the AI part of the pilot.
void ai_destroy(Pilot* p) {
ai_freetask(p->task);
}
// Init the AI stuff. Which is basically Lua.
int ai_init(void) { int ai_init(void) {
L = luaL_newstate(); L = luaL_newstate();
if(L == NULL) if(L == NULL)
@ -76,7 +82,7 @@ int ai_init(void) {
lua_register(L, "taskname", ai_taskname); lua_register(L, "taskname", ai_taskname);
lua_register(L, "gettarget", ai_gettarget); lua_register(L, "gettarget", ai_gettarget);
lua_register(L, "gettargetid", ai_gettargetid); lua_register(L, "gettargetid", ai_gettargetid);
lua_register(L, "getdistance", ai_getdistance); lua_register(L, "getdist", ai_getdistance);
lua_register(L, "getpos", ai_getpos); lua_register(L, "getpos", ai_getpos);
lua_register(L, "minbrakedist", ai_minbrakedist); lua_register(L, "minbrakedist", ai_minbrakedist);
lua_register(L, "accel", ai_accel); lua_register(L, "accel", ai_accel);
@ -96,6 +102,7 @@ int ai_init(void) {
return 0; return 0;
} }
// Clean up global AI
void ai_exit(void) { void ai_exit(void) {
lua_close(L); lua_close(L);
} }
@ -148,6 +155,7 @@ static int ai_pushtask(lua_State* L) {
Task* t = MALLOC_L(Task); Task* t = MALLOC_L(Task);
t->name = (lua_isstring(L, 2)) ? strdup((char*) lua_tostring(L, 2)) : NULL; t->name = (lua_isstring(L, 2)) ? strdup((char*) lua_tostring(L, 2)) : NULL;
t->next = NULL; t->next = NULL;
t->target = NULL;
if(lua_gettop(L) > 2) { if(lua_gettop(L) > 2) {
if(lua_isnumber(L, 3)) if(lua_isnumber(L, 3))
@ -241,8 +249,7 @@ static int ai_minbrakedist(lua_State* L) {
// Accelerate the pilot based on a param. // Accelerate the pilot based on a param.
static int ai_accel(lua_State* L) { static int ai_accel(lua_State* L) {
MIN_ARGS(1); pilot_acc = (lua_gettop(L) > 1 && lua_isnumber(L, 1)) ? ABS((double)lua_tonumber(L, 1)) : 1.;
pilot_acc = (lua_isnumber(L, 1)) ? ABS((double)lua_tonumber(L, 1)) : 1.;
return 0; return 0;
} }
@ -263,13 +270,17 @@ static int ai_face(lua_State* L) {
double mod = 10; double mod = 10;
if(lua_gettop(L) > 1 && lua_isnumber(L,2)) if(lua_gettop(L) > 1 && lua_isnumber(L,2))
switch((int)lua_tonumber(L,2)) { switch((int)lua_tonumber(L,2)) {
case 0: break;
case 1: mod *= -1; break; case 1: mod *= -1; break;
case 2: break; case 2: break;
} }
double diff = angle_diff(cur_pilot->solid->dir, vect_angle(&cur_pilot->solid->pos, v));
pilot_turn = mod * angle_diff(cur_pilot->solid->dir, vect_angle(&cur_pilot->solid->pos, v)); pilot_turn = mod*diff;
return 0; lua_pushnumber(L, ABS(diff*180./M_PI));
return 1;
} }
// Create a vector. // Create a vector.

View File

@ -28,6 +28,8 @@ extern const char* keybindNames[]; // Keybindings.
static int quit = 0; // Primary loop. static int quit = 0; // Primary loop.
static unsigned int time = 0; // Calculate FPS and movement. static unsigned int time = 0; // Calculate FPS and movement.
static int show_fps = 1; // Default - True.
// Prototypes. // Prototypes.
static void print_usage(char** argv); static void print_usage(char** argv);
@ -82,6 +84,10 @@ int main(int argc, char** argv) {
if((int)lua_tonumber(L, -1) == 1) if((int)lua_tonumber(L, -1) == 1)
gl_screen.fullscreen = 1; gl_screen.fullscreen = 1;
lua_getglobal(L, "fps");
if(lua_isnumber(L, -1))
show_fps = (int)lua_tonumber(L, -1);
// Joystick. // Joystick.
lua_getglobal(L, "joystick"); lua_getglobal(L, "joystick");
if(lua_isnumber(L, -1)) if(lua_isnumber(L, -1))
@ -137,19 +143,23 @@ int main(int argc, char** argv) {
// Parse arguments. // Parse arguments.
static struct option long_options[] = { static struct option long_options[] = {
{ "fullscreen", no_argument, 0, 'f' }, { "fullscreen", no_argument, 0, 'f' },
{ "fps", optional_argument, 0, 'F' },
{ "joystick", required_argument, 0, 'j' }, { "joystick", required_argument, 0, 'j' },
{ "joystick", required_argument, 0, 'J' }, { "joystick", required_argument, 0, 'J' },
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' }, { "version", no_argument, 0, 'v' },
{ 0, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
int option_index = 0; int option_index = 0;
int c = 0; int c = 0;
while((c = getopt_long(argc, argv, "fJ:j:hv", long_options, &option_index)) != -1) { while((c = getopt_long(argc, argv, "fFJ:j:hv", long_options, &option_index)) != -1) {
switch(c) { switch(c) {
case 'f': case 'f':
gl_screen.fullscreen = 1; gl_screen.fullscreen = 1;
break; break;
case 'F':
if(optarg != NULL) show_fps = atoi(optarg);
break;
case 'j': case 'j':
indjoystick = atoi(optarg); indjoystick = atoi(optarg);
break; break;
@ -256,7 +266,7 @@ static void update_all(void) {
if(dt > MINIMUM_FPS) { if(dt > MINIMUM_FPS) {
Vec2 pos; Vec2 pos;
vect_cset(&pos, 10., (double)(gl_screen.h-40)); vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
gl_print(NULL, &pos, "FPS is really low! Skipping frames."); gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
return; return;
@ -264,10 +274,15 @@ static void update_all(void) {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// BG.
space_render(dt); space_render(dt);
planets_render(); planets_render();
// N
pilots_update(dt); pilots_update(dt);
// FG.
player_renderGUI();
display_fps(dt); display_fps(dt);
@ -287,7 +302,8 @@ static void display_fps(const double dt) {
fps_dt = fps_cur = 0.; fps_dt = fps_cur = 0.;
} }
Vec2 pos; Vec2 pos;
vect_cset(&pos, 10., (double)(gl_screen.h-20)); vect_csetmin(&pos, 10., (double)(gl_screen.h-20));
gl_print(NULL, &pos, "%3.2f", fps); if(show_fps)
gl_print(NULL, &pos, "%3.2f", fps);
} }

View File

@ -420,6 +420,8 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te
// End of the display list. // End of the display list.
glEndList(); glEndList();
FT_Done_Glyph(glyph);
} }
void gl_fontInit(gl_font* font, const char* fname, unsigned int h) { void gl_fontInit(gl_font* font, const char* fname, unsigned int h) {

View File

@ -25,6 +25,12 @@ void vect_cset(Vec2* v, const double x, const double y) {
v->angle = ANGLE(x, y); v->angle = ANGLE(x, y);
} }
// Create a minimal vector, only valid for blitting.
void vect_csetmin(Vec2* v, const double x, const double y) {
v->x = x;
v->y = y;
}
// Set the vector value using polar coords. // Set the vector value using polar coords.
void vect_pset(Vec2* v, const double mod, const double angle) { void vect_pset(Vec2* v, const double mod, const double angle) {
v->mod = mod; v->mod = mod;

View File

@ -20,6 +20,8 @@ typedef struct {
// Vector manupulation. // Vector manupulation.
void vect_cset(Vec2* v, const double x, const double y); void vect_cset(Vec2* v, const double x, const double y);
// Doesn't set mod nor angle.
void vect_csetmin(Vec2* v, const double x, const double y);
void vect_pset(Vec2* v, const double mod, const double angle); void vect_pset(Vec2* v, const double mod, const double angle);
void vectcpy(Vec2* dest, const Vec2* src); void vectcpy(Vec2* dest, const Vec2* src);
void vectnull(Vec2* v); void vectnull(Vec2* v);

View File

@ -14,8 +14,11 @@ static unsigned int pilot_id = 0;
static Pilot** pilot_stack; static Pilot** pilot_stack;
static int pilots = 0; static int pilots = 0;
// External.
extern void ai_destroy(Pilot* p); // Ai.
extern void player_think(Pilot* pilot, const double dt); // Player.c extern void player_think(Pilot* pilot, const double dt); // Player.c
extern void ai_think(Pilot* pilot); // Ai.c extern void ai_think(Pilot* pilot); // Ai.c
// Internal.
static void pilot_update(Pilot* pilot, const double dt); static void pilot_update(Pilot* pilot, const double dt);
static void pilot_render(Pilot* pilot); static void pilot_render(Pilot* pilot);
@ -110,6 +113,24 @@ unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel, const Vec2* p
return dyn->id; return dyn->id;
} }
// Frees and cleans up a pilot.
void pilot_destroy(Pilot* p) {
int i;
solid_free(p->solid);
free(p->name);
ai_destroy(p);
for(i = 0; i < pilots; i++)
if(pilot_stack[i] == p)
break;
while(i < pilots) {
pilot_stack[i] = pilot_stack[i+1];
i++;
}
free(p);
}
// Free the prisoned pilot! // Free the prisoned pilot!
void pilots_free(void) { void pilots_free(void) {
int i; int i;

View File

@ -39,6 +39,7 @@ unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel,
const Vec2* pos, const int flags); const Vec2* pos, const int flags);
// Cleanup. // Cleanup.
void pilot_destroy(Pilot* p);
void pilots_free(void); void pilots_free(void);
// Update. // Update.

View File

@ -32,6 +32,17 @@ void player_think(Pilot* player, const double dt) {
vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir); vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
} }
// ================
// GUI!
// ================
void player_renderGUI(void) {
}
// ================
// INPUT!
// ================
// Initialization/exit functions (does not assign keys). // Initialization/exit functions (does not assign keys).
void input_init(void) { void input_init(void) {
Keybind* tmp; Keybind* tmp;
@ -178,6 +189,7 @@ void input_handle(SDL_Event* event) {
break; break;
case SDL_JOYBUTTONUP: case SDL_JOYBUTTONUP:
input_joyup(event->jbutton.button); input_joyup(event->jbutton.button);
break;
case SDL_KEYDOWN: case SDL_KEYDOWN:
input_keydown(event->key.keysym.sym); input_keydown(event->key.keysym.sym);
break; break;

View File

@ -3,6 +3,9 @@
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType; typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
// GUI.
void player_renderGUI(void);
int player_isFlag(unsigned int flag); int player_isFlag(unsigned int flag);
void player_setFlag(unsigned int flag); void player_setFlag(unsigned int flag);
void player_rmFlag(unsigned int flag); void player_rmFlag(unsigned int flag);

View File

@ -26,6 +26,13 @@
#define PLANET_GFX "../gfx/planet/" #define PLANET_GFX "../gfx/planet/"
// Overcome warning due to zero value.
#define FLAG_XSET (1<<0)
#define FLAG_YSET (1<<1)
#define FLAG_ASTEROIDSSET (1<<2)
#define FLAG_INTEFERENCESET (1<<3)
// Planet types. I didn't take them from Star Trek, I promise. // Planet types. I didn't take them from Star Trek, I promise.
typedef enum { typedef enum {
PLANET_CLASS_A, // Geothermal. PLANET_CLASS_A, // Geothermal.
@ -55,14 +62,14 @@ typedef enum {
typedef struct { typedef struct {
char* name; char* name;
double x, y; // Position in star system. Vec2 pos; // Position in star system.
PlanetClass class; PlanetClass class;
gl_texture* gfx_space; // Graphics in space. gl_texture* gfx_space; // Graphics in space.
} Planet; } Planet;
typedef struct { typedef struct {
char* name; char* name;
double x, y; // Position. Vec2 pos; // Position.
int stars, asteroids; // Un numero! int stars, asteroids; // Un numero!
double interference; // Un uh.. Percentage. double interference; // Un uh.. Percentage.
@ -112,6 +119,9 @@ static Planet* planet_get(const char* name) {
Planet* tmp = NULL; Planet* tmp = NULL;
char str[MAX_PATH_NAME] = "\0"; char str[MAX_PATH_NAME] = "\0";
char* tstr;
uint32_t flags = 0;
uint32_t bufsize; uint32_t bufsize;
char* buf = pack_readfile(DATA, PLANET_DATA, &bufsize); char* buf = pack_readfile(DATA, PLANET_DATA, &bufsize);
@ -133,9 +143,10 @@ static Planet* planet_get(const char* name) {
do { do {
if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_PLANET_TAG)==0) { if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_PLANET_TAG)==0) {
if(strcmp((char*)xmlGetProp(node, (xmlChar*)"name"), name)==0) { // Found. tstr = (char*)xmlGetProp(node, (xmlChar*)"name");
if(strcmp(tstr, name)==0) { // Found.
tmp = CALLOC_L(Planet); tmp = CALLOC_L(Planet);
tmp->name = strdup(name); tmp->name = tstr;
node = node->xmlChildrenNode; node = node->xmlChildrenNode;
@ -151,10 +162,14 @@ static Planet* planet_get(const char* name) {
else if(strcmp((char*)node->name, "pos")==0) { else if(strcmp((char*)node->name, "pos")==0) {
cur = node->children; cur = node->children;
while((cur = cur->next)) { while((cur = cur->next)) {
if(strcmp((char*)cur->name, "x")==0) if(strcmp((char*)cur->name, "x")==0) {
tmp->x = atof((char*)cur->children->content); flags |= FLAG_XSET;
else if(strcmp((char*)cur->name, "y")==0) tmp->pos.x = atof((char*)cur->children->content);
tmp->y = atof((char*)cur->children->content); }
else if(strcmp((char*)cur->name, "y")==0) {
flags |= FLAG_YSET;
tmp->pos.y = atof((char*)cur->children->content);
}
} }
} }
else if(strcmp((char*)node->name, "general")==0) { else if(strcmp((char*)node->name, "general")==0) {
@ -166,7 +181,8 @@ static Planet* planet_get(const char* name) {
} }
} }
break; break;
} } else
free(tstr); // xmlGetProp mallocs the string.
} }
} while((node = node->next)); } while((node = node->next));
@ -176,9 +192,9 @@ static Planet* planet_get(const char* name) {
// Check elements. // Check elements.
if(tmp) { if(tmp) {
#define MELEMENT(o,s) if(o == 0) WARN("Planet '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if((o) == 0) WARN("Planet '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->x, "x"); MELEMENT(flags&FLAG_XSET, "x");
MELEMENT(tmp->x, "y"); MELEMENT(flags&FLAG_YSET, "y");
MELEMENT(tmp->class, "class"); MELEMENT(tmp->class, "class");
#undef MELEMENT #undef MELEMENT
} else } else
@ -194,8 +210,10 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
StarSystem* tmp = CALLOC_L(StarSystem); StarSystem* tmp = CALLOC_L(StarSystem);
xmlNodePtr cur, node; xmlNodePtr cur, node;
tmp->name = strdup((char*) xmlGetProp(parent, (xmlChar*)"name")); uint32_t flags;
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); // Already mallocs.
node = parent->xmlChildrenNode; node = parent->xmlChildrenNode;
while((node = node->next)) { while((node = node->next)) {
@ -203,21 +221,29 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
if(strcmp((char*)node->name, "pos")==0) { if(strcmp((char*)node->name, "pos")==0) {
cur = node->children; cur = node->children;
while((cur = cur->next)) { while((cur = cur->next)) {
if(strcmp((char*)cur->name, "x")==0) if(strcmp((char*)cur->name, "x")==0) {
tmp->x = atof((char*)cur->children->content); flags |= FLAG_XSET;
if(strcmp((char*)cur->name, "y")==0) tmp->pos.x = atof((char*)cur->children->content);
tmp->y = atof((char*)cur->children->content); }
if(strcmp((char*)cur->name, "y")==0) {
flags |= FLAG_YSET;
tmp->pos.y = atof((char*)cur->children->content);
}
} }
} }
else if(strcmp((char*)node->name, "general")==0) { else if(strcmp((char*)node->name, "general")==0) {
cur = node->children; cur = node->children;
while((cur = cur->next)) { while((cur = cur->next)) {
if(strcmp((char*)cur->name, "stars")==0) if(strcmp((char*)cur->name, "stars")==0) // Non-zero.
tmp->stars = atoi((char*)cur->children->content); tmp->stars = atoi((char*)cur->children->content);
else if(strcmp((char*)cur->name, "asteroids")==0) else if(strcmp((char*)cur->name, "asteroids")==0) {
flags |= FLAG_ASTEROIDSSET;
tmp->asteroids = atoi((char*)cur->children->content); tmp->asteroids = atoi((char*)cur->children->content);
else if(strcmp((char*)cur->name, "interference")==0) }
else if(strcmp((char*)cur->name, "interference")==0) {
flags |= FLAG_INTEFERENCESET;
tmp->interference = atof((char*)cur->children->content); tmp->interference = atof((char*)cur->children->content);
}
} }
} }
else if(strcmp((char*)node->name, "planets")==0) { else if(strcmp((char*)node->name, "planets")==0) {
@ -233,12 +259,12 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
} }
} }
// Check elements. // Check elements.
#define MELEMENT(o,s) if(o == 0) WARN("Star System '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if((o) == 0) WARN("Star System '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->x, "x"); MELEMENT(flags&FLAG_XSET, "x");
MELEMENT(tmp->x, "y"); MELEMENT(flags&FLAG_YSET, "y");
MELEMENT(tmp->stars, "stars"); MELEMENT(tmp->stars, "stars");
/*MELEMENT(tmp->asteroids, "asteroids"); // Can be 0. MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); // Can be 0.
MELEMENT(tmp->interference, "interference");*/ MELEMENT(flags&FLAG_INTEFERENCESET, "inteference");
#undef MELEMENT #undef MELEMENT
DEBUG("Loaded Star System '%s' with %d Planets%s", tmp->name, tmp->nplanets, (tmp->nplanets > 1) ? "s" : ""); DEBUG("Loaded Star System '%s' with %d Planets%s", tmp->name, tmp->nplanets, (tmp->nplanets > 1) ? "s" : "");
@ -314,11 +340,8 @@ void space_render(double dt) {
void planets_render(void) { void planets_render(void) {
int i; int i;
Vec2 v; Vec2 v;
for(i = 0; i < cur_system->nplanets; i++) { for(i = 0; i < cur_system->nplanets; i++)
v.x = cur_system->planets[i].x; gl_blitSprite(cur_system->planets[i].gfx_space, &cur_system->planets[i].pos, 0, 0);
v.y = cur_system->planets[i].y;
gl_blitSprite(cur_system->planets[i].gfx_space, &v, 0, 0);
}
} }
// Clean up the system. // Clean up the system.