[Add] Initial commit of Lephisto.

This commit is contained in:
Allanis 2013-01-30 22:22:30 +00:00
parent 227242c447
commit cc47d41137
14 changed files with 808 additions and 0 deletions

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# Object files
*.o
# Libraries
*.lib
*.a
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
*.bin
# Executables
*.exe
*.out
*.app
# Crap.
*.log
*.swp
*.txt
*.tsv
*.pdf
*bin/Lephisto

26
bin/Makefile Normal file
View File

@ -0,0 +1,26 @@
DEBUG = 1
APPNAME = Lephisto
OBJ := ../src/main.o \
../src/physics.o \
../src/opengl.o \
../src/ship.o \
../src/pilot.o
CFLAGS = -Wall `sdl-config --cflags`
ifdef DEBUG
CFLAGS += -g3 -DDEBUG
else
CFLAGS += -O2
endif
LDFLAGS = -lm `sdl-config --libs` -lSDL_image -lGL
%.o: ../src/%.c
gcc -c $(CFLAGS) -o $@ $<
all: $(OBJ)
gcc $(LDFLAGS) -o $(APPNAME) $(OBJ)
clean:
rm -rf $(OBJ) $(APPNAME)

BIN
gfx/ship.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

6
src/def.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#define MALLOC_L(type)(malloc(sizeof(type)))
typedef float FP;

14
src/log.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <stdio.h>
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
#define WARN(str, args...)(fprintf(stderr, "[%d] "str"\n", 0, ## args))
#ifdef DEBUG
# undef DEBUG
# define DEBUG(str, args...) LOG(str, ## args)
# define DEBUGGING
#else
# define DEBUG(str, args...) do {;} while(0)
#endif

View File

@ -1,2 +1,95 @@
#include <SDL.h>
#include <stdlib.h>
#include <math.h>
#include "def.h"
#include "log.h"
#include "log.h"
#include "physics.h"
#include "opengl.h"
#include "ship.h"
#include "pilot.h"
int main(int argc, const char** argv) {
int quit = 0;
SDL_Event event;
gl_screen.w = 800;
gl_screen.h = 640;
gl_screen.fullscreen = 0;
gl_init();
gl_texture* tex;
if((tex = gl_newSprite("../gfx/ship.png", 6, 6)) == NULL) {
WARN("Unable to load image");
return -1;
}
Ship* ship = MALLOC_L(Ship);
ship->gfx_ship = tex;
ship->mass = 1;
ship->class = SHIP_CLASS_CIVILIAN;
Pilot* player = pilot_create(ship, "player", NULL, NULL, PILOT_PLAYER);
gl_bindCamera(&player->solid->pos);
int tflag = 0;
unsigned int time = SDL_GetTicks();
FP dt;
while(!quit) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_q:
quit = 1;
break;
case SDLK_a:
tflag ^= 1;
break;
case SDLK_d:
tflag ^=2;
case SDLK_w:
tflag ^= 8;
break;
default:
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_a:
tflag ^= 1;
break;
case SDLK_d:
tflag ^= 2;
break;
case SDLK_w:
tflag ^= 8;
break;
default:
break;
}
break;
}
}
dt = (FP)(SDL_GetTicks() - time) / 1000.0;
if(tflag & 1) player->solid->dir += 200.0 / 180.0*M_PI*dt;
if(tflag & 2) player->solid->dir -= 200.0 / 180.0*M_PI*dt;
if(tflag & 8) player->solid->force = 340;
else player->solid->force = 0;
glClear(GL_COLOR_BUFFER_BIT);
player->update(player, dt);
SDL_GL_SwapBuffers();
time = SDL_GetTicks();
SDL_Delay(5);
}
pilot_free(player);
free(ship);
gl_free(tex);
gl_exit();
return 0;
}

302
src/opengl.c Normal file
View File

