[Add] Rudimentary shooting. This needs some work.

[Add] Layers should be working properly.
This commit is contained in:
Allanis 2013-02-05 16:50:56 +00:00
parent b13ecc66bb
commit 998a1bf68b
17 changed files with 496 additions and 103 deletions

1
.gitignore vendored
View File

@ -26,5 +26,6 @@
*bin/Lephisto
*bin/data
*pack
*core

View File

@ -48,5 +48,5 @@ data: pack $(DATAFILES) ../src/pack.c
clean:
@echo -e "\tRemoving data.."
rm -rf $(OBJS) $(APPNAME) $(DATA) pack
rm -rf $(OBJS) $(APPNAME) $(DATA) pack core

View File

@ -9,7 +9,9 @@
<specific type = "1">
<sound>laser.wav</sound>
<gfx>lasergreen.png</gfx>
<speed>450</speed>
<delay>500</delay>
<speed>550</speed>
<range>300</range>
<accuracy>30</accuracy>
<damage>
<armor>20</armor>

View File

@ -89,6 +89,7 @@ static double pilot_turn = 0.;
// Destroy the AI part of the pilot.
void ai_destroy(Pilot* p) {
if(p->task)
ai_freetask(p->task);
}

View File

@ -18,9 +18,11 @@
#include "rng.h"
#include "ai.h"
#include "outfit.h"
#include "pack.h"
#include "weapon.h"
#include "pilot.h"
#define WINDOW_CAPTION "Lephisto"
#define APPNAME "Lephisto"
#define CONF_FILE "conf"
#define MINIMUM_FPS 0.5
@ -31,14 +33,13 @@ static unsigned int time = 0; // Calculate FPS and movement.
#define DATA_DEF "data"
char* data = NULL;
static int show_fps = 1; // Default - True.
static int max_fps = 0;
// Prototypes.
static void print_usage(char** argv);
static void display_fps(const double dt);
// Update.
static void update_all(void);
@ -47,7 +48,7 @@ static void print_usage(char** argv) {
LOG("USAGE: %s [OPTION]", argv[0]);
LOG("Options are:");
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-j n, --joystick n - Use joystick (n)");
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 i;
// Print the version.
LOG(""APPNAME" v%d.%d.%d", VMAJOR, VMINOR, VREV);
// Initialize SDL for possible warnings.
SDL_Init(0);
// Default values..
@ -74,6 +79,7 @@ int main(int argc, char** argv) {
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_w, 0);
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_a, 0);
input_setKeybind("right", KEYBIND_KEYBOARD, SDLK_d, 0);
input_setKeybind("primary", KEYBIND_KEYBOARD, SDLK_SPACE, 0);
// Use Lua to parse configuration file.
lua_State* L = luaL_newstate();
@ -96,7 +102,7 @@ int main(int argc, char** argv) {
lua_getglobal(L, "fps");
if(lua_isnumber(L, -1))
show_fps = (int)lua_tonumber(L, -1);
max_fps = (int)lua_tonumber(L, -1);
// Joystick.
lua_getglobal(L, "joystick");
@ -153,7 +159,7 @@ int main(int argc, char** argv) {
// Parse arguments.
static struct option long_options[] = {
{ "fullscreen", no_argument, 0, 'f' },
{ "fps", optional_argument, 0, 'F' },
{ "fps", required_argument, 0, 'F' },
{ "data", required_argument, 0, 'd' },
{ "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 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) {
case 'f':
gl_screen.fullscreen = 1;
break;
case 'F':
if(optarg != NULL) show_fps = atoi(optarg);
else show_fps = !show_fps;
else max_fps = !show_fps;
break;
case 'd':
data = strdup(optarg);
@ -195,11 +201,21 @@ int main(int argc, char** argv) {
if(gl_init()) {
// Initializes video output.
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);
}
// Window.
SDL_WM_SetCaption(WINDOW_CAPTION, NULL);
SDL_WM_SetCaption(APPNAME, NULL);
// Input.
if(indjoystick >= 0 || namjoystick != NULL) {
@ -225,11 +241,11 @@ int main(int argc, char** argv) {
space_load();
// 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);
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();
@ -268,19 +284,23 @@ int main(int argc, char** argv) {
//
// BG | Stars and planets.
// | Background particles.
// | Back layer weapons.
// X
// N | NPC ships.
// | Normal layer particles (above ships).
// | Front layer weapons.
// X
// FG | Player.
// | Foreground particles.
// | Text and GUI.
// ========================================================
static double fps_dt = 1.;
static void update_all(void) {
// dt in us.
double dt = (double)(SDL_GetTicks() - time) / 1000.;
time = SDL_GetTicks();
// TODO: This could use some work.
if(dt > MINIMUM_FPS) {
Vec2 pos;
vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
@ -288,20 +308,27 @@ static void update_all(void) {
SDL_GL_SwapBuffers();
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);
// --
// BG.
space_render(dt);
planets_render();
// N
weapons_update(dt, WEAPON_LAYER_BG);
// N.
pilots_update(dt);
weapons_update(dt, WEAPON_LAYER_FG);
// FG.
player_renderGUI();
player_render();
display_fps(dt);
// --
SDL_GL_SwapBuffers();
}
@ -310,7 +337,6 @@ static void update_all(void) {
// Spit this out on display.
static double fps = 0.;
static double fps_cur = 0.;
static double fps_dt = 1.;
static void display_fps(const double dt) {
fps_dt += dt;
fps_cur += 1.;

View File

@ -4,6 +4,7 @@
#include "main.h"
#include "log.h"
#include "pack.h"
#include "outfit.h"
#define XML_NODE_START 1
@ -31,8 +32,27 @@ Outfit* outfit_get(const char* name) {
}
// Return 1 if outfit is a weapon.
int outfit_isweapon(const Outfit* o) {
return (o->type > OUTFIT_TYPE_NULL && o->type <= OUTFIT_TYPE_MISSILE_SWARM_SMART);
int outfit_isWeapon(const Outfit* o) {
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[] = {
@ -40,10 +60,15 @@ const char* outfit_typename[] = {
"Bolt Cannon",
"Beam Cannon",
"Dumb Missile",
"Dumb Missile Ammunition",
"Seeker Missile",
"Smart Missile",
"Seeker Missile Ammunition",
"Smart Seeker Missile",
"Smart Seeker Missile Ammunition",
"Swam Missile",
"Smart Swarm Missile"
"Swarm Missile Ammunition Pack",
"Smart Swarm Missile",
"Smart Swarm Missile Ammunition Pack"
};
const char* outfit_getType(const Outfit* o) {
@ -61,6 +86,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
// Load all the things.
if(strcmp((char*)node->name, "speed")==0)
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)
tmp->accuracy = atof((char*)node->children->content)*M_PI/180.; // to rad.
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)
MELEMENT(tmp->speed, "speed");
MELEMENT(tmp->accuracy, "tech");
MELEMENT(tmp->delay, "delay");
MELEMENT(tmp->damage_armor, "armor' from element 'damage");
MELEMENT(tmp->damage_shield, "shield' from element 'damage");
#undef MELEMENT
@ -181,7 +209,7 @@ int outfit_load(void) {
void outfit_free(void) {
int 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);
free(outfit_stack[i].name);
}

View File

@ -1,42 +1,70 @@
#pragma once
#include "opengl.h"
#define OUTFIT_PROP_WEAP_PRIMARY (1<<0)
#define OUTFIT_PROP_WEAP_SECONDARY (1<<1)
// Outfit types.
typedef enum {
OUTFIT_TYPE_NULL,
OUTFIT_TYPE_NULL = 0,
OUTFIT_TYPE_BOLT,
OUTFIT_TYPE_BEAM,
OUTFIT_TYPE_MISSILE_DUMB,
OUTFIT_TYPE_MISSILE_DUMB_AMMO,
OUTFIT_TYPE_MISSILE_SEEK,
OUTFIT_TYPE_MISSILE_SEEK_AMMO,
OUTFIT_TYPE_MISSILE_SEEK_SMART,
OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,
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;
// An outfit depends a lot on the type.
typedef struct {
char* name;
// General specs.
int max;
int tech;
int mass;
gl_texture gfx_store;
gl_texture gfx_store; // Store graphic.
int properties; // Properties stored bitwise.
// Type dependant.
OutfitType type;
union {
struct {
double speed;
double accuracy;
double damage_armor, damage_shield;
struct { // Beam/Bolt.
unsigned int delay; // Delay between shots.
double speed; // Speed of shot. (not applicable to beam.
double range;
double accuracy; // Desviation accuracy.
double damage_armor, damage_shield; // Damage.
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_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);
// Load/free outfit stack.

View File

@ -175,11 +175,11 @@ static void rk4_update(Solid* obj, const double dt) {
}
// 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;
vect_cset(&dest->force, 0., 0.);
dest->dir = 0.;
dest->dir = dir;
if(vel == NULL) vectnull(&dest->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.
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);
assert(dyn != NULL);
solid_init(dyn, mass, vel, pos);
solid_init(dyn, mass, dir, pos, vel);
return dyn;
}

View File

@ -37,7 +37,9 @@ struct Solid {
typedef struct Solid Solid;
// Solid manipulation.
void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos);
Solid* solid_create(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);
Solid* solid_create(const double mass, const double dir,
const Vec2* pos, const Vec2* vel);
void solid_free(Solid* src);

View File

@ -5,6 +5,7 @@
#include "main.h"
#include "log.h"
#include "weapon.h"
#include "pilot.h"
// 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.
static Pilot** pilot_stack;
static int pilots = 0;
extern Pilot* player;
// External.
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
// Internal.
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.
Pilot* get_pilot(unsigned int id) {
@ -31,6 +34,7 @@ Pilot* get_pilot(unsigned int id) {
return pilot_stack[i];
return NULL;
#endif
if(id == 0) return player;
// Dichotomical search.
int i, n;
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;
}
// 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.
static void pilot_render(Pilot* pilot) {
void pilot_render(Pilot* p) {
int sprite;
gl_texture* texture = pilot->ship->gfx_ship;
gl_texture* t = p->ship->gfx_ship;
// 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.
@ -68,17 +97,23 @@ static void pilot_update(Pilot* pilot, const double dt) {
// ==Init pilot.===========================================
// ship : Ship pilot is flying.
// name : Pilot's name, if NULL, ships name will be used.
// dir : Initial facing direction. (radians)
// vel : Initial velocity.
// pos : Initial position.
// 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->ship = ship;
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.
pilot->armor = ship->armor;
@ -88,39 +123,73 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
// Initially idle.
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) {
pilot->think = player_think; // Players don't need to thing! :P
pilot->render = NULL;
pilot->properties |= PILOT_PLAYER;
player = pilot;
} else
} else {
pilot->think = ai_think;
pilot->update = pilot_update;
}
}
// 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);
if(dyn == NULL) {
WARN("Unable to allocate memory.");
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.
pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*));
pilot_stack[pilots-1] = dyn;
}
return dyn->id;
}
// Frees and cleans up a pilot.
void pilot_destroy(Pilot* p) {
int i;
static void pilot_free(Pilot* p) {
solid_free(p->solid);
free(p->outfits);
free(p->name);
ai_destroy(p);
free(p);
}
// Destroy pilot from stack.
void pilot_destroy(Pilot* p) {
int i;
for(i = 0; i < pilots; i++)
if(pilot_stack[i] == p)
break;
@ -128,27 +197,27 @@ void pilot_destroy(Pilot* p) {
pilot_stack[i] = pilot_stack[i+1];
i++;
}
free(p);
pilot_free(p);
}
// Free the prisoned pilot!
void pilots_free(void) {
int i;
for(i = 0; i < pilots; i++) {
solid_free(pilot_stack[i]->solid);
free(pilot_stack[i]->name);
free(pilot_stack[i]);
}
for(i = 0; i < pilots; i++)
pilot_free(pilot_stack[i]);
free(pilot_stack);
}
// Update all pilots.
void pilots_update(double dt) {
int i;
for(i = pilots-1; i >= 0; i--) {
if(pilot_stack[i]->think != NULL)
for(i = 0; i < pilots; i++) {
if(pilot_stack[i]->think)
pilot_stack[i]->think(pilot_stack[i]);
if(pilot_stack[i]->update)
pilot_stack[i]->update(pilot_stack[i], dt);
if(pilot_stack[i]->render)
pilot_stack[i]->render(pilot_stack[i]);
}
}

View File

@ -2,10 +2,17 @@
#include "main.h"
#include "physics.h"
#include "ai.h"
#include "outfit.h"
#include "ship.h"
#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.
typedef struct Pilot {
unsigned int id; // Pilots id.
@ -18,24 +25,30 @@ typedef struct Pilot {
// Current health.
double armor, shield, energy;
void (*think)(struct Pilot*); // AI thinking for 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.
// AI.
void (*think)(struct Pilot*); // Ai thinking for the pilot.
Task* task; // Current action.
} Pilot;
extern Pilot* player; // The player.
Pilot* get_pilot(unsigned int id);
// Creation.
void pilot_init(Pilot* dest, Ship* ship, char* name,
const Vec2* vel, const Vec2* pos, const int flags);
void pilot_shoot(Pilot* p, int secondary);
unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel,
const Vec2* pos, const int flags);
// Creation.
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.
void pilot_destroy(Pilot* p);

View File

@ -16,11 +16,21 @@ typedef struct {
} Keybind;
static Keybind** player_input; // Contains the players keybindings.
// Name of each keybinding.
const char* keybindNames[] = { "accel", "left", "right" };
const char* keybindNames[] = { "accel", "left", "right", "primary" };
Pilot* player = NULL; // extern in pilot.h
static double player_turn = 0.; // Turn 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
// Basically uses keyboard input instead of AI input.
@ -29,13 +39,15 @@ void player_think(Pilot* player) {
if(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);
}
// ================
// 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;
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.
player_acc = ABS(player_acc);

View File

@ -1,10 +1,12 @@
#pragma once
#include <SDL.h>
#include "pilot.h"
extern Pilot* pilot;
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
// GUI.
void player_renderGUI(void);
void player_render(void);
int player_isFlag(unsigned int flag);
void player_setFlag(unsigned int flag);

View File

@ -6,8 +6,6 @@
#include "pack.h"
#include "ship.h"
#define MAX_PATH_NAME 30 // Maximum size of the path.
#define XML_NODE_START 1
#define XML_NODE_TEXT 3
@ -20,6 +18,8 @@
static Ship* ship_stack = NULL;
static int ships = 0;
static Ship* ship_parse(xmlNodePtr parent);
// Get a ship based on it's name.
Ship* get_ship(const char* name) {
Ship* tmp = ship_stack;
@ -33,11 +33,13 @@ Ship* get_ship(const char* name) {
return tmp+i;
}
Ship* ship_parse(xmlNodePtr parent) {
static Ship* ship_parse(xmlNodePtr parent) {
xmlNodePtr cur, node;
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");
@ -45,18 +47,12 @@ Ship* ship_parse(xmlNodePtr parent) {
while((node = node->next)) { // Load all the data.
if(strcmp((char*)node->name, "GFX")==0) {
cur = node->children;
if(strcmp((char*)cur->name, "text")==0) {
snprintf(str, strlen((char*)cur->content)+sizeof(SHIP_GFX),
SHIP_GFX"%s", (char*)cur->content);
snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX),
SHIP_GFX"%s", (char*)node->children->content);
tmp->gfx_ship = gl_newSprite(str, 6, 6);
}
}
else if(strcmp((char*)node->name, "class")==0) {
cur = node->children;
if(strcmp((char*)cur->name, "text")==0)
tmp->class = atoi((char*)cur->content);
}
else if(strcmp((char*)node->name, "class")==0)
tmp->class = atoi((char*)node->children->content);
else if(strcmp((char*)node->name, "movement")==0) {
cur = node->children;
while((cur = cur->next)) {
@ -98,7 +94,28 @@ Ship* ship_parse(xmlNodePtr parent) {
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.
#define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name)

View File

@ -1,10 +1,25 @@
#pragma once
#include "main.h"
#include "outfit.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;
// Small wrapper for the outfits.
typedef struct ShipOutfit {
struct ShipOutfit* next; // Linked list.
Outfit* data; // Data itself.
int quantity;
} ShipOutfit;
// Ship structure.
typedef struct {
char* name; // Ship name.
ship_class class; // Ship class.
@ -26,6 +41,9 @@ typedef struct {
// Capacity.
int cap_cargo, cap_weapon;
// Outfits
ShipOutfit* outfit;
} Ship;
int ships_load(void);

158
src/weapon.c Normal file
View 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
View 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);