diff --git a/bin/ai_test.lua b/bin/ai_test.lua new file mode 100644 index 0000000..4a9cbd3 --- /dev/null +++ b/bin/ai_test.lua @@ -0,0 +1,4 @@ +function control(pilot) + accel(1) +end + diff --git a/dat/ship.xml b/dat/ship.xml index f9ed5f2..e657d1c 100644 --- a/dat/ship.xml +++ b/dat/ship.xml @@ -5,7 +5,7 @@ 1 400 - 960 + 360 360 diff --git a/src/ai.c b/src/ai.c index b19aed7..944b73a 100644 --- a/src/ai.c +++ b/src/ai.c @@ -6,6 +6,7 @@ #include "def.h" #include "log.h" #include "pilot.h" +#include "physics.h" #include "ai.h" // == AI ====================================================== @@ -21,23 +22,45 @@ // (task). // ============================================================ +// Call the AI function with name f. +#define AI_LCALL(f) (lua_getglobal(L, f), lua_call(L, 0, 0)) + +static int ai_minbrakedist(lua_State* L); // Minimal breaking distance. +static int ai_accel(lua_State* L); // Accelerate. // Basic task. // name : Tasks name (Lua function.) // target : Target, this will depend on the task itself. typedef struct { char* name; - void* target; + union { + void* target; + unsigned int ID; + }; } Task; // Global Lua interpreter. static lua_State* L = NULL; +// Current pilot "thinking" and assorted variables. +static Pilot* cur_pilot = NULL; +static double pilot_acc = 0.; +static double pilot_turn = 0.; + int ai_init(void) { L = luaL_newstate(); if(L == NULL) return -1; + // Register C funstions in Lua. + lua_register(L, "minbrakedist", ai_minbrakedist); + lua_register(L, "accel", ai_accel); + + if(luaL_dofile(L, "ai_test.lua") != 0) { + WARN("Unable to load AI file: %s", "ai_test.lua"); + return -1; + } + return 0; } @@ -47,8 +70,43 @@ void ai_exit(void) { // Heart of hearts of the ai!! Brains of the pilot. void ai_think(Pilot* pilot) { + cur_pilot = pilot; // Set current pilot being processed. + pilot_acc = pilot_turn = 0.; // Clean up some variables. if(pilot->action == NULL) { // Idle git! + AI_LCALL("control"); } + + cur_pilot->solid->dir_vel = 0.; + if(pilot_turn) + cur_pilot->solid->dir_vel -= cur_pilot->ship->turn * pilot_turn; + vect_pset(&cur_pilot->solid->force, cur_pilot->ship->thrust * pilot_acc, cur_pilot->solid->dir); +} + +// ======================================================== +// C functions to call from Lua. +// ----------------------------- +// Get the minimum braking distance. +// +// Braking vel ==> v*t = 0.5 a * t^2 => t = 2*v / a +// Add turn around time (to initial velocity) : +// ==> 180.*360./cur_pilot->ship->turn +// Add it to general euler equation x = v*t + 0.5 * a * t^2 +// Have fun. +// ======================================================== +static int ai_minbrakedist(lua_State* L) { + double time = 2. * VMOD(cur_pilot->solid->vel) / + (cur_pilot->ship->thrust / cur_pilot->solid->mass); + + double dist = VMOD(cur_pilot->solid->vel) * (time + 0.5 * (180. * 360. / cur_pilot->ship->turn)) - + 0.5 * (cur_pilot->ship->thrust / cur_pilot->solid->mass)*time*time; + + lua_pushnumber(L, dist); // return + return 1; +} + +static int ai_accel(lua_State* L) { + pilot_acc = (lua_isnumber(L, 1)) ? (double)lua_tonumber(L, 1) : 1.; + return 0; } diff --git a/src/main.c b/src/main.c index abb5b25..fa30dd3 100644 --- a/src/main.c +++ b/src/main.c @@ -239,12 +239,12 @@ int main(int argc, char** argv) { // | Text and GUI. // ======================================================== static void update_all(void) { - double dt = (double)(SDL_GetTicks() - time) / 1000.0; + double dt = (double)(SDL_GetTicks() - time) / 1000.; time = SDL_GetTicks(); if(dt > MINIMUM_FPS) { Vec2 pos; - vect_cinit(&pos, 10., (double)(gl_screen.h-40)); + vect_cset(&pos, 10., (double)(gl_screen.h-40)); gl_print(NULL, &pos, "FPS is really low! Skipping frames."); SDL_GL_SwapBuffers(); return; @@ -273,7 +273,7 @@ static void display_fps(const double dt) { fps_dt = fps_cur = 0.; } Vec2 pos; - vect_cinit(&pos, 10., (double)(gl_screen.h-20)); + vect_cset(&pos, 10., (double)(gl_screen.h-20)); gl_print(NULL, &pos, "%3.2f", fps); } diff --git a/src/physics.c b/src/physics.c index 7bc523d..f0a0fa8 100644 --- a/src/physics.c +++ b/src/physics.c @@ -8,16 +8,33 @@ #define M_PI 3.14159265358979323846f #endif -// Init cartesian vector. -void vect_cinit(Vec2* v, double x, double y) { +// Set the vector value using cartesian coords. +void vect_cset(Vec2* v, double x, double y) { + v->x = x; + v->y = y; v->mod = MOD(x,y); v->angle = ANGLE(x, y); } -// Init polarized vector -void vect_pinit(Vec2* v, double mod, double angle) { +// Set the vector value using polar coords. +void vect_pset(Vec2* v, double mod, double angle) { v->mod = mod; v->angle = angle; + v->x = v->mod*cos(v->angle); + v->y = v->mod*sin(v->angle); +} + +// Copy vector source to destination. +void vectcpy(Vec2* dest, const Vec2* src) { + dest->x = src->x; + dest->y = src->y; + dest->mod = src->mod; + dest->angle = src->angle; +} + +// Null a vector. +void vectnull(Vec2* v) { + v->x = v->y = v->mod = v->angle = 0.; } // ==Update method.======================================== @@ -124,14 +141,12 @@ static void rk4_update(Solid* obj, const double dt) { py += ty; vy += ay*h; } - obj->vel.mod = MOD(vx, vy); - obj->vel.angle = ANGLE(vx, vy); + vect_cset(&obj->vel, vx, vy); } else { px += dt*vx; py += dt*vy; } - obj->pos.mod = MOD(px, py); - obj->pos.angle = ANGLE(px, py); + vect_cset(&obj->pos, px, py); } // Initialize a new solid. @@ -141,18 +156,13 @@ void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos dest->force.mod = 0; dest->dir = 0; - if(vel == NULL) - vect_cinit(&dest->vel, 0., 0.); - else - vect_pinit(&dest->vel, vel->mod, vel->angle); - - if(pos == NULL) - vect_cinit(&dest->pos, 0., 0.); - else - vect_pinit(&dest->pos, pos->mod, pos->angle); + if(vel == NULL) vectnull(&dest->vel); + else vectcpy(&dest->vel, vel); + + if(pos == NULL) vectnull(&dest->pos); + else vectcpy(&dest->pos, pos); dest->update = rk4_update; - //dest->update = simple_update; } // Create a new solid. diff --git a/src/physics.h b/src/physics.h index a674dfb..a939652 100644 --- a/src/physics.h +++ b/src/physics.h @@ -16,8 +16,10 @@ typedef struct { } Vec2; // Vector manupulation. -void vect_cinit(Vec2* v, double x, double y); -void vect_pinit(Vec2* v, double mod, double angle); +void vect_cset(Vec2* v, double x, double y); +void vect_pset(Vec2* v, double mod, double angle); +void vectcpy(Vec2* dest, const Vec2* src); +void vectnull(Vec2* v); // Describe any solid in 2D space. struct Solid { diff --git a/src/pilot.c b/src/pilot.c index 5440ff3..d7077b0 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -56,7 +56,7 @@ static void pilot_update(Pilot* pilot, const double dt) { if(VMOD(pilot->solid->vel) > pilot->ship->speed) { // Should not go faster. - VMOD(pilot->solid->vel) = pilot->ship->speed; + vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel)); } pilot_render(pilot); diff --git a/src/player.c b/src/player.c index 56a2841..6ec1aac 100644 --- a/src/player.c +++ b/src/player.c @@ -29,8 +29,7 @@ void player_think(Pilot* player, const double dt) { if(player_turn) player->solid->dir_vel -= player->ship->turn * player_turn; - player->solid->force.angle = player->solid->dir; - player->solid->force.mod = player->ship->thrust * player_acc; + vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir); } // Initialization/exit functions (does not assign keys).