@ -0,0 +1,302 @@
#include <SDL.h>
#include <SDL_image.h>
#include "def.h"
#include "log.h"
#include "opengl.h"
// Recommended for compatibility bullshit.
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
# define RMASK 0xff000000
# define GMASK 0x00ff0000
# define BMASK 0x0000ff00
# define AMASK 0x000000ff
#else
# define RMASK 0x000000ff
# define GMASK 0x0000ff00
# define BMASK 0x00ff0000
# define AMASK 0xff000000
#endif
#define RGBMASK RMASK,GMASK,BMASK,AMASK
// The screen info, gives data of current opengl settings.
gl_info gl_screen;
// Our precious camera.
Vec2* gl_camera;
static int flip_surface(SDL_Surface* surface);
// Flips the surface vertically. Return 0 on success.
static int flip_surface(SDL_Surface* surface) {
// Flip the image.
Uint8* rowhi, *rowlo, *tmpbuf;
int y;
tmpbuf = (Uint8*)malloc(surface->pitch);
if(tmpbuf == NULL) {
WARN("Out of memory");
return -1;
}
rowhi = (Uint8*)surface->pixels;
rowlo = rowhi + (surface->h * surface->pitch) - surface->pitch;
for(y = 0; y < surface->h / 2; ++y) {
memcpy(tmpbuf, rowhi, surface->pitch);
memcpy(rowhi, rowlo, surface->pitch);
memcpy(rowlo, tmpbuf, surface->pitch);
rowhi += surface->pitch;
rowlo -= surface->pitch;
}
free(tmpbuf);
// Might be obvious, but I'm done flipping.
return 0;
}
// Load the image directly as an opengl texture.
gl_texture* gl_newImage(const char* path) {
SDL_Surface* tmp, *surface;
Uint32 saved_flags;
Uint8 saved_alpha;
int potw, poth;
tmp = IMG_Load(path); // Load the surface.
if(tmp == 0) {
WARN("'%s' could not be opened: %s", path, IMG_GetError());
return 0;
}
surface = SDL_DisplayFormatAlpha(tmp); // Set the surface to what we use.
if(surface == 0) {
WARN("Error converting image to screen format: %s", SDL_GetError());
return 0;
}
SDL_FreeSurface(tmp); // Free the temp surface.
flip_surface(surface);
// Set up the texture defaults.
gl_texture* texture = MALLOC_L(gl_texture);
texture->w = (FP)surface->w;
texture->h = (FP)surface->h;
texture->sx = 1.0;
texture->sy = 1.0;
// Ensure size is power of two.
potw = surface->w;
if((potw &(potw-1)) != 0) {
potw = 1;
while(potw < surface->w)
potw <<= 1;
}
texture->rw = potw;
poth = surface->h;
if((poth &(poth-1)) != 0) {
poth = 1;
while(poth < surface->h)
poth <<= 1;
}
texture->rh = poth;
if(surface->w != potw || surface->h != poth) {
// Size isn't original.
SDL_Rect rtemp;
rtemp.x = rtemp.y = 0;
rtemp.w = surface->w;
rtemp.h = surface->h;
// Save alpha.
saved_flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
saved_alpha = surface->format->alpha;
if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
SDL_SetAlpha(surface, 0, 0);
// Create the temp POT surface.
tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
texture->rw, texture->rh, surface->format->BytesPerPixel*8, RGBMASK);
if(tmp == NULL) {
WARN("Unable to create POT surface %s", SDL_GetError());
return 0;
}
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
WARN("Unable to fill rect: %s", SDL_GetError());
return 0;
}
SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
SDL_FreeSurface(surface);
surface = tmp;
// Set saved alpha.
if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
SDL_SetAlpha(surface, saved_flags, saved_alpha);
}
glGenTextures(1, &texture->texture); // Create the texure.
glBindTexture(GL_TEXTURE_2D, texture->texture); // Load the texture.
// Filtering, LINEAR is better for scaling, nearest looks nicer, LINEAR
// also seems to create a bit of artifacts around the edges.
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
SDL_LockSurface(surface);
glTexImage2D(GL_TEXTURE_2D, 0, surface->format->BytesPerPixel,
surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
return texture;
}
// Load the texture immediately, but also set is as a sprite.
gl_texture* gl_newSprite(const char* path, const int sx, const int sy) {
gl_texture* texture;
if((texture = gl_newImage(path)) == NULL)
return NULL;
texture->sx = (FP)sx;
texture->sy = (FP)sy;
texture->sw = texture->w/texture->sx;
texture->sh = texture->h/texture->sy;
return texture;
}
// Free the texture.
void gl_free(gl_texture* texture) {
glDeleteTextures(1, &texture->texture);
free(texture);
}
// Blit the sprite at given position.
void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
glMatrixMode(GL_TEXTURE);
glTranslatef(sprite->sw * (FP)(sx)/sprite->rw,
sprite->sh*(sprite->sy-(FP)sy-1)/sprite->rh, 0.0f);
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Projection translation matrix.
glTranslatef(gl_camera->x - pos->x - sprite->sw / 2.0,
gl_camera->y - pos->y - sprite->sh/2.0, 0.0f);
// Actual blitting....
glBindTexture(GL_TEXTURE_2D, sprite->texture);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(sprite->sw/sprite->rw, 0.0f);
glVertex2f(sprite->sw, 0.0f);
glTexCoord2f(0.0f, sprite->sh/sprite->rh);
glVertex2f(0.0f, sprite->sh);
glTexCoord2f(sprite->sw/sprite->rw, sprite->sh/sprite->rh);
glVertex2f(sprite->sw, sprite->sh);
glEnd();
glPopMatrix(); // Projection translation matrix.
glMatrixMode(GL_TEXTURE);
glPopMatrix(); // Sprite translation matrix.
}
// Just straight out blit the thing at position.
void gl_blit(gl_texture* texture, Vec2* pos) {
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Set up translation matrix.
glTranslatef(pos->x, pos->y, 0);
// Actual blitting..
glBindTexture(GL_TEXTURE_2D, texture->texture);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(texture->w/texture->rw, 0.0f);
glVertex2f(texture->w, 0.0f);
glTexCoord2f(0.0f, texture->h/texture->rh);
glVertex2f(0.0f, texture->h);
glTexCoord2f(texture->w/texture->rw, texture->h/texture->rh);
glVertex2f(texture->w, texture->h);
glEnd();
glPopMatrix(); // Pop the translation matrix.
}
// Bind our precious camera to a vector.
void gl_bindCamera(Vec2* pos) {
gl_camera = pos;
}
// Initialize SDL/OpenGL etc.
int gl_init(void) {
int depth;
int flags = SDL_OPENGL;
// Initializes video.
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
WARN("Unable to initialize SDL: %s", SDL_GetError());
return -1;
}
// FFUUUU Ugly cursor thing.
SDL_ShowCursor(SDL_DISABLE);
flags |= SDL_FULLSCREEN* gl_screen.fullscreen;
depth = SDL_VideoModeOK(gl_screen.w, gl_screen.h, gl_screen.depth, flags); // Test set up.
if(depth != gl_screen.depth)
WARN("Depth: %d bpp unavailable, will use %d bpp", gl_screen.depth, depth);
gl_screen.depth = depth;
// Actually creating the screen.
if(SDL_SetVideoMode(gl_screen.w, gl_screen.h, gl_screen.depth, flags) == NULL) {
WARN("Unable to create OpenGL window: %s", SDL_GetError());
SDL_Quit();
return -1;
}
// Grab some info.
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &gl_screen.r);
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &gl_screen.g);
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &gl_screen.b);
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &gl_screen.a);
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &gl_screen.doublebuf);
gl_screen.depth = gl_screen.r + gl_screen.g + gl_screen.b + gl_screen.a;
// Debug heaven.
DEBUG("OpenGL Window Created: %dx%d@%dbpp %s", gl_screen.w, gl_screen.h, gl_screen.depth,
gl_screen.fullscreen ? "fullscreen" : "window");
DEBUG("r: %d, g: %d, b: %d, a: %d, doublebuffer: %s", gl_screen.r, gl_screen.g, gl_screen.b, gl_screen.a,
gl_screen.doublebuf ? "yes" : "no");
DEBUG("Renderer: %s", glGetString(GL_RENDERER));
// Some openGL options.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_DEPTH_TEST); // Set for doing 2D shidazles.
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-gl_screen.w/2, // Left edge.
gl_screen.w/2, // Right edge.
-gl_screen.h/2, // Bottom edge.
gl_screen.h/2, // Top edge.
-1.0f, // Near.
1.0f); // Far.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Alpha.
glEnable(GL_BLEND);
glClear(GL_COLOR_BUFFER_BIT);
SDL_WM_SetCaption(WINDOW_CAPTION, NULL);
return 0;
}
// Clean up our mess.
void gl_exit(void) {
SDL_ShowCursor(SDL_ENABLE);
SDL_Quit();
}

