[Add] Command line option.

[Add] Finished(tm) joypad support.
[Change] Input comes from player.
This commit is contained in:
Allanis 2013-02-01 02:32:29 +00:00
parent e124672464
commit 223a6185fb
14 changed files with 340 additions and 141 deletions

View File

@ -1,13 +1,15 @@
DEBUG = 1
APPNAME = Lephisto
VERSION = -DVMAJOR=0 -DVMINOR=0 -DVREV=1
OBJS := $(shell find ../src/ -name '*.c' -print)
OBJS := $(OBJS:../src/%.c=../src/%.o)
DATA = data
DATAFILES = $(shell find ../gfx/ ../dat/ -name '*.png' -o -name '*.xml' -print)
CFLAGS = -Wall `sdl-config --cflags` `xml2-config --cflags`
CFLAGS = -Wall `sdl-config --cflags` `xml2-config --cflags` $(VERSION)
ifdef DEBUG
CFLAGS += -g3 -DDEBUG
else

View File

@ -5,7 +5,7 @@
<class>1</class>
<movement>
<thrust>400</thrust>
<turn>360</turn>
<turn>960</turn>
<speed>360</speed>
</movement>
<health>

View File

@ -3,6 +3,8 @@
#define MALLOC_L(type)(malloc(sizeof(type)))
#define CALLOC_L(type)(calloc(1, sizeof(type)))
#define ABS(X) ((X<0)?-X:X)
typedef float FP;
#define DATA "data"

View File

@ -3,14 +3,31 @@
#include "log.h"
#include "joystick.h"
static SDL_Joystick* joystick;
static SDL_Joystick* joystick = NULL;
int joystick_use(int indjoystick) {
// Start using the joystick.
LOG("Using joystick %d", indjoystick);
joystick = SDL_JoystickOpen(indjoystick);
if(joystick == NULL) {
WARN("Error opening joystick %d [%s]", indjoystick, SDL_JoystickName(indjoystick));
return -1;
}
DEBUG("\t\tWith %d axes, %d buttons, %d balls, and %d hats",
SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
SDL_JoystickNumBalls(joystick), SDL_JoystickNumHats(joystick));
return 0;
}
int joystick_init(void) {
int indjoystick, numjoysticks, i;
indjoystick = 1;
int numjoysticks, i;
// Init the SDL subsys.
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
WARN("Unable to init the joystick subsystem.");
return -1;
}
// Figure out how many joysticks there are.
numjoysticks = SDL_NumJoysticks();
@ -18,10 +35,13 @@ int joystick_init(void) {
for(i = 0; i < numjoysticks; i++)
LOG("\t\t%d. %s", i, SDL_JoystickName(i));
// Start using that bitch.
LOG("Using joystick %d", indjoystick);
joystick = SDL_JoystickOpen(indjoystick);
// Enable joystick events.
SDL_JoystickEventState(SDL_ENABLE);
return 0;
}
void joystick_exit(void) {
SDL_JoystickClose(joystick);
}

View File

@ -1,2 +1,7 @@
int joystick_init(void);
#pragma once
int joystick_use(int indjoystick);
int joystick_init(void);
void joystick_exit(void);

View File

