Optional free axis mode

This commit is contained in:
Andrew "Akari" Alexeyew 2012-08-15 17:36:39 +03:00
parent d8ceb05757
commit 4754e6c76e
11 changed files with 94 additions and 14 deletions

View file

@ -42,6 +42,7 @@ ConfigEntry configdefs[] = {
{CFGT_INT, GAMEPAD_AXIS_UD, "gamepad_axis_ud"},
{CFGT_INT, GAMEPAD_AXIS_LR, "gamepad_axis_lr"},
{CFGT_INT, GAMEPAD_AXIS_THRESHOLD, "gamepad_axis_threshold"},
{CFGT_INT, GAMEPAD_AXIS_FREE, "gamepad_axis_free"},
// gamepad controls
{CFGT_INT, GP_UP, "gamepad_key_up"},
@ -67,6 +68,7 @@ ConfigEntry* config_findentry(char *name) {
void config_preset(void) {
memset(tconfig.strval, 0, sizeof(tconfig.strval));
memset(tconfig.intval, 0, sizeof(tconfig.intval));
tconfig.intval[KEY_UP] = SDLK_UP;
tconfig.intval[KEY_DOWN] = SDLK_DOWN;

View file

@ -57,6 +57,7 @@ typedef enum ConfigKey {
GAMEPAD_AXIS_UD,
GAMEPAD_AXIS_LR,
GAMEPAD_AXIS_THRESHOLD,
GAMEPAD_AXIS_FREE,
// gamepad controls
// The UDLR ones should work without adjusting - but you can assign custom buttons to them if you really need to

View file

@ -38,6 +38,8 @@ typedef enum {
// EF_Game
E_PlrKeyDown,
E_PlrKeyUp,
E_PlrAxisUD,
E_PlrAxisLR,
E_Pause
} EventType;

View file

@ -11,6 +11,7 @@
#include "taisei_err.h"
#include "config.h"
#include "events.h"
#include "global.h"
static struct {
int initialized;
@ -85,8 +86,20 @@ int gamepad_axis2menuevt(int id, int val) {
return -1;
}
void gamepad_axis(int id, int val, EventHandler handler, EventFlags flags, void *arg) {
int *a = gamepad.axis;
int gamepad_axis2gameevt(int id) {
if(id == tconfig.intval[GAMEPAD_AXIS_LR])
return E_PlrAxisLR;
if(id == tconfig.intval[GAMEPAD_AXIS_UD])
return E_PlrAxisUD;
return -1;
}
void gamepad_axis(int id, int raw, EventHandler handler, EventFlags flags, void *arg) {
int *a = gamepad.axis;
int val = AXISVAL(raw);
int free = tconfig.intval[GAMEPAD_AXIS_FREE];
int menu = flags & EF_Menu;
int game = flags & EF_Game;
@ -96,11 +109,19 @@ void gamepad_axis(int id, int val, EventHandler handler, EventFlags flags, void
return;
}
printf("axis: %i %i %i\n", id, val, raw);
if(game && free) {
int evt = gamepad_axis2gameevt(id);
if(evt >= 0)
handler(evt, raw, arg);
}
if(val) { // simulate press
if(!a[id]) {
a[id] = val;
if(game) {
if(game && !free) {
int key = gamepad_axis2gamekey(id, val);
if(key >= 0)
handler(E_PlrKeyDown, key, arg);
@ -164,10 +185,8 @@ void gamepad_event(SDL_Event *event, EventHandler handler, EventFlags flags, voi
switch(event->type) {
case SDL_JOYAXISMOTION:
val = event->jaxis.value;
if(val < -sens || val > sens || !val) {
printf("Axis: %i %i\n", event->jaxis.axis, val);
gamepad_axis(event->jaxis.axis, AXISVAL(val), handler, flags, arg);
}
if(val < -sens || val > sens || !val)
gamepad_axis(event->jaxis.axis, val, handler, flags, arg);
break;
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP:

View file

@ -27,6 +27,7 @@ enum {
};
#define GAMEPAD_AXES 16
#define AXISVAL(x) ((x > 0) - (x < 0))
#define GAMEPAD_AXIS_RANGE 32767
#define AXISVAL SIGN
#endif

View file

@ -152,11 +152,15 @@ int strendswith(char *s, char *e);
char* difficulty_name(Difficulty diff);
void stralloc(char **dest, char *src);
#define SIGN(x) ((x > 0) - (x < 0))
// this is used by both player and replay code
enum {
EV_PRESS,
EV_RELEASE,
EV_OVER // replay-only
EV_OVER, // replay-only
EV_AXIS_LR,
EV_AXIS_UD,
};
#endif

View file

@ -291,13 +291,47 @@ void player_event(Player* plr, int type, int key) {
}
break;
case EV_AXIS_LR:
plr->axis_lr = key;
break;
case EV_AXIS_UD:
plr->axis_ud = key;
break;
}
}
// free-axis movement
int player_applymovement_gamepad(Player *plr) {
if(!plr->axis_lr && !plr->axis_ud)
return False;
complex direction = (plr->axis_lr + plr->axis_ud*I) / (double)GAMEPAD_AXIS_RANGE;
//if(cabs(direction))
// direction /= cabs(direction);
double real = creal(direction);
double imag = cimag(direction);
int sr = SIGN(real);
int si = SIGN(imag);
player_setmoveflag(plr, KEY_UP, si == -1);
player_setmoveflag(plr, KEY_DOWN, si == 1);
player_setmoveflag(plr, KEY_LEFT, sr == -1);
player_setmoveflag(plr, KEY_RIGHT, sr == 1);
if(direction)
player_move(&global.plr, direction);
return True;
}
void player_applymovement(Player* plr) {
if(plr->deathtime < -1)
return;
int gamepad = player_applymovement_gamepad(plr);
plr->moving = False;
int up = plr->moveflags & MOVEFLAG_UP,
@ -311,7 +345,10 @@ void player_applymovement(Player* plr) {
} else if(right && !left) {
plr->moving = True;
plr->dir = 0;
}
}
if(gamepad)
return;
complex direction = 0;
@ -319,7 +356,7 @@ void player_applymovement(Player* plr) {
if(down) direction += 1I;
if(left) direction -= 1;
if(right) direction += 1;
if(cabs(direction))
direction /= cabs(direction);

View file

@ -10,7 +10,7 @@
#include <complex.h>
#include "enemy.h"
#include "gamepad.h"
#include "resource/animation.h"
enum {
@ -65,6 +65,9 @@ typedef struct {
int movetime;
int prevmove;
int prevmovetime;
int axis_ud;
int axis_lr;
} Player;
void init_player(Player*);

View file

@ -89,7 +89,7 @@ void replay_event(Replay *rpy, int type, int key) {
ReplayEvent *e = &(s->events[s->ecount]);
e->frame = global.frames;
e->type = (char)type;
e->key = (char)key;
e->key = (short)key;
s->ecount++;
if(s->ecount >= s->capacity) {

View file

@ -15,7 +15,7 @@
typedef struct ReplayEvent {
int frame;
char type;
char key;
short key;
} ReplayEvent;
typedef struct ReplayStage {

View file

@ -86,6 +86,16 @@ void stage_input_event(EventType type, int key, void *arg) {
stage_ingamemenu();
break;
case E_PlrAxisLR:
player_event(&global.plr, EV_AXIS_LR, key);
replay_event(&global.replay, EV_AXIS_LR, key);
break;
case E_PlrAxisUD:
player_event(&global.plr, EV_AXIS_UD, key);
replay_event(&global.replay, EV_AXIS_UD, key);
break;
default: break;
}
}
@ -477,6 +487,7 @@ void stage_loop(StageInfo* info, StageRule start, StageRule end, StageRule draw,
player_set_power(&global.plr, power);
global.plr.movetime = global.plr.prevmove = global.plr.prevmovetime = 0;
global.plr.axis_lr = global.plr.axis_ud = 0;
start();