40
src/opengl.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "SDL_opengl.h"
#include "physics.h"
#define WINDOW_CAPTION "Lephisto"
// Info about opengl screen.
typedef struct {
int w, h; // Window dimensions.
int depth; // Depth in bpp.
int fullscreen; // 1 = fullscreen, 0 = windowed.
int r, g, b, a; // Framebuffer values in bits.
int doublebuf; // Double buffer.
} gl_info;
extern gl_info gl_screen; // Local structure set with gl_init etc.
// Spritesheet info.
typedef struct {
FP w, h; // Real size of the image (excluding POT buffer.
FP rw, rh; // Size of POT surface.
FP sx, sy; // Number of sprites on x and y axes.
FP sw, sh; // Size of each sprite.
GLuint texture; // The opengl texture itself.
} gl_texture;
// gl_texute loading/freeing.
gl_texture* gl_newImage(const char* path);
gl_texture* gl_newSprite(const char* path, const int sx, const int sy);
void gl_free(gl_texture* texture);
// Rendering.
void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy);
void gl_blit(gl_texture* texture, Vec2* pos);
void gl_bindCamera(Vec2* pos);
// Initialize/cleanup.
int gl_init(void);
void gl_exit(void);

134
src/physics.c Normal file
View File

@ -0,0 +1,134 @@
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "physics.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
// Pretty efficient, no need for sine table!!
#define SIN(dir)(sinf(dir))
#define COS(dir)(cosf(dir))
// ==Update method.========================================
// d^2 x(t) / d t^2 = a, a = constant (acceleration)
// x'(0) = v, x(0) = p
//
// d x(t) / d t = a*t + v, v = constant (initial velocity)
// x(t) = a/2*t + v*t + p, p = constant (initial position)
//
// Since dt isn't actually differential this gives us an
// error, so watch out with big values for dt.
// ========================================================
static void simple_update(Solid* obj, const FP dt) {
if(obj->force) {
Vec2 acc;
acc.x = obj->force / obj->mass * COS(obj->dir);
acc.y = obj->force / obj->mass * SIN(obj->dir);
obj->pos.x += acc.x * dt;
obj->vel.y += acc.y * dt;
obj->pos.x += obj->vel.x * dt + 0.5 * acc.x / obj->mass * dt * dt;
obj->pos.y += obj->vel.y * dt + 0.5 * acc.y / obj->mass * dt * dt;
} else {
obj->pos.x += obj->vel.x * dt;
obj->pos.y += obj->vel.y * dt;
}
}
// ==Runge-Kutta 4th method.===============================
// d^2 x(t) / d t^2 = a, a = constant(acceleration)
// x'(0) = v, x(0) = p
// x'' = f(t, x, x') = (x', a)
//
// x_ {n+1} = x_n + h/6 (k1 + 2*k2 + 3*k3 + k4)
// h = (b-a)/2
// k1 = f(t_n, X_n), X_n = (x_n, x'_n)
// k2 = f(t_n + h/2, X_n + h/2*k1)
// k3 = f(t_n + h/2, X_n + h/2*k2)
// k4 = f(t_n + h, X_n + h*k3)
//
// x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a)
// ========================================================
#define RK4_N 4
static void rk4_update(Solid* obj, const FP dt) {
FP h = dt / RK4_N; // Step.
if(obj->force) { // Force applied on object.
int i;
Vec2 initial, tmp;
Vec2 acc;
acc.x = obj->force / obj->mass * COS(obj->dir);
acc.y = obj->force / obj->mass * SIN(obj->dir);
for(i = 0; i < RK4_N; i++) {
// X component.
tmp.x = initial.x = obj->vel.x;
tmp.x += 2*initial.x + h*tmp.x;
tmp.x += 2*initial.x + h*tmp.x;
tmp.x += initial.x + h*tmp.x;
tmp.x *= h/6;
obj->pos.x += tmp.x;
obj->vel.x += acc.x*h;
// Y component.
tmp.y = initial.y = obj->vel.y;
tmp.y += 2*(initial.y + h/2*tmp.y);
tmp.y += 2*(initial.y + h/2*tmp.y);
tmp.y += initial.y + h*tmp.y;
tmp.y *= h/6;
obj->pos.y += tmp.y;
obj->pos.y += acc.y*h;
}
} else {
obj->pos.x += dt*obj->vel.x;
obj->pos.y += dt*obj->vel.y;
}
}
// Initialize a new solid.
void solid_init(Solid* dest, const FP mass, const Vec2* vel, const Vec2* pos) {
dest->mass = mass;
dest->force = 0;
dest->dir = 0;
if(vel == NULL)
dest->vel.x = dest->vel.y = 0.0;
else {
dest->vel.x = vel->x;
dest->vel.y = vel->y;
}
if(pos == NULL)
dest->pos.x = dest->pos.y = 0.0;
else {
dest->pos.x = pos->x;
dest->pos.y = pos->y;
}
dest->update = rk4_update;
}
// Create a new solid.
Solid* solid_create(const FP mass, const Vec2* vel, const Vec2* pos) {
Solid* dyn = MALLOC_L(Solid);
assert(dyn != NULL);
solid_init(dyn, mass, vel, pos);
return dyn;
}
// Free an existing solid.
void solid_free(Solid* src) {
free(src);
src = NULL;
}