@ -1,15 +1,15 @@
#include <SDL.h>
#include <stdlib.h>
#include <unistd.h>
#include "def.h"
#include "log.h"
#include "log.h"
#include "physics.h"
#include "opengl.h"
#include "ship.h"
#include "pilot.h"
#include "player.h"
#include "joystick.h"
#include "rng.h"
#include "pilot.h"
static int quit = 0;
@ -17,19 +17,54 @@ static int quit = 0;
static unsigned int time = 0;
// Prototypes.
static void handle_keydown(SDLKey key);
static void handle_keyup(SDLKey key);
// Update.
static void update_all(void);
int main(int argc, const char** argv) {
// Usage.
void print_usage(char** argv) {
LOG("USAGE: %s [-f] [-j n] [-hv]", argv[0]);
LOG("Options are:");
LOG("\t-f - Fullscreen");
LOG("\t-w n - Set width to (n)");
LOG("\t-h n - Set height to (n)");
LOG("\t-j n - Use joystick (n)");
LOG("\t-h - Display this message and exit.");
LOG("\t-v - Print the version and exit");
}
int main(int argc, char** argv) {
SDL_Event event;
// Default window params.
// Default values..
gl_screen.w = 800;
gl_screen.h = 640;
gl_screen.fullscreen = 0;
// Joystick.
int indjoystick = -1;
// Parse arguments.
int c = 0;
while((c = getopt(argc, argv, "fj:hv")) != -1) {
switch(c) {
case 'f':
gl_screen.fullscreen = 1;
break;
case 'j':
indjoystick = atoi(optarg);
break;
case 'v':
LOG("Lephisto: version %d.%d.%d\n", VMAJOR, VMINOR, VREV);
case 'h':
print_usage(argv);
exit(EXIT_SUCCESS);
}
}
// Random numbers.
rng_init();
// default window params.
if(gl_init()) {
// Initializes video output.
WARN("Error initializing video output, exiting...");
@ -37,8 +72,11 @@ int main(int argc, const char** argv) {
}
// Input.
if(indjoystick >= 0) {
if(joystick_init())
WARN("Error initializing joystick input");
joystick_use(indjoystick);
}
// Data loading.
ships_load();
@ -56,70 +94,20 @@ int main(int argc, const char** argv) {
while(!quit) {
// Event loop.
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
handle_keydown(event.key.keysym.sym);
break;
case SDL_KEYUP:
handle_keyup(event.key.keysym.sym);
break;
case SDL_QUIT:
quit = 1;
break;
}
if(event.type == SDL_QUIT) quit = 1; // Handle quit.
handle_input(&event);
}
update_all();
}
// Unload data.
pilots_free();
ships_free();
// Exit subsystems.
joystick_exit();
gl_exit(); // Kills video output.
exit(EXIT_SUCCESS);
}
// Handle keydown events.
static void handle_keydown(SDLKey key) {
switch(key) {
case SDLK_ESCAPE:
quit = 1;
break;
case SDLK_a:
case SDLK_LEFT:
player_setFlag(PLAYER_FLAG_MOV_LEFT);
break;
case SDLK_d:
case SDLK_RIGHT:
player_setFlag(PLAYER_FLAG_MOV_RIGHT);
break;
case SDLK_w:
case SDLK_UP:
player_setFlag(PLAYER_FLAG_MOV_ACC);
break;
default:
break;
}
}
// Handle keyup events.
static void handle_keyup(SDLKey key) {
switch(key) {
case SDLK_a:
case SDLK_LEFT:
player_rmFlag(PLAYER_FLAG_MOV_LEFT);
break;
case SDLK_d:
case SDLK_RIGHT:
player_rmFlag(PLAYER_FLAG_MOV_RIGHT);
break;
case SDLK_w:
case SDLK_UP:
player_rmFlag(PLAYER_FLAG_MOV_ACC);
break;
default:
break;
}
}
// Update all the things.
// Pilots:
// -- Think (ai).

View File

@ -4,19 +4,8 @@
#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
#define SCREEN_W gl_screen.w
#define SCREEN_H gl_screen.h
// The screen info, gives data of current opengl settings.
gl_info gl_screen;
@ -52,38 +41,19 @@ static int flip_surface(SDL_Surface* surface) {
return 0;
}
// Load the image directly as an opengl texture.
gl_texture* gl_newImage(const char* path) {
SDL_Surface* tmp, *surface;
// Load the SDL_Surface to an opengl texture.
gl_texture* gl_loadImage(SDL_Surface* surface) {
SDL_Surface* tmp;
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 NULL;
}
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 NULL;
}
SDL_FreeSurface(tmp); // Free the temp surface.
if(flip_surface(surface)) {
WARN("Error flipping surface");
return NULL;
}
// 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;
texture->sx = 1.;
texture->sy = 1.;
// Ensure size is power of two.
potw = surface->w;
@ -132,6 +102,27 @@ gl_texture* gl_newImage(const char* path) {
surface = tmp;
// Set saved 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 NULL;
}
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
WARN("Unable to fill rect: %s", SDL_GetError());
return NULL;
}
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);
@ -142,8 +133,6 @@ gl_texture* gl_newImage(const char* path) {
// 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);
@ -154,9 +143,39 @@ gl_texture* gl_newImage(const char* path) {
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
texture->sx = 1.;
texture->sy = 1.;
texture->sw = texture->w;
texture->sh = texture->h;
return texture;
}
// Load the image directly as an opengl texture.
gl_texture* gl_newImage(const char* path) {
SDL_Surface* tmp, *surface;
tmp = IMG_Load(path); // Load the surface.
if(tmp == 0) {
WARN("'%s' could not be opened: %s", path, IMG_GetError());
return NULL;
}
surface = SDL_DisplayFormatAlpha(tmp); // Sets the surface to what we use.
if(surface == 0) {
WARN("Error converting image to screen format: %s", SDL_GetError());
return NULL;
}
SDL_FreeSurface(tmp); // Free the temp surface.
if(flip_surface(surface)) {
WARN("Error flipping surface");
return NULL;
}
return gl_loadImage(surface);
}
// 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;
@ -180,22 +199,23 @@ void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glTranslatef(sprite->sw * (FP)(sx)/sprite->rw,
sprite->sh*(sprite->sy-(FP)sy-1)/sprite->rh, 0.0f);
sprite->sh*(sprite->sy-(FP)sy-1)/sprite->rh, 0.);
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Projection translation matrix.
glTranslatef(pos->x - gl_camera->x - sprite->sw/2.0,
pos->y - gl_camera->y - sprite->sh/2.0, 0.0f);
glTranslatef(pos->x - gl_camera->x - sprite->sw/2.,
pos->y - gl_camera->y - sprite->sh/2., 0.);
glScalef((FP)gl_screen.w/SCREEN_W, (FP)gl_screen.h/SCREEN_H, 0.);
// 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(0., 0.);
glVertex2f(0., 0.);
glTexCoord2f(sprite->sw/sprite->rw, 0.);
glVertex2f(sprite->sw, 0.);
glTexCoord2f(0., sprite->sh/sprite->rh);
glVertex2f(0., sprite->sh);
glTexCoord2f(sprite->sw/sprite->rw, sprite->sh/sprite->rh);
glVertex2f(sprite->sw, sprite->sh);
glEnd();
@ -210,17 +230,18 @@ void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
void gl_blitStatic(gl_texture* texture, Vec2* pos) {
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Set up translation matrix.
glTranslatef(pos->x, pos->y, 0);
glTranslatef(pos->x - (FP)gl_screen.w/2., pos->y - (FP)gl_screen.h/2., 0);
glScalef((FP)gl_screen.w/SCREEN_W, (FP)gl_screen.h/SCREEN_H, 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(0., 0.);
glVertex2f(0., 0.);
glTexCoord2f(texture->w/texture->rw, 0.);
glVertex2f(texture->w, 0.);
glTexCoord2f(0., texture->h/texture->rh);
glVertex2f(0., texture->h);
glTexCoord2f(texture->w/texture->rw, texture->h/texture->rh);
glVertex2f(texture->w, texture->h);
glEnd();
@ -235,8 +256,10 @@ void gl_bindCamera(Vec2* pos) {
// Initialize SDL/OpenGL etc.
int gl_init(void) {
int depth;
int depth, i, supported = 0;
SDL_Rect** modes;
int flags = SDL_OPENGL;
flags |= SDL_FULLSCREEN * gl_screen.fullscreen;
// Initializes video.
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
@ -248,8 +271,35 @@ int gl_init(void) {
// -- Ok, Maybe for now.
//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.
// Get available fullscreen modes.
modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
if(modes == NULL) {
WARN("No fullscreen modes available");
if(flags & SDL_FULLSCREEN) {
WARN("Disabling fullscreen mode");
flags ^= SDL_FULLSCREEN;
}
}
else if(modes == (SDL_Rect**) -1)
DEBUG("All fullscreen modes available.");
else {
DEBUG("Available fullscreen modes:");
for(i = 0; modes[i]; ++i) {
DEBUG("\t\t%d x %d", modes[i]->w, modes[i]->h);
if(flags & SDL_FULLSCREEN && modes[i]->w == gl_screen.w && modes[i]->h == gl_screen.h)
supported = 1;
}
}
// Make sure fullscreen mode is supported.
if((flags & SDL_FULLSCREEN) && (!supported)) {
WARN("Fullscreen mode %d x %d is not supported by your current setup, switching to another mode.",
gl_screen.w, gl_screen.h);
gl_screen.w = modes[0]->w;
gl_screen.h = modes[0]->h;
}
// Test the setup.
depth = SDL_VideoModeOK(gl_screen.w, gl_screen.h, gl_screen.depth, flags);
if(depth != gl_screen.depth)
WARN("Depth: %d bpp unavailable, will use %d bpp", gl_screen.depth, depth);
@ -278,17 +328,17 @@ int gl_init(void) {
DEBUG("Renderer: %s", glGetString(GL_RENDERER));
// Some openGL options.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearColor(0., 0., 0., 0.);
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.
glOrtho(-SCREEN_W /2, // Left edge.
SCREEN_W /2, // Right edge.
-SCREEN_H /2, // Bottom edge.
SCREEN_H /2, // Top edge.
-1., // Near.
1.); // Far.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Alpha.
glEnable(GL_BLEND);

View File

@ -1,7 +1,22 @@
#pragma once
#include "SDL_opengl.h"
#include <SDL.h>
#include <SDL_opengl.h>
#include "physics.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
#define WINDOW_CAPTION "Lephisto"
// Info about opengl screen.
@ -25,6 +40,7 @@ typedef struct {
} gl_texture;
// gl_texute loading/freeing.
gl_texture* gl_loadImage(SDL_Surface* surface); // Frees the surface.
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);

View File

@ -81,7 +81,8 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
if(flags & PILOT_PLAYER) {
pilot->think = (void*)player_think; // Players don't need to thing! :P
pilot->think = NULL;
pilot->properties |= PILOT_PLAYER;
player = pilot;
} else
pilot->think = NULL;

View File

@ -22,6 +22,7 @@ struct Pilot {
};
typedef struct Pilot Pilot;
extern Pilot* player; // The player.
Pilot* get_pilot(unsigned int id);
// Creation.

View File

@ -3,17 +3,25 @@
#include "log.h"
#include "player.h"
Pilot* player = NULL;
static unsigned int player_flags = PLAYER_FLAG_NULL;
static FP player_turn = 0.;
static FP player_acc = 0.;
// To be used in pilot.c
void player_think(Pilot* player, const FP dt) {
player->solid->dir_vel = 0.0;
player->solid->dir_vel = 0.;
if(player_turn)
player->solid->dir_vel -= player->ship->turn*player_turn/(FP)(1<<15);
#if 0
if(player_isFlag(PLAYER_FLAG_MOV_LEFT))
player->solid->dir_vel += player->ship->turn;
if(player_isFlag(PLAYER_FLAG_MOV_RIGHT))
player->solid->dir_vel -= player->ship->turn;
#endif
player->solid->force = (player_isFlag(PLAYER_FLAG_MOV_ACC)) ? player->ship->thrust : 0.0;
player->solid->force = player->ship->thrust*player_acc/(FP)(1<<15);
}
// Flag manipulationz.
@ -31,3 +39,89 @@ void player_rmFlag(unsigned int flag) {
player_flags ^= flag;
}
// --Events--
// Joystick.
static void handle_joyaxis(int axis, int value) {
switch(axis) {
case 0:
player_turn = (FP)value;
break;
case 1:
if(value <= 0)
player_acc = (FP)-value;
break;
}
}
static void handle_joybutton(int button) {
switch(button) {
case 0:
break;
case 1:
break;
}
}
// Keyboard.
static void handle_keydown(SDLKey key) {
SDL_Event quit;
switch(key) {
case SDLK_ESCAPE:
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
break;
case SDLK_LEFT:
case SDLK_a:
player_turn -= (FP)(1<<15);
break;
case SDLK_RIGHT:
case SDLK_d:
player_turn += (FP)(1<<15);
break;
case SDLK_UP:
case SDLK_w:
player_acc += (FP)(1<<15);
break;
default:
break;
}
}
static void handle_keyup(SDLKey key) {
switch(key) {
case SDLK_LEFT:
case SDLK_a:
player_turn += (FP)(1<<15);
break;
case SDLK_RIGHT:
case SDLK_d:
player_turn -= (FP)(1<<15);
break;
case SDLK_UP:
case SDLK_w:
player_acc -= (FP)(1<<15);
break;
default:
break;
}
}
// Global input.
void handle_input(SDL_Event* event) {
switch(event->type) {
case SDL_JOYAXISMOTION:
handle_joyaxis(event->jaxis.axis, event->jaxis.value);
break;
case SDL_JOYBUTTONDOWN:
handle_joybutton(event->jbutton.button);
break;
case SDL_KEYDOWN:
handle_keydown(event->key.keysym.sym);
break;
case SDL_KEYUP:
handle_keyup(event->key.keysym.sym);
break;
}
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <SDL.h>
// Flags.
#define PLAYER_FLAG_NULL (1<<0)
#define PLAYER_FLAG_MOV_LEFT (1<<1)
#define PLAYER_FLAG_MOV_RIGHT (1<<2)
@ -9,3 +11,6 @@ int player_isFlag(unsigned int flag);
void player_setFlag(unsigned int flag);
void player_rmFlag(unsigned int flag);
// Input.
void handle_input(SDL_Event* event);

8
src/rng.c Normal file
View File

@ -0,0 +1,8 @@
#include <unistd.h>
#include <SDL.h>
#include "rng.h"
void rng_init(void) {
srand(getpid() + SDL_GetTicks());
}

7
src/rng.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stdlib.h>
#define RNG(L,H) rand()%(H-L_1)+L
void rng_init(void);