[Add] Rudimentary shooting. This needs some work.
[Add] Layers should be working properly.
This commit is contained in:
parent
b13ecc66bb
commit
998a1bf68b
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,5 +26,6 @@
|
|||||||
*bin/Lephisto
|
*bin/Lephisto
|
||||||
*bin/data
|
*bin/data
|
||||||
*pack
|
*pack
|
||||||
|
*core
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,5 +48,5 @@ data: pack $(DATAFILES) ../src/pack.c
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo -e "\tRemoving data.."
|
@echo -e "\tRemoving data.."
|
||||||
rm -rf $(OBJS) $(APPNAME) $(DATA) pack
|
rm -rf $(OBJS) $(APPNAME) $(DATA) pack core
|
||||||
|
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
<specific type = "1">
|
<specific type = "1">
|
||||||
<sound>laser.wav</sound>
|
<sound>laser.wav</sound>
|
||||||
<gfx>lasergreen.png</gfx>
|
<gfx>lasergreen.png</gfx>
|
||||||
<speed>450</speed>
|
<delay>500</delay>
|
||||||
|
<speed>550</speed>
|
||||||
|
<range>300</range>
|
||||||
<accuracy>30</accuracy>
|
<accuracy>30</accuracy>
|
||||||
<damage>
|
<damage>
|
||||||
<armor>20</armor>
|
<armor>20</armor>
|
||||||
|
1
src/ai.c
1
src/ai.c
@ -89,6 +89,7 @@ static double pilot_turn = 0.;
|
|||||||
|
|
||||||
// Destroy the AI part of the pilot.
|
// Destroy the AI part of the pilot.
|
||||||
void ai_destroy(Pilot* p) {
|
void ai_destroy(Pilot* p) {
|
||||||
|
if(p->task)
|
||||||
ai_freetask(p->task);
|
ai_freetask(p->task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
src/main.c
60
src/main.c
@ -18,9 +18,11 @@
|
|||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
#include "outfit.h"
|
#include "outfit.h"
|
||||||
|
#include "pack.h"
|
||||||
|
#include "weapon.h"
|
||||||
#include "pilot.h"
|
#include "pilot.h"
|
||||||
|
|
||||||
#define WINDOW_CAPTION "Lephisto"
|
#define APPNAME "Lephisto"
|
||||||
#define CONF_FILE "conf"
|
#define CONF_FILE "conf"
|
||||||
#define MINIMUM_FPS 0.5
|
#define MINIMUM_FPS 0.5
|
||||||
|
|
||||||
@ -31,14 +33,13 @@ static unsigned int time = 0; // Calculate FPS and movement.
|
|||||||
|
|
||||||
#define DATA_DEF "data"
|
#define DATA_DEF "data"
|
||||||
char* data = NULL;
|
char* data = NULL;
|
||||||
|
|
||||||
static int show_fps = 1; // Default - True.
|
static int show_fps = 1; // Default - True.
|
||||||
|
static int max_fps = 0;
|
||||||
|
|
||||||
// Prototypes.
|
// Prototypes.
|
||||||
|
|
||||||
static void print_usage(char** argv);
|
static void print_usage(char** argv);
|
||||||
static void display_fps(const double dt);
|
static void display_fps(const double dt);
|
||||||
|
|
||||||
// Update.
|
// Update.
|
||||||
static void update_all(void);
|
static void update_all(void);
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ static void print_usage(char** argv) {
|
|||||||
LOG("USAGE: %s [OPTION]", argv[0]);
|
LOG("USAGE: %s [OPTION]", argv[0]);
|
||||||
LOG("Options are:");
|
LOG("Options are:");
|
||||||
LOG("\t-f, --fullscreen - Fullscreen");
|
LOG("\t-f, --fullscreen - Fullscreen");
|
||||||
LOG("\t-F, --fps - Toggle frames per second");
|
LOG("\t-F, --fps - Limit frames per second");
|
||||||
LOG("\t-d s, --data s - Set the data file to be s");
|
LOG("\t-d s, --data s - Set the data file to be s");
|
||||||
LOG("\t-j n, --joystick n - Use joystick (n)");
|
LOG("\t-j n, --joystick n - Use joystick (n)");
|
||||||
LOG("\t-J s, --joystick s - Use joystick whose name contains (s)");
|
LOG("\t-J s, --joystick s - Use joystick whose name contains (s)");
|
||||||
@ -57,6 +58,10 @@ static void print_usage(char** argv) {
|
|||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
// Print the version.
|
||||||
|
LOG(""APPNAME" v%d.%d.%d", VMAJOR, VMINOR, VREV);
|
||||||
|
|
||||||
// Initialize SDL for possible warnings.
|
// Initialize SDL for possible warnings.
|
||||||
SDL_Init(0);
|
SDL_Init(0);
|
||||||
// Default values..
|
// Default values..
|
||||||
@ -74,6 +79,7 @@ int main(int argc, char** argv) {
|
|||||||
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_w, 0);
|
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_w, 0);
|
||||||
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_a, 0);
|
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_a, 0);
|
||||||
input_setKeybind("right", KEYBIND_KEYBOARD, SDLK_d, 0);
|
input_setKeybind("right", KEYBIND_KEYBOARD, SDLK_d, 0);
|
||||||
|
input_setKeybind("primary", KEYBIND_KEYBOARD, SDLK_SPACE, 0);
|
||||||
|
|
||||||
// Use Lua to parse configuration file.
|
// Use Lua to parse configuration file.
|
||||||
lua_State* L = luaL_newstate();
|
lua_State* L = luaL_newstate();
|
||||||
@ -96,7 +102,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
lua_getglobal(L, "fps");
|
lua_getglobal(L, "fps");
|
||||||
if(lua_isnumber(L, -1))
|
if(lua_isnumber(L, -1))
|
||||||
show_fps = (int)lua_tonumber(L, -1);
|
max_fps = (int)lua_tonumber(L, -1);
|
||||||
|
|
||||||
// Joystick.
|
// Joystick.
|
||||||
lua_getglobal(L, "joystick");
|
lua_getglobal(L, "joystick");
|
||||||
@ -153,7 +159,7 @@ 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' },
|
{ "fps", required_argument, 0, 'F' },
|
||||||
{ "data", required_argument, 0, 'd' },
|
{ "data", required_argument, 0, 'd' },
|
||||||
{ "joystick", required_argument, 0, 'j' },
|
{ "joystick", required_argument, 0, 'j' },
|
||||||
{ "joystick", required_argument, 0, 'J' },
|
{ "joystick", required_argument, 0, 'J' },
|
||||||
@ -163,14 +169,14 @@ int main(int argc, char** argv) {
|
|||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while((c = getopt_long(argc, argv, "fFd:J:j:hv", long_options, &option_index)) != -1) {
|
while((c = getopt_long(argc, argv, "fF:d:J: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':
|
case 'F':
|
||||||
if(optarg != NULL) show_fps = atoi(optarg);
|
if(optarg != NULL) show_fps = atoi(optarg);
|
||||||
else show_fps = !show_fps;
|
else max_fps = !show_fps;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
data = strdup(optarg);
|
data = strdup(optarg);
|
||||||
@ -195,11 +201,21 @@ int main(int argc, char** argv) {
|
|||||||
if(gl_init()) {
|
if(gl_init()) {
|
||||||
// Initializes video output.
|
// Initializes video output.
|
||||||
WARN("Error initializing video output, exiting...");
|
WARN("Error initializing video output, exiting...");
|
||||||
|
SDL_Quit();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the data file is valid.
|
||||||
|
if(pack_check(data)) {
|
||||||
|
ERR("Data file '%s' not found", data);
|
||||||
|
WARN("You can specify what data file you want to use with '-d'");
|
||||||
|
WARN("See -h or -- help for more infoamtion.");
|
||||||
|
SDL_Quit();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window.
|
// Window.
|
||||||
SDL_WM_SetCaption(WINDOW_CAPTION, NULL);
|
SDL_WM_SetCaption(APPNAME, NULL);
|
||||||
|
|
||||||
// Input.
|
// Input.
|
||||||
if(indjoystick >= 0 || namjoystick != NULL) {
|
if(indjoystick >= 0 || namjoystick != NULL) {
|
||||||
@ -225,11 +241,11 @@ int main(int argc, char** argv) {
|
|||||||
space_load();
|
space_load();
|
||||||
|
|
||||||
// Testing.
|
// Testing.
|
||||||
pilot_create(get_ship("Ship"), "Player", NULL, NULL, PILOT_PLAYER);
|
pilot_create(get_ship("Ship"), "Player", 0., NULL, NULL, PILOT_PLAYER);
|
||||||
gl_bindCamera(&player->solid->pos);
|
gl_bindCamera(&player->solid->pos);
|
||||||
space_init("SaraSys");
|
space_init("SaraSys");
|
||||||
|
|
||||||
pilot_create(get_ship("Test"), NULL, NULL, NULL, 0);
|
pilot_create(get_ship("Test"), NULL, 2., NULL, NULL, 0);
|
||||||
|
|
||||||
time = SDL_GetTicks();
|
time = SDL_GetTicks();
|
||||||
|
|
||||||
@ -268,19 +284,23 @@ int main(int argc, char** argv) {
|
|||||||
//
|
//
|
||||||
// BG | Stars and planets.
|
// BG | Stars and planets.
|
||||||
// | Background particles.
|
// | Background particles.
|
||||||
|
// | Back layer weapons.
|
||||||
// X
|
// X
|
||||||
// N | NPC ships.
|
// N | NPC ships.
|
||||||
// | Normal layer particles (above ships).
|
// | Normal layer particles (above ships).
|
||||||
|
// | Front layer weapons.
|
||||||
// X
|
// X
|
||||||
// FG | Player.
|
// FG | Player.
|
||||||
// | Foreground particles.
|
// | Foreground particles.
|
||||||
// | Text and GUI.
|
// | Text and GUI.
|
||||||
// ========================================================
|
// ========================================================
|
||||||
|
static double fps_dt = 1.;
|
||||||
static void update_all(void) {
|
static void update_all(void) {
|
||||||
// dt in us.
|
// dt in us.
|
||||||
double dt = (double)(SDL_GetTicks() - time) / 1000.;
|
double dt = (double)(SDL_GetTicks() - time) / 1000.;
|
||||||
time = SDL_GetTicks();
|
time = SDL_GetTicks();
|
||||||
|
|
||||||
|
// TODO: This could use some work.
|
||||||
if(dt > MINIMUM_FPS) {
|
if(dt > MINIMUM_FPS) {
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
|
vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
|
||||||
@ -288,20 +308,27 @@ static void update_all(void) {
|
|||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If FPS is limited.
|
||||||
|
else if(max_fps != 0 && dt < 1./max_fps) {
|
||||||
|
double delay = 1./max_fps - dt;
|
||||||
|
SDL_Delay(delay);
|
||||||
|
fps_dt += delay; // Make sure it displays the propper FPS.
|
||||||
|
}
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// --
|
||||||
// BG.
|
// BG.
|
||||||
space_render(dt);
|
space_render(dt);
|
||||||
planets_render();
|
planets_render();
|
||||||
|
weapons_update(dt, WEAPON_LAYER_BG);
|
||||||
// N
|
// N.
|
||||||
pilots_update(dt);
|
pilots_update(dt);
|
||||||
|
weapons_update(dt, WEAPON_LAYER_FG);
|
||||||
// FG.
|
// FG.
|
||||||
player_renderGUI();
|
player_render();
|
||||||
|
|
||||||
display_fps(dt);
|
display_fps(dt);
|
||||||
|
// --
|
||||||
|
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
}
|
}
|
||||||
@ -310,7 +337,6 @@ static void update_all(void) {
|
|||||||
// Spit this out on display.
|
// Spit this out on display.
|
||||||
static double fps = 0.;
|
static double fps = 0.;
|
||||||
static double fps_cur = 0.;
|
static double fps_cur = 0.;
|
||||||
static double fps_dt = 1.;
|
|
||||||
static void display_fps(const double dt) {
|
static void display_fps(const double dt) {
|
||||||
fps_dt += dt;
|
fps_dt += dt;
|
||||||
fps_cur += 1.;
|
fps_cur += 1.;
|
||||||
|
38
src/outfit.c
38
src/outfit.c
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "pack.h"
|
||||||
#include "outfit.h"
|
#include "outfit.h"
|
||||||
|
|
||||||
#define XML_NODE_START 1
|
#define XML_NODE_START 1
|
||||||
@ -31,8 +32,27 @@ Outfit* outfit_get(const char* name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return 1 if outfit is a weapon.
|
// Return 1 if outfit is a weapon.
|
||||||
int outfit_isweapon(const Outfit* o) {
|
int outfit_isWeapon(const Outfit* o) {
|
||||||
return (o->type > OUTFIT_TYPE_NULL && o->type <= OUTFIT_TYPE_MISSILE_SWARM_SMART);
|
return ((o->type == OUTFIT_TYPE_BOLT) || (o->type == OUTFIT_TYPE_BEAM));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 1 if outfit is a launcher.
|
||||||
|
int outfit_isLauncher(const Outfit* o) {
|
||||||
|
return((o->type == OUTFIT_TYPE_MISSILE_DUMB) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SEEK) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SWARM) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SWARM_SMART));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 1 if outfit is weapon ammunition.
|
||||||
|
int outfit_isAmmo(const Outfit* o) {
|
||||||
|
return((o->type == OUTFIT_TYPE_MISSILE_DUMB_AMMO) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SEEK_AMMO) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SWARM_AMMO) ||
|
||||||
|
(o->type == OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* outfit_typename[] = {
|
const char* outfit_typename[] = {
|
||||||
@ -40,10 +60,15 @@ const char* outfit_typename[] = {
|
|||||||
"Bolt Cannon",
|
"Bolt Cannon",
|
||||||
"Beam Cannon",
|
"Beam Cannon",
|
||||||
"Dumb Missile",
|
"Dumb Missile",
|
||||||
|
"Dumb Missile Ammunition",
|
||||||
"Seeker Missile",
|
"Seeker Missile",
|
||||||
"Smart Missile",
|
"Seeker Missile Ammunition",
|
||||||
|
"Smart Seeker Missile",
|
||||||
|
"Smart Seeker Missile Ammunition",
|
||||||
"Swam Missile",
|
"Swam Missile",
|
||||||
"Smart Swarm Missile"
|
"Swarm Missile Ammunition Pack",
|
||||||
|
"Smart Swarm Missile",
|
||||||
|
"Smart Swarm Missile Ammunition Pack"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* outfit_getType(const Outfit* o) {
|
const char* outfit_getType(const Outfit* o) {
|
||||||
@ -61,6 +86,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
|
|||||||
// Load all the things.
|
// Load all the things.
|
||||||
if(strcmp((char*)node->name, "speed")==0)
|
if(strcmp((char*)node->name, "speed")==0)
|
||||||
tmp->speed = (double)atoi((char*)node->children->content);
|
tmp->speed = (double)atoi((char*)node->children->content);
|
||||||
|
else if(strcmp((char*)node->name, "delay")==0)
|
||||||
|
tmp->delay = atoi((char*)node->children->content);
|
||||||
else if(strcmp((char*)node->name, "accuracy")==0)
|
else if(strcmp((char*)node->name, "accuracy")==0)
|
||||||
tmp->accuracy = atof((char*)node->children->content)*M_PI/180.; // to rad.
|
tmp->accuracy = atof((char*)node->children->content)*M_PI/180.; // to rad.
|
||||||
else if(strcmp((char*)node->name, "gfx")==0) {
|
else if(strcmp((char*)node->name, "gfx")==0) {
|
||||||
@ -81,6 +108,7 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
|
|||||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||||
MELEMENT(tmp->speed, "speed");
|
MELEMENT(tmp->speed, "speed");
|
||||||
MELEMENT(tmp->accuracy, "tech");
|
MELEMENT(tmp->accuracy, "tech");
|
||||||
|
MELEMENT(tmp->delay, "delay");
|
||||||
MELEMENT(tmp->damage_armor, "armor' from element 'damage");
|
MELEMENT(tmp->damage_armor, "armor' from element 'damage");
|
||||||
MELEMENT(tmp->damage_shield, "shield' from element 'damage");
|
MELEMENT(tmp->damage_shield, "shield' from element 'damage");
|
||||||
#undef MELEMENT
|
#undef MELEMENT
|
||||||
@ -181,7 +209,7 @@ int outfit_load(void) {
|
|||||||
void outfit_free(void) {
|
void outfit_free(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < outfits; i++) {
|
for(i = 0; i < outfits; i++) {
|
||||||
if(outfit_isweapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
|
if(outfit_isWeapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
|
||||||
gl_freeTexture(outfit_stack[i].gfx_space);
|
gl_freeTexture(outfit_stack[i].gfx_space);
|
||||||
free(outfit_stack[i].name);
|
free(outfit_stack[i].name);
|
||||||
}
|
}
|
||||||
|
44
src/outfit.h
44
src/outfit.h
@ -1,42 +1,70 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
|
||||||
|
#define OUTFIT_PROP_WEAP_PRIMARY (1<<0)
|
||||||
|
#define OUTFIT_PROP_WEAP_SECONDARY (1<<1)
|
||||||
|
|
||||||
// Outfit types.
|
// Outfit types.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OUTFIT_TYPE_NULL,
|
OUTFIT_TYPE_NULL = 0,
|
||||||
OUTFIT_TYPE_BOLT,
|
OUTFIT_TYPE_BOLT,
|
||||||
OUTFIT_TYPE_BEAM,
|
OUTFIT_TYPE_BEAM,
|
||||||
OUTFIT_TYPE_MISSILE_DUMB,
|
OUTFIT_TYPE_MISSILE_DUMB,
|
||||||
|
OUTFIT_TYPE_MISSILE_DUMB_AMMO,
|
||||||
OUTFIT_TYPE_MISSILE_SEEK,
|
OUTFIT_TYPE_MISSILE_SEEK,
|
||||||
|
OUTFIT_TYPE_MISSILE_SEEK_AMMO,
|
||||||
OUTFIT_TYPE_MISSILE_SEEK_SMART,
|
OUTFIT_TYPE_MISSILE_SEEK_SMART,
|
||||||
|
OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,
|
||||||
OUTFIT_TYPE_MISSILE_SWARM,
|
OUTFIT_TYPE_MISSILE_SWARM,
|
||||||
OUTFIT_TYPE_MISSILE_SWARM_SMART
|
OUTFIT_TYPE_MISSILE_SWARM_AMMO,
|
||||||
|
OUTFIT_TYPE_MISSILE_SWARM_SMART,
|
||||||
|
OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO
|
||||||
} OutfitType;
|
} OutfitType;
|
||||||
|
|
||||||
// An outfit depends a lot on the type.
|
// An outfit depends a lot on the type.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* name;
|
char* name;
|
||||||
|
|
||||||
|
// General specs.
|
||||||
int max;
|
int max;
|
||||||
int tech;
|
int tech;
|
||||||
int mass;
|
int mass;
|
||||||
|
|
||||||
gl_texture gfx_store;
|
gl_texture gfx_store; // Store graphic.
|
||||||
|
|
||||||
|
int properties; // Properties stored bitwise.
|
||||||
|
|
||||||
|
// Type dependant.
|
||||||
OutfitType type;
|
OutfitType type;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct { // Beam/Bolt.
|
||||||
double speed;
|
unsigned int delay; // Delay between shots.
|
||||||
double accuracy;
|
double speed; // Speed of shot. (not applicable to beam.
|
||||||
double damage_armor, damage_shield;
|
double range;
|
||||||
|
double accuracy; // Desviation accuracy.
|
||||||
|
double damage_armor, damage_shield; // Damage.
|
||||||
|
|
||||||
gl_texture* gfx_space;
|
gl_texture* gfx_space;
|
||||||
};
|
};
|
||||||
|
struct { // Launcher.
|
||||||
|
//unsigned int delay; // Delay between shots.
|
||||||
|
};
|
||||||
|
struct { // Ammo.
|
||||||
|
//double speed; // Max speed.
|
||||||
|
//double turn; // Turn vel.
|
||||||
|
//double thrust; // Acceleration.
|
||||||
|
//double damage_armor, damage_shield;
|
||||||
|
|
||||||
|
//gl_texture* gfx_space;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} Outfit;
|
} Outfit;
|
||||||
|
|
||||||
Outfit* outfit_get(const char* name);
|
Outfit* outfit_get(const char* name);
|
||||||
int outfit_isweapon(const Outfit* o);
|
// Outfit types.
|
||||||
|
int outfit_isWeapon(const Outfit* o);
|
||||||
|
int outfit_isLauncher(const Outfit* o);
|
||||||
|
int outfit_isAmmo(const Outfit* o);
|
||||||
const char* outfit_getType(const Outfit* o);
|
const char* outfit_getType(const Outfit* o);
|
||||||
|
|
||||||
// Load/free outfit stack.
|
// Load/free outfit stack.
|
||||||
|
@ -175,11 +175,11 @@ static void rk4_update(Solid* obj, const double dt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a new solid.
|
// Initialize a new solid.
|
||||||
void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos) {
|
void solid_init(Solid* dest, const double mass, const double dir, const Vec2* pos, const Vec2* vel) {
|
||||||
dest->mass = mass;
|
dest->mass = mass;
|
||||||
|
|
||||||
vect_cset(&dest->force, 0., 0.);
|
vect_cset(&dest->force, 0., 0.);
|
||||||
dest->dir = 0.;
|
dest->dir = dir;
|
||||||
|
|
||||||
if(vel == NULL) vectnull(&dest->vel);
|
if(vel == NULL) vectnull(&dest->vel);
|
||||||
else vectcpy(&dest->vel, vel);
|
else vectcpy(&dest->vel, vel);
|
||||||
@ -191,10 +191,10 @@ void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new solid.
|
// Create a new solid.
|
||||||
Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos) {
|
Solid* solid_create(const double mass, const double dir, const Vec2* pos, const Vec2* vel) {
|
||||||
Solid* dyn = MALLOC_L(Solid);
|
Solid* dyn = MALLOC_L(Solid);
|
||||||
assert(dyn != NULL);
|
assert(dyn != NULL);
|
||||||
solid_init(dyn, mass, vel, pos);
|
solid_init(dyn, mass, dir, pos, vel);
|
||||||
return dyn;
|
return dyn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@ struct Solid {
|
|||||||
typedef struct Solid Solid;
|
typedef struct Solid Solid;
|
||||||
|
|
||||||
// Solid manipulation.
|
// Solid manipulation.
|
||||||
void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos);
|
void solid_init(Solid* dest, const double mass, const double dir,
|
||||||
Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos);
|
const Vec2* pos, const Vec2* vel);
|
||||||
|
Solid* solid_create(const double mass, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel);
|
||||||
void solid_free(Solid* src);
|
void solid_free(Solid* src);
|
||||||
|
|
||||||
|
113
src/pilot.c
113
src/pilot.c
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "weapon.h"
|
||||||
#include "pilot.h"
|
#include "pilot.h"
|
||||||
|
|
||||||
// Stack of pilot id's to assure uniqueness.
|
// Stack of pilot id's to assure uniqueness.
|
||||||
@ -13,6 +14,7 @@ static unsigned int pilot_id = 0;
|
|||||||
// Stack of pilots - yes, they come in stacks now.
|
// Stack of pilots - yes, they come in stacks now.
|
||||||
static Pilot** pilot_stack;
|
static Pilot** pilot_stack;
|
||||||
static int pilots = 0;
|
static int pilots = 0;
|
||||||
|
extern Pilot* player;
|
||||||
|
|
||||||
// External.
|
// External.
|
||||||
extern void ai_destroy(Pilot* p); // Ai.
|
extern void ai_destroy(Pilot* p); // Ai.
|
||||||
@ -20,7 +22,8 @@ extern void player_think(Pilot* pilot); // Player.c
|
|||||||
extern void ai_think(Pilot* pilot); // Ai.c
|
extern void ai_think(Pilot* pilot); // Ai.c
|
||||||
// Internal.
|
// 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);
|
void pilot_render(Pilot* pilot);
|
||||||
|
static void pilot_free(Pilot* p);
|
||||||
|
|
||||||
// Pull a pilot out of the pilot_stack based on id.
|
// Pull a pilot out of the pilot_stack based on id.
|
||||||
Pilot* get_pilot(unsigned int id) {
|
Pilot* get_pilot(unsigned int id) {
|
||||||
@ -31,6 +34,7 @@ Pilot* get_pilot(unsigned int id) {
|
|||||||
return pilot_stack[i];
|
return pilot_stack[i];
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
if(id == 0) return player;
|
||||||
// Dichotomical search.
|
// Dichotomical search.
|
||||||
int i, n;
|
int i, n;
|
||||||
for(i = 0, n = pilots/2; n > 0; n /= 2)
|
for(i = 0, n = pilots/2; n > 0; n /= 2)
|
||||||
@ -38,15 +42,40 @@ Pilot* get_pilot(unsigned int id) {
|
|||||||
return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL;
|
return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mkay, this is how we shoot. Listen up.
|
||||||
|
void pilot_shoot(Pilot* p, int secondary) {
|
||||||
|
int i;
|
||||||
|
if(!secondary) {
|
||||||
|
// Primary weapons.
|
||||||
|
if(!p->outfits) return; // No outfits.
|
||||||
|
|
||||||
|
for(i = 0; p->outfits[i].outfit; i++) // Cycle through outfits to find weapons.
|
||||||
|
if(outfit_isWeapon(p->outfits[i].outfit) || // Is a weapon or launch?
|
||||||
|
outfit_isLauncher(p->outfits[i].outfit))
|
||||||
|
// Ready to shoot again.
|
||||||
|
if((SDL_GetTicks()-p->outfits[i].timer) > p->outfits[i].outfit->delay)
|
||||||
|
// Different weapons have different behaviours.
|
||||||
|
switch(p->outfits[i].outfit->type) {
|
||||||
|
case OUTFIT_TYPE_BOLT:
|
||||||
|
weapon_add(p->outfits[i].outfit, p->solid->dir, &p->solid->pos,
|
||||||
|
&p->solid->vel, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG);
|
||||||
|
p->outfits[i].timer = SDL_GetTicks();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render the pilot.
|
// Render the pilot.
|
||||||
static void pilot_render(Pilot* pilot) {
|
void pilot_render(Pilot* p) {
|
||||||
int sprite;
|
int sprite;
|
||||||
gl_texture* texture = pilot->ship->gfx_ship;
|
gl_texture* t = p->ship->gfx_ship;
|
||||||
|
|
||||||
// Get the sprite corresponding to the direction facing.
|
// Get the sprite corresponding to the direction facing.
|
||||||
sprite = (int)(pilot->solid->dir / (2.0*M_PI / (texture->sy * texture->sx)));
|
sprite = (int)(p->solid->dir / (2.0*M_PI / (t->sy * t->sx)));
|
||||||
|
|
||||||
gl_blitSprite(texture, &pilot->solid->pos, sprite % (int)texture->sx, sprite / (int)texture->sy);
|
gl_blitSprite(t, &p->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the pilot.
|
// Update the pilot.
|
||||||
@ -68,17 +97,23 @@ static void pilot_update(Pilot* pilot, const double dt) {
|
|||||||
// ==Init pilot.===========================================
|
// ==Init pilot.===========================================
|
||||||
// ship : Ship pilot is flying.
|
// ship : Ship pilot is flying.
|
||||||
// name : Pilot's name, if NULL, ships name will be used.
|
// name : Pilot's name, if NULL, ships name will be used.
|
||||||
|
// dir : Initial facing direction. (radians)
|
||||||
// vel : Initial velocity.
|
// vel : Initial velocity.
|
||||||
// pos : Initial position.
|
// pos : Initial position.
|
||||||
// flags : Tweaking the pilot.
|
// flags : Tweaking the pilot.
|
||||||
// ========================================================
|
// ========================================================
|
||||||
void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec2* pos, const int flags) {
|
void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Vec2* pos,
|
||||||
|
const Vec2* vel, const int flags) {
|
||||||
|
|
||||||
|
if(flags & PILOT_PLAYER) // Player is ID 0
|
||||||
|
pilot->id = 0;
|
||||||
|
else
|
||||||
pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0.
|
pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0.
|
||||||
|
|
||||||
pilot->ship = ship;
|
pilot->ship = ship;
|
||||||
pilot->name = strdup((name == NULL) ? ship->name : name);
|
pilot->name = strdup((name == NULL) ? ship->name : name);
|
||||||
|
|
||||||
pilot->solid = solid_create(ship->mass, vel, pos);
|
pilot->solid = solid_create(ship->mass, dir, pos, vel);
|
||||||
|
|
||||||
// Max shields armor.
|
// Max shields armor.
|
||||||
pilot->armor = ship->armor;
|
pilot->armor = ship->armor;
|
||||||
@ -88,39 +123,73 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
|
|||||||
// Initially idle.
|
// Initially idle.
|
||||||
pilot->task = NULL;
|
pilot->task = NULL;
|
||||||
|
|
||||||
|
// Outfits.
|
||||||
|
pilot->outfits = NULL;
|
||||||
|
ShipOutfit* so;
|
||||||
|
if(ship->outfit) {
|
||||||
|
int noutfits = 0;
|
||||||
|
for(so = ship->outfit; so; so = so->next) {
|
||||||
|
pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit));
|
||||||
|
pilot->outfits[noutfits].outfit = so->data;
|
||||||
|
pilot->outfits[noutfits].quantity = so->quantity;
|
||||||
|
pilot->outfits[noutfits].timer = 0;
|
||||||
|
noutfits++;
|
||||||
|
}
|
||||||
|
// Sentinal.
|
||||||
|
pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit));
|
||||||
|
pilot->outfits[noutfits].outfit = NULL;
|
||||||
|
pilot->outfits[noutfits].quantity = 0;
|
||||||
|
pilot->outfits[noutfits].timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(flags & PILOT_PLAYER) {
|
if(flags & PILOT_PLAYER) {
|
||||||
pilot->think = player_think; // Players don't need to thing! :P
|
pilot->think = player_think; // Players don't need to thing! :P
|
||||||
|
pilot->render = NULL;
|
||||||
pilot->properties |= PILOT_PLAYER;
|
pilot->properties |= PILOT_PLAYER;
|
||||||
player = pilot;
|
player = pilot;
|
||||||
} else
|
} else {
|
||||||
pilot->think = ai_think;
|
pilot->think = ai_think;
|
||||||
|
|
||||||
pilot->update = pilot_update;
|
pilot->update = pilot_update;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new pilot - Params are same as pilot_init. Return pilot's id.
|
// Create a new pilot - Params are same as pilot_init. Return pilot's id.
|
||||||
unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel, const Vec2* pos, const int flags) {
|
unsigned int pilot_create(Ship* ship, char* name, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel, const int flags) {
|
||||||
Pilot* dyn = MALLOC_L(Pilot);
|
Pilot* dyn = MALLOC_L(Pilot);
|
||||||
if(dyn == NULL) {
|
if(dyn == NULL) {
|
||||||
WARN("Unable to allocate memory.");
|
WARN("Unable to allocate memory.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pilot_init(dyn, ship, name, vel, pos, flags);
|
pilot_init(dyn, ship, name, dir, pos, vel, flags);
|
||||||
|
|
||||||
|
if(flags & PILOT_PLAYER) {
|
||||||
|
// Player.
|
||||||
|
if(!pilot_stack) {
|
||||||
|
pilot_stack = MALLOC_L(Pilot*);
|
||||||
|
pilots = 1;
|
||||||
|
}
|
||||||
|
pilot_stack[0] = dyn;
|
||||||
|
} else {
|
||||||
// Add to the stack.
|
// Add to the stack.
|
||||||
pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*));
|
pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*));
|
||||||
pilot_stack[pilots-1] = dyn;
|
pilot_stack[pilots-1] = dyn;
|
||||||
|
}
|
||||||
return dyn->id;
|
return dyn->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frees and cleans up a pilot.
|
// Frees and cleans up a pilot.
|
||||||
void pilot_destroy(Pilot* p) {
|
static void pilot_free(Pilot* p) {
|
||||||
int i;
|
|
||||||
|
|
||||||
solid_free(p->solid);
|
solid_free(p->solid);
|
||||||
|
free(p->outfits);
|
||||||
free(p->name);
|
free(p->name);
|
||||||
ai_destroy(p);
|
ai_destroy(p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy pilot from stack.
|
||||||
|
void pilot_destroy(Pilot* p) {
|
||||||
|
int i;
|
||||||
for(i = 0; i < pilots; i++)
|
for(i = 0; i < pilots; i++)
|
||||||
if(pilot_stack[i] == p)
|
if(pilot_stack[i] == p)
|
||||||
break;
|
break;
|
||||||
@ -128,27 +197,27 @@ void pilot_destroy(Pilot* p) {
|
|||||||
pilot_stack[i] = pilot_stack[i+1];
|
pilot_stack[i] = pilot_stack[i+1];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
free(p);
|
pilot_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the prisoned pilot!
|
// Free the prisoned pilot!
|
||||||
void pilots_free(void) {
|
void pilots_free(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < pilots; i++) {
|
for(i = 0; i < pilots; i++)
|
||||||
solid_free(pilot_stack[i]->solid);
|
pilot_free(pilot_stack[i]);
|
||||||
free(pilot_stack[i]->name);
|
|
||||||
free(pilot_stack[i]);
|
|
||||||
}
|
|
||||||
free(pilot_stack);
|
free(pilot_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all pilots.
|
// Update all pilots.
|
||||||
void pilots_update(double dt) {
|
void pilots_update(double dt) {
|
||||||
int i;
|
int i;
|
||||||
for(i = pilots-1; i >= 0; i--) {
|
for(i = 0; i < pilots; i++) {
|
||||||
if(pilot_stack[i]->think != NULL)
|
if(pilot_stack[i]->think)
|
||||||
pilot_stack[i]->think(pilot_stack[i]);
|
pilot_stack[i]->think(pilot_stack[i]);
|
||||||
|
if(pilot_stack[i]->update)
|
||||||
pilot_stack[i]->update(pilot_stack[i], dt);
|
pilot_stack[i]->update(pilot_stack[i], dt);
|
||||||
|
if(pilot_stack[i]->render)
|
||||||
|
pilot_stack[i]->render(pilot_stack[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
src/pilot.h
25
src/pilot.h
@ -2,10 +2,17 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
|
#include "outfit.h"
|
||||||
#include "ship.h"
|
#include "ship.h"
|
||||||
|
|
||||||
#define PILOT_PLAYER 1 // Pilot is a player.
|
#define PILOT_PLAYER 1 // Pilot is a player.
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Outfit* outfit; // Associated outfit.
|
||||||
|
unsigned int quantity; // Number of outfits of this type that the pilot has.
|
||||||
|
unsigned int timer; // Used to store last used weapon time.
|
||||||
|
} PilotOutfit;
|
||||||
|
|
||||||
// Primary pilot structure.
|
// Primary pilot structure.
|
||||||
typedef struct Pilot {
|
typedef struct Pilot {
|
||||||
unsigned int id; // Pilots id.
|
unsigned int id; // Pilots id.
|
||||||
@ -18,24 +25,30 @@ typedef struct Pilot {
|
|||||||
// Current health.
|
// Current health.
|
||||||
double armor, shield, energy;
|
double armor, shield, energy;
|
||||||
|
|
||||||
|
void (*think)(struct Pilot*); // AI thinking for the pilot.
|
||||||
void (*update)(struct Pilot*, const double); // Update the pilot.
|
void (*update)(struct Pilot*, const double); // Update the pilot.
|
||||||
|
void (*render)(struct Pilot*); // Rendering the pilot.
|
||||||
|
|
||||||
|
// Outfit management.
|
||||||
|
PilotOutfit* outfits;
|
||||||
|
|
||||||
unsigned int properties; // Used for AI etc.
|
unsigned int properties; // Used for AI etc.
|
||||||
|
|
||||||
// AI.
|
// AI.
|
||||||
void (*think)(struct Pilot*); // Ai thinking for the pilot.
|
|
||||||
Task* task; // Current action.
|
Task* task; // Current action.
|
||||||
} Pilot;
|
} Pilot;
|
||||||
|
|
||||||
extern Pilot* player; // The player.
|
extern Pilot* player; // The player.
|
||||||
Pilot* get_pilot(unsigned int id);
|
Pilot* get_pilot(unsigned int id);
|
||||||
|
|
||||||
// Creation.
|
void pilot_shoot(Pilot* p, int secondary);
|
||||||
void pilot_init(Pilot* dest, Ship* ship, char* name,
|
|
||||||
const Vec2* vel, const Vec2* pos, const int flags);
|
|
||||||
|
|
||||||
unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel,
|
// Creation.
|
||||||
const Vec2* pos, const int flags);
|
void pilot_init(Pilot* dest, Ship* ship, char* name, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel, const int flags);
|
||||||
|
|
||||||
|
unsigned int pilot_create(Ship* ship, char* name, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel, const int flags);
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
void pilot_destroy(Pilot* p);
|
void pilot_destroy(Pilot* p);
|
||||||
|
21
src/player.c
21
src/player.c
@ -16,11 +16,21 @@ typedef struct {
|
|||||||
} Keybind;
|
} Keybind;
|
||||||
static Keybind** player_input; // Contains the players keybindings.
|
static Keybind** player_input; // Contains the players keybindings.
|
||||||
// Name of each keybinding.
|
// Name of each keybinding.
|
||||||
const char* keybindNames[] = { "accel", "left", "right" };
|
const char* keybindNames[] = { "accel", "left", "right", "primary" };
|
||||||
|
|
||||||
Pilot* player = NULL; // extern in pilot.h
|
Pilot* player = NULL; // extern in pilot.h
|
||||||
static double player_turn = 0.; // Turn velocity from input.
|
static double player_turn = 0.; // Turn velocity from input.
|
||||||
static double player_acc = 0.; // Accel velocity from input.
|
static double player_acc = 0.; // Accel velocity from input.
|
||||||
|
static int player_primary = 0; // Player is shooting primary weapon.
|
||||||
|
|
||||||
|
extern void pilot_render(Pilot* pilot); // Extern is in Pilot.*
|
||||||
|
static void player_renderGUI(void);
|
||||||
|
|
||||||
|
// Render the player.
|
||||||
|
void player_render(void) {
|
||||||
|
pilot_render(player);
|
||||||
|
player_renderGUI();
|
||||||
|
}
|
||||||
|
|
||||||
// Used in pilot.c
|
// Used in pilot.c
|
||||||
// Basically uses keyboard input instead of AI input.
|
// Basically uses keyboard input instead of AI input.
|
||||||
@ -29,13 +39,15 @@ void player_think(Pilot* player) {
|
|||||||
if(player_turn)
|
if(player_turn)
|
||||||
player->solid->dir_vel -= player->ship->turn * player_turn;
|
player->solid->dir_vel -= player->ship->turn * player_turn;
|
||||||
|
|
||||||
|
//if(player_primary) pilot_shoot(player, 0);
|
||||||
|
|
||||||
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!
|
// GUI!
|
||||||
// ================
|
// ================
|
||||||
void player_renderGUI(void) {
|
static void player_renderGUI(void) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +111,11 @@ static void input_key(int keynum, double value, int abs) {
|
|||||||
if(abs) player_turn = value;
|
if(abs) player_turn = value;
|
||||||
else player_turn += value;
|
else player_turn += value;
|
||||||
}
|
}
|
||||||
|
// Shoot primary weapon. BOOM BOOM.
|
||||||
|
else if(strcmp(player_input[keynum]->name, "primary")==0) {
|
||||||
|
if(value==KEY_PRESS) player_primary = 1;
|
||||||
|
else if(value == KEY_RELEASE) player_primary = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//Make sure values are sane.
|
//Make sure values are sane.
|
||||||
player_acc = ABS(player_acc);
|
player_acc = ABS(player_acc);
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include "pilot.h"
|
||||||
|
|
||||||
|
extern Pilot* pilot;
|
||||||
|
|
||||||
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_render(void);
|
||||||
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);
|
||||||
|
45
src/ship.c
45
src/ship.c
@ -6,8 +6,6 @@
|
|||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "ship.h"
|
#include "ship.h"
|
||||||
|
|
||||||
#define MAX_PATH_NAME 30 // Maximum size of the path.
|
|
||||||
|
|
||||||
#define XML_NODE_START 1
|
#define XML_NODE_START 1
|
||||||
#define XML_NODE_TEXT 3
|
#define XML_NODE_TEXT 3
|
||||||
|
|
||||||
@ -20,6 +18,8 @@
|
|||||||
static Ship* ship_stack = NULL;
|
static Ship* ship_stack = NULL;
|
||||||
static int ships = 0;
|
static int ships = 0;
|
||||||
|
|
||||||
|
static Ship* ship_parse(xmlNodePtr parent);
|
||||||
|
|
||||||
// Get a ship based on it's name.
|
// Get a ship based on it's name.
|
||||||
Ship* get_ship(const char* name) {
|
Ship* get_ship(const char* name) {
|
||||||
Ship* tmp = ship_stack;
|
Ship* tmp = ship_stack;
|
||||||
@ -33,11 +33,13 @@ Ship* get_ship(const char* name) {
|
|||||||
return tmp+i;
|
return tmp+i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ship* ship_parse(xmlNodePtr parent) {
|
static Ship* ship_parse(xmlNodePtr parent) {
|
||||||
xmlNodePtr cur, node;
|
xmlNodePtr cur, node;
|
||||||
Ship* tmp = CALLOC_L(Ship);
|
Ship* tmp = CALLOC_L(Ship);
|
||||||
|
ShipOutfit* otmp, *ocur;
|
||||||
|
|
||||||
char str[MAX_PATH_NAME] = "\0";
|
char str[PATH_MAX] = "\0";
|
||||||
|
xmlChar* xstr;
|
||||||
|
|
||||||
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
|
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
|
||||||
|
|
||||||
@ -45,18 +47,12 @@ Ship* ship_parse(xmlNodePtr parent) {
|
|||||||
|
|
||||||
while((node = node->next)) { // Load all the data.
|
while((node = node->next)) { // Load all the data.
|
||||||
if(strcmp((char*)node->name, "GFX")==0) {
|
if(strcmp((char*)node->name, "GFX")==0) {
|
||||||
cur = node->children;
|
snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX),
|
||||||
if(strcmp((char*)cur->name, "text")==0) {
|
SHIP_GFX"%s", (char*)node->children->content);
|
||||||
snprintf(str, strlen((char*)cur->content)+sizeof(SHIP_GFX),
|
|
||||||
SHIP_GFX"%s", (char*)cur->content);
|
|
||||||
tmp->gfx_ship = gl_newSprite(str, 6, 6);
|
tmp->gfx_ship = gl_newSprite(str, 6, 6);
|
||||||
}
|
}
|
||||||
}
|
else if(strcmp((char*)node->name, "class")==0)
|
||||||
else if(strcmp((char*)node->name, "class")==0) {
|
tmp->class = atoi((char*)node->children->content);
|
||||||
cur = node->children;
|
|
||||||
if(strcmp((char*)cur->name, "text")==0)
|
|
||||||
tmp->class = atoi((char*)cur->content);
|
|
||||||
}
|
|
||||||
else if(strcmp((char*)node->name, "movement")==0) {
|
else if(strcmp((char*)node->name, "movement")==0) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
while((cur = cur->next)) {
|
while((cur = cur->next)) {
|
||||||
@ -98,7 +94,28 @@ Ship* ship_parse(xmlNodePtr parent) {
|
|||||||
tmp->cap_cargo = atoi((char*)cur->children->content);
|
tmp->cap_cargo = atoi((char*)cur->children->content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strcmp((char*)node->name, "outfits")==0) {
|
||||||
|
cur = node->children;
|
||||||
|
while((cur = cur->next)) {
|
||||||
|
if(strcmp((char*)cur->name, "outfit")==0)
|
||||||
|
otmp = MALLOC_L(ShipOutfit);
|
||||||
|
otmp->data = outfit_get((char*)cur->children->content);
|
||||||
|
xstr = xmlGetProp(cur, (xmlChar*)"qunatity");
|
||||||
|
if(!xstr)
|
||||||
|
WARN("Ship '%s' is missing tag 'quantity for outfit '%s'", tmp->name, otmp->data->name);
|
||||||
|
otmp->quantity = atoi((char*)xstr);
|
||||||
|
free(xstr);
|
||||||
|
otmp->next = NULL;
|
||||||
|
|
||||||
|
if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp;
|
||||||
|
else {
|
||||||
|
while(ocur->next);
|
||||||
|
ocur->next = otmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tmp->thrust *= tmp->mass; // Helps keep number sane.
|
tmp->thrust *= tmp->mass; // Helps keep number sane.
|
||||||
|
|
||||||
#define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name)
|
#define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name)
|
||||||
|
20
src/ship.h
20
src/ship.h
@ -1,10 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "outfit.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
|
||||||
enum ship_class { SHIP_CLASS_NULL, SHIP_CLASS_CIVILIAN };
|
enum ship_class {
|
||||||
|
SHIP_CLASS_NULL,
|
||||||
|
SHIP_CLASS_CIV_LIGHT,
|
||||||
|
SHIP_CLASS_CIV_MEDIUM,
|
||||||
|
SHIP_CLASS_CIV_HEAVY
|
||||||
|
};
|
||||||
typedef enum ship_class ship_class;
|
typedef enum ship_class ship_class;
|
||||||
|
|
||||||
|
// Small wrapper for the outfits.
|
||||||
|
typedef struct ShipOutfit {
|
||||||
|
struct ShipOutfit* next; // Linked list.
|
||||||
|
Outfit* data; // Data itself.
|
||||||
|
int quantity;
|
||||||
|
} ShipOutfit;
|
||||||
|
|
||||||
|
|
||||||
|
// Ship structure.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* name; // Ship name.
|
char* name; // Ship name.
|
||||||
ship_class class; // Ship class.
|
ship_class class; // Ship class.
|
||||||
@ -26,6 +41,9 @@ typedef struct {
|
|||||||
|
|
||||||
// Capacity.
|
// Capacity.
|
||||||
int cap_cargo, cap_weapon;
|
int cap_cargo, cap_weapon;
|
||||||
|
|
||||||
|
// Outfits
|
||||||
|
ShipOutfit* outfit;
|
||||||
} Ship;
|
} Ship;
|
||||||
|
|
||||||
int ships_load(void);
|
int ships_load(void);
|
||||||
|
158
src/weapon.c
Normal file
158
src/weapon.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "outfit.h"
|
||||||
|
#include "physics.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "weapon.h"
|
||||||
|
|
||||||
|
typedef struct Weapon {
|
||||||
|
Solid* solid; // Actually has its own solid. :D
|
||||||
|
|
||||||
|
const Outfit* outfit; // Related outfit that fired.
|
||||||
|
unsigned int timer; // Mainly used to see when the weapon was fired.
|
||||||
|
|
||||||
|
void(*update)(struct Weapon*, const double); // Position update and render.
|
||||||
|
void(*think)(struct Weapon*); // Some missiles need to be inteligent.
|
||||||
|
} Weapon;
|
||||||
|
|
||||||
|
// Behind Pilot layer.
|
||||||
|
static Weapon** backLayer = NULL; // Behind pilots.
|
||||||
|
static int nbackLayer = 0; // Number of elements.
|
||||||
|
static int mbackLayer = 0; // Allocated memory size.
|
||||||
|
// Behind player layer.
|
||||||
|
static Weapon** frontLayer = NULL; // Behind pilots.
|
||||||
|
static int nfrontLayer = 0; // Number of elements.
|
||||||
|
static int mfrontLayer = 0; // Allocated memory size.
|
||||||
|
|
||||||
|
|
||||||
|
static Weapon* weapon_create(const Outfit* outfit, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel);
|
||||||
|
|
||||||
|
static void weapon_render(const Weapon* w);
|
||||||
|
static void weapon_update(Weapon* w, const double dt);
|
||||||
|
static void weapon_free(Weapon* w);
|
||||||
|
|
||||||
|
// Update all weapons in the layer.
|
||||||
|
void weapons_update(const double dt, WeaponLayer layer) {
|
||||||
|
Weapon** wlayer;
|
||||||
|
int nlayer;
|
||||||
|
|
||||||
|
switch(layer) {
|
||||||
|
case WEAPON_LAYER_BG:
|
||||||
|
wlayer = backLayer;
|
||||||
|
nlayer = nbackLayer;
|
||||||
|
break;
|
||||||
|
case WEAPON_LAYER_FG:
|
||||||
|
wlayer = frontLayer;
|
||||||
|
nlayer = nfrontLayer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < nlayer; i++)
|
||||||
|
weapon_update(wlayer[i], dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the weapons.
|
||||||
|
static void weapon_render(const Weapon* w) {
|
||||||
|
int sprite;
|
||||||
|
gl_texture* t = w->outfit->gfx_space;
|
||||||
|
|
||||||
|
// Get the sprite corresponding to the direction facing.
|
||||||
|
sprite = (int)(w->solid->dir / (2.0*M_PI / (t->sy*t->sx)));
|
||||||
|
|
||||||
|
gl_blitSprite(t, &w->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the weapon.
|
||||||
|
static void weapon_update(Weapon* w, const double dt) {
|
||||||
|
if(w->think)
|
||||||
|
(*w->think)(w);
|
||||||
|
(*w->solid->update)(w->solid, dt);
|
||||||
|
|
||||||
|
weapon_render(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel) {
|
||||||
|
Vec2 v;
|
||||||
|
double mass = 1; // Presumer lasers have a mass of 1.
|
||||||
|
Weapon* w = MALLOC_L(Weapon);
|
||||||
|
w->outfit = outfit; // Non-Changeable.
|
||||||
|
w->update = weapon_update;
|
||||||
|
w->think = NULL;
|
||||||
|
|
||||||
|
switch(outfit->type) {
|
||||||
|
case OUTFIT_TYPE_BOLT:
|
||||||
|
vect_cset(&v, VY(*vel)+outfit->speed*cos(dir), VANGLE(*vel)+outfit->speed*sin(dir));
|
||||||
|
w->solid = solid_create(mass, dir, pos, &v);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new weapon.
|
||||||
|
void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, WeaponLayer layer) {
|
||||||
|
if(!outfit_isWeapon(outfit)) {
|
||||||
|
ERR("Trying to create a weapon from a non-Weapon type Outfit");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Weapon* w = weapon_create(outfit, dir, pos, vel);
|
||||||
|
|
||||||
|
// Set the propper layer.
|
||||||
|
Weapon** curLayer = NULL;
|
||||||
|
int* mLayer = NULL;
|
||||||
|
int* nLayer = NULL;
|
||||||
|
switch(layer) {
|
||||||
|
case WEAPON_LAYER_BG:
|
||||||
|
curLayer = backLayer;
|
||||||
|
nLayer = &nbackLayer;
|
||||||
|
mLayer = &mbackLayer;
|
||||||
|
break;
|
||||||
|
case WEAPON_LAYER_FG:
|
||||||
|
curLayer = frontLayer;
|
||||||
|
nLayer = &nfrontLayer;
|
||||||
|
mLayer = &mfrontLayer;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("Invalid WEAPON_LAYER specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(*mLayer > *nLayer) // More memory allocated than what we need.
|
||||||
|
curLayer[(*nLayer)++] = w;
|
||||||
|
else { // Need to allocate more memory.
|
||||||
|
switch(layer) {
|
||||||
|
case WEAPON_LAYER_BG:
|
||||||
|
curLayer = backLayer = realloc(curLayer, (++(*mLayer))*sizeof(Weapon));
|
||||||
|
break;
|
||||||
|
case WEAPON_LAYER_FG:
|
||||||
|
curLayer = frontLayer = realloc(curLayer, (++(*mLayer))*sizeof(Weapon*));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curLayer[(*nLayer)++] = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the weapon.
|
||||||
|
static void weapon_free(Weapon* w) {
|
||||||
|
solid_free(w->solid);
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all the weapons, do not free the layers.
|
||||||
|
void weapon_clear(void) {
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < nbackLayer; i++)
|
||||||
|
weapon_free(backLayer[i]);
|
||||||
|
nbackLayer = 0;
|
||||||
|
backLayer = NULL;
|
||||||
|
for(i = 0; i < nfrontLayer; i++)
|
||||||
|
weapon_free(frontLayer[i]);
|
||||||
|
nfrontLayer = 0;
|
||||||
|
frontLayer = NULL;
|
||||||
|
}
|
||||||
|
|
11
src/weapon.h
Normal file
11
src/weapon.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "outfit.h"
|
||||||
|
#include "physics.h"
|
||||||
|
|
||||||
|
typedef enum { WEAPON_LAYER_BG, WEAPON_LAYER_FG } WeaponLayer;
|
||||||
|
|
||||||
|
void weapon_add(const Outfit* outfit, const double dir,
|
||||||
|
const Vec2* pos, const Vec2* vel, WeaponLayer layer);
|
||||||
|
|
||||||
|
void weapons_update(const double dt, WeaponLayer layer);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user