[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>
|
<class>1</class>
|
||||||
<movement>
|
<movement>
|
||||||
<thrust>400</thrust>
|
<thrust>400</thrust>
|
||||||
<turn>960</turn>
|
<turn>360</turn>
|
||||||
<speed>360</speed>
|
<speed>360</speed>
|
||||||
</movement>
|
</movement>
|
||||||
<health>
|
<health>
|
||||||
|
58
src/ai.c
58
src/ai.c
@ -6,6 +6,7 @@
|
|||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pilot.h"
|
#include "pilot.h"
|
||||||
|
#include "physics.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
|
|
||||||
// == AI ======================================================
|
// == AI ======================================================
|
||||||
@ -21,23 +22,45 @@
|
|||||||
// (task).
|
// (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.
|
// Basic task.
|
||||||
// name : Tasks name (Lua function.)
|
// name : Tasks name (Lua function.)
|
||||||
// target : Target, this will depend on the task itself.
|
// target : Target, this will depend on the task itself.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* name;
|
char* name;
|
||||||
|
union {
|
||||||
void* target;
|
void* target;
|
||||||
|
unsigned int ID;
|
||||||
|
};
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
// Global Lua interpreter.
|
// Global Lua interpreter.
|
||||||
static lua_State* L = NULL;
|
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) {
|
int ai_init(void) {
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
if(L == NULL)
|
if(L == NULL)
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +70,43 @@ void ai_exit(void) {
|
|||||||
|
|
||||||
// Heart of hearts of the ai!! Brains of the pilot.
|
// Heart of hearts of the ai!! Brains of the pilot.
|
||||||
void ai_think(Pilot* 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) {
|
if(pilot->action == NULL) {
|
||||||
// Idle git!
|
// 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.
|
// | Text and GUI.
|
||||||
// ========================================================
|
// ========================================================
|
||||||
static void update_all(void) {
|
static void update_all(void) {
|
||||||
double dt = (double)(SDL_GetTicks() - time) / 1000.0;
|
double dt = (double)(SDL_GetTicks() - time) / 1000.;
|
||||||
time = SDL_GetTicks();
|
time = SDL_GetTicks();
|
||||||
|
|
||||||
if(dt > MINIMUM_FPS) {
|
if(dt > MINIMUM_FPS) {
|
||||||
Vec2 pos;
|
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.");
|
gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
return;
|
return;
|
||||||
@ -273,7 +273,7 @@ static void display_fps(const double dt) {
|
|||||||
fps_dt = fps_cur = 0.;
|
fps_dt = fps_cur = 0.;
|
||||||
}
|
}
|
||||||
Vec2 pos;
|
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);
|
gl_print(NULL, &pos, "%3.2f", fps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,16 +8,33 @@
|
|||||||
#define M_PI 3.14159265358979323846f
|
#define M_PI 3.14159265358979323846f
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Init cartesian vector.
|
// Set the vector value using cartesian coords.
|
||||||
void vect_cinit(Vec2* v, double x, double y) {
|
void vect_cset(Vec2* v, double x, double y) {
|
||||||
|
v->x = x;
|
||||||
|
v->y = y;
|
||||||
v->mod = MOD(x,y);
|
v->mod = MOD(x,y);
|
||||||
v->angle = ANGLE(x, y);
|
v->angle = ANGLE(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init polarized vector
|
// Set the vector value using polar coords.
|
||||||
void vect_pinit(Vec2* v, double mod, double angle) {
|
void vect_pset(Vec2* v, double mod, double angle) {
|
||||||
v->mod = mod;
|
v->mod = mod;
|
||||||
v->angle = angle;
|
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.========================================
|
// ==Update method.========================================
|
||||||
@ -124,14 +141,12 @@ static void rk4_update(Solid* obj, const double dt) {
|
|||||||
py += ty;
|
py += ty;
|
||||||
vy += ay*h;
|
vy += ay*h;
|
||||||
}
|
}
|
||||||
obj->vel.mod = MOD(vx, vy);
|
vect_cset(&obj->vel, vx, vy);
|
||||||
obj->vel.angle = ANGLE(vx, vy);
|
|
||||||
} else {
|
} else {
|
||||||
px += dt*vx;
|
px += dt*vx;
|
||||||
py += dt*vy;
|
py += dt*vy;
|
||||||
}
|
}
|
||||||
obj->pos.mod = MOD(px, py);
|
vect_cset(&obj->pos, px, py);
|
||||||
obj->pos.angle = ANGLE(px, py);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a new solid.
|
// 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->force.mod = 0;
|
||||||
dest->dir = 0;
|
dest->dir = 0;
|
||||||
|
|
||||||
if(vel == NULL)
|
if(vel == NULL) vectnull(&dest->vel);
|
||||||
vect_cinit(&dest->vel, 0., 0.);
|
else vectcpy(&dest->vel, vel);
|
||||||
else
|
|
||||||
vect_pinit(&dest->vel, vel->mod, vel->angle);
|
|
||||||
|
|
||||||
if(pos == NULL)
|
if(pos == NULL) vectnull(&dest->pos);
|
||||||
vect_cinit(&dest->pos, 0., 0.);
|
else vectcpy(&dest->pos, pos);
|
||||||
else
|
|
||||||
vect_pinit(&dest->pos, pos->mod, pos->angle);
|
|
||||||
|
|
||||||
dest->update = rk4_update;
|
dest->update = rk4_update;
|
||||||
//dest->update = simple_update;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new solid.
|
// Create a new solid.
|
||||||
|
@ -16,8 +16,10 @@ typedef struct {
|
|||||||
} Vec2;
|
} Vec2;
|
||||||
|
|
||||||
// Vector manupulation.
|
// Vector manupulation.
|
||||||
void vect_cinit(Vec2* v, double x, double y);
|
void vect_cset(Vec2* v, double x, double y);
|
||||||
void vect_pinit(Vec2* v, double mod, double angle);
|
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.
|
// Describe any solid in 2D space.
|
||||||
struct Solid {
|
struct Solid {
|
||||||
|
@ -56,7 +56,7 @@ static void pilot_update(Pilot* pilot, const double dt) {
|
|||||||
|
|
||||||
if(VMOD(pilot->solid->vel) > pilot->ship->speed) {
|
if(VMOD(pilot->solid->vel) > pilot->ship->speed) {
|
||||||
// Should not go faster.
|
// 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);
|
pilot_render(pilot);
|
||||||
|
@ -29,8 +29,7 @@ void player_think(Pilot* player, const double dt) {
|
|||||||
if(player_turn)
|
if(player_turn)
|
||||||
player->solid->dir_vel -= player->ship->turn * player_turn;
|
player->solid->dir_vel -= player->ship->turn * player_turn;
|
||||||
|
|
||||||
player->solid->force.angle = player->solid->dir;
|
vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
|
||||||
player->solid->force.mod = player->ship->thrust * player_acc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization/exit functions (does not assign keys).
|
// Initialization/exit functions (does not assign keys).
|
||||||
|
Loading…
Reference in New Issue
Block a user