21
src/physics.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "def.h"
// Base of 2D vectors.
typedef struct {
FP x, y; // Basic 2D vector components.
} Vec2;
// Describe any solid in 2D space.
struct Solid {
FP mass, force, dir; // Properties.
Vec2 vel, pos; // Position/velocity vectors.
void(*update)(struct Solid*, const FP); // Update method.
};
typedef struct Solid Solid;
void solid_init(Solid* dest, const FP mass, const Vec2* vel, const Vec2* pos);
Solid* solid_create(const FP mass, const Vec2* vel, const Vec2* pos);
void solid_free(Solid* src);

80
src/pilot.c Normal file
View File

@ -0,0 +1,80 @@
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "pilot.h"
// Stack of pilot id's to assure uniqueness.
static unsigned int pilot_id = 0;
static void pilot_update(Pilot* pilot, const FP dt);
static void pilot_render(Pilot* pilot);
// Render the pilot.
static void pilot_render(Pilot* pilot) {
int sprite;
Vec2 pos;
gl_texture* texture = pilot->ship->gfx_ship;
pos.x = pilot->solid->pos.x;
pos.y = pilot->solid->pos.y;
// Get the sprite corresponding to the direction facing.
sprite = (int)(pilot->solid->dir / (2.0*M_PI / (texture->sy * texture->sx)));
gl_blitSprite(texture, &pos, sprite % (int)texture->sx, sprite / (int)texture->sy);
}
// Update the pilot.
static void pilot_update(Pilot* pilot, const FP dt) {
if(pilot->solid->dir > 2*M_PI) pilot->solid->dir -= 2*M_PI;
if(pilot->solid->dir < 0.0) pilot->solid->dir += 2*M_PI;
// Update the solid.
pilot->solid->update(pilot->solid, dt);
pilot_render(pilot);
}
// ==Init pilot.===========================================
// ship : Ship pilot is flying.
// name : Pilot's name, if NULL, ships name will be used.
// 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) {
pilot->id = pilot_id++; // New unique pilot id based on pilot_id.
pilot->ship = ship;
if(name == NULL)
pilot->name = ship->name;
else
pilot->name = name;
pilot->solid = solid_create(ship->mass, vel, pos);
pilot->armor = ship->armor;
pilot->shield = ship->shield;
pilot->energy = ship->energy;
if(flags & PILOT_PLAYER)
pilot->think = NULL; // Players don't need to thing! :P
pilot->update = pilot_update;
}
// Create a new pilot - Params are same as pilot_init.
Pilot* pilot_create(Ship* ship, char* name, const Vec2* vel, const Vec2* pos, const int flags) {
Pilot* dyn = MALLOC_L(Pilot);
assert(dyn != NULL);
pilot_init(dyn, ship, name, vel, pos, flags);
return dyn;
}
// Free the prisoned pilot!
void pilot_free(Pilot* pilot) {
solid_free(pilot->solid);
free(pilot);
pilot = NULL;
}

