[Add] Initial AI support with Lua
This commit is contained in:
parent
05e83fdcd6
commit
57dc51fb91
4
bin/ai_test.lua
Normal file
4
bin/ai_test.lua
Normal file
@ -0,0 +1,4 @@
|
||||
function control(pilot)
|
||||
accel(1)
|
||||
end
|
||||
|
@ -5,7 +5,7 @@
|
||||
<class>1</class>
|
||||
<movement>
|
||||
<thrust>400</thrust>
|
||||
<turn>960</turn>
|
||||
<turn>360</turn>
|
||||
<speed>360</speed>
|
||||
</movement>
|
||||
<health>
|
||||
|
60
src/ai.c
60
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(vel == NULL) vectnull(&dest->vel);
|
||||
else vectcpy(&dest->vel, vel);
|
||||
|
||||
if(pos == NULL)
|
||||
vect_cinit(&dest->pos, 0., 0.);
|
||||
else
|
||||
vect_pinit(&dest->pos, pos->mod, pos->angle);
|
||||
if(pos == NULL) vectnull(&dest->pos);
|
||||
else vectcpy(&dest->pos, pos);
|
||||
|
||||
dest->update = rk4_update;
|
||||
//dest->update = simple_update;
|
||||
}
|
||||
|
||||
// Create a new solid.
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user