32
src/pilot.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "def.h"
#include "physics.h"
#include "ship.h"
#define PILOT_PLAYER 1 // Pilot is a player.
struct Pilot {
int id; // Pilot's id.
char* name; // Pilot's name (if unique).
Ship* ship; // Pilots ship.
Solid* solid; // Associated solid (physics).
// Current health.
FP armor, shield, energy;
void (*update)(struct Pilot*, const FP); // Update the pilot.
void (*think)(struct Pilot*); // AI thinking for the pilot.
unsigned int flags; // Used for AI etc.
};
typedef struct Pilot Pilot;
void pilot_init(Pilot* dest, Ship* ship, char* name,
const Vec2* vel, const Vec2* pos, const int flags);
Pilot* pilot_create(Ship* ship, char* name, const Vec2* vel,
const Vec2* pos, const int flags);
void pilot_free(Pilot* src);

2
src/ship.c Normal file
View File

@ -0,0 +1,2 @@
#include "ship.h"

30
src/ship.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include "def.h"
#include "opengl.h"
enum ship_class { SHIP_CLASS_NULL, SHIP_CLASS_CIVILIAN };
typedef enum ship_class ship_class;
typedef struct {
char* name; // Ship name.
ship_class class; // Ship class.
// Movement.
FP thrust, turn, speed;
// Graphics.
gl_texture* gfx_ship, *gfx_target;
// Characteristics.
int crew;
int mass;
// Health.
FP armor, armor_regen;
FP shield, shield_regen;
FP energy, energy_regen;
// Capacity.
int cap_cargo, cap_weapon;
} Ship;