suddenly, replays, thousands of them. (not really, just one for now)
This commit is contained in:
parent
3099cf95c0
commit
ccc9f341db
14 changed files with 236 additions and 38 deletions
|
@ -13,6 +13,7 @@
|
|||
#include "paths/native.h"
|
||||
#include "resource/resource.h"
|
||||
#include "taisei_err.h"
|
||||
#include "replay.h"
|
||||
|
||||
Global global;
|
||||
|
||||
|
@ -24,6 +25,9 @@ void init_global() {
|
|||
load_resources();
|
||||
printf("- fonts:\n");
|
||||
init_fonts();
|
||||
|
||||
memset(&global.replay, 0, sizeof(Replay));
|
||||
global.replaymode = REPLAY_RECORD;
|
||||
}
|
||||
|
||||
void game_over() {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "fbo.h"
|
||||
#include "vbo.h"
|
||||
#include "resource/resource.h"
|
||||
#include "replay.h"
|
||||
|
||||
#define FILE_PREFIX PREFIX "/share/taisei/"
|
||||
#define CONFIG_FILE "config"
|
||||
|
@ -92,7 +93,6 @@ typedef struct {
|
|||
int frames;
|
||||
int lasttime; // frame limiter
|
||||
int timer;
|
||||
int replaytimer; // lol
|
||||
|
||||
Boss *boss;
|
||||
MenuData *menu;
|
||||
|
@ -106,6 +106,9 @@ typedef struct {
|
|||
FPSCounter fps;
|
||||
|
||||
int nostagebg; // I don't want the automatic stagebg handling to mess with the config, and I don't want that longass if in more than one place either.
|
||||
|
||||
Replay replay;
|
||||
int replaymode;
|
||||
} Global;
|
||||
|
||||
extern Global global;
|
||||
|
@ -127,7 +130,8 @@ double frand();
|
|||
// this is used by both player and replay code
|
||||
enum {
|
||||
EV_PRESS,
|
||||
EV_RELEASE
|
||||
EV_RELEASE,
|
||||
EV_OVER // replay-only
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -115,7 +115,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
init_player(&global.plr);
|
||||
StageInfo* stg = stage_get(atoi(argv[1]) - 1);
|
||||
StageInfo* stg = stage_get(atoi(argv[1]));
|
||||
|
||||
if(stg) {
|
||||
printf("** Entering %s.\n", stg->title);
|
||||
|
|
|
@ -46,6 +46,23 @@ troll:
|
|||
global.game_over = 0;
|
||||
}
|
||||
|
||||
void start_replay(void *arg) {
|
||||
StageInfo *s = stage_get(global.replay.stage);
|
||||
|
||||
if(!s) {
|
||||
printf("Invalid stage %d in replay... wtf?!\n", global.replay.stage);
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: workaround, doesn't even always work. DEBUG THIS.
|
||||
global.fps.show_fps = 0;
|
||||
|
||||
global.replaymode = REPLAY_PLAY;
|
||||
s->loop();
|
||||
global.replaymode = REPLAY_RECORD;
|
||||
global.game_over = 0;
|
||||
}
|
||||
|
||||
void enter_options(void *arg) {
|
||||
MenuData m;
|
||||
create_options_menu(&m);
|
||||
|
@ -64,6 +81,7 @@ void create_main_menu(MenuData *m) {
|
|||
m->type = MT_Persistent;
|
||||
|
||||
add_menu_entry(m, "Start Story", start_story, NULL);
|
||||
add_menu_entry(m, "Replay (TEST)", start_replay, NULL);
|
||||
add_menu_entry(m, "Start Extra", NULL, NULL);
|
||||
#ifdef DEBUG
|
||||
add_menu_entry(m, "Select Stage", enter_stagemenu, NULL);
|
||||
|
|
|
@ -201,10 +201,12 @@ void plr_realdeath(Player *plr) {
|
|||
plr->bombs = PLR_START_BOMBS;
|
||||
|
||||
if(plr->lifes-- == 0) {
|
||||
if(plr->continues < MAX_CONTINUES)
|
||||
if(plr->continues < MAX_CONTINUES) {
|
||||
if(global.replaymode == REPLAY_RECORD) // actually... I'd be strange if REPLAY_PLAY ever got there
|
||||
replay_destroy(&global.replay); // 19:39:29 [@ laochailan] no. no fame for continue users >:D
|
||||
global.menu = create_gameover_menu();
|
||||
else
|
||||
game_over();
|
||||
} else
|
||||
game_over();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct {
|
|||
complex pos;
|
||||
short focus;
|
||||
short fire;
|
||||
short moving;
|
||||
short moving;
|
||||
|
||||
short dir;
|
||||
float power;
|
||||
|
|
59
src/replay.c
59
src/replay.c
|
@ -6,6 +6,63 @@
|
|||
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
|
||||
*/
|
||||
|
||||
void replay_event(int type, int key) {
|
||||
#include "replay.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
void replay_init(Replay *rpy, StageInfo *stage, int seed, Player *plr) {
|
||||
memset(rpy, 0, sizeof(Replay));
|
||||
|
||||
rpy->capacity = REPLAY_ALLOC_INITIAL;
|
||||
rpy->events = (ReplayEvent*)malloc(sizeof(ReplayEvent) * rpy->capacity);
|
||||
|
||||
rpy->stage = stage->id;
|
||||
rpy->seed = seed;
|
||||
rpy->diff = global.diff;
|
||||
rpy->points = global.points;
|
||||
|
||||
rpy->plr_pos = plr->pos;
|
||||
rpy->plr_char = plr->cha;
|
||||
rpy->plr_shot = plr->shot;
|
||||
rpy->plr_lifes = plr->lifes;
|
||||
rpy->plr_bombs = plr->bombs;
|
||||
rpy->plr_power = plr->power;
|
||||
|
||||
rpy->active = True;
|
||||
|
||||
printf("Replay initialized with capacity of %d\n", rpy->capacity);
|
||||
}
|
||||
|
||||
void replay_destroy(Replay *rpy) {
|
||||
if(rpy->events)
|
||||
free(rpy->events);
|
||||
memset(rpy, 0, sizeof(Replay));
|
||||
printf("Replay destroyed.\n");
|
||||
}
|
||||
|
||||
void replay_event(Replay *rpy, int type, int key) {
|
||||
if(!rpy->active)
|
||||
return;
|
||||
|
||||
printf("[%d] Replay event #%d: %d, %d\n", global.frames, rpy->ecount, type, key);
|
||||
|
||||
if(type == EV_OVER)
|
||||
printf("The replay is OVER\n");
|
||||
|
||||
ReplayEvent *e = &(rpy->events[rpy->ecount]);
|
||||
e->frame = global.frames;
|
||||
e->type = (char)type;
|
||||
e->key = (char)key;
|
||||
rpy->ecount++;
|
||||
|
||||
if(rpy->ecount >= rpy->capacity) {
|
||||
printf("Replay reached it's capacity of %d, reallocating\n", rpy->capacity);
|
||||
rpy->capacity += REPLAY_ALLOC_ADDITIONAL;
|
||||
rpy->events = (ReplayEvent*)realloc(rpy->events, sizeof(ReplayEvent) * rpy->capacity);
|
||||
printf("The new capacity is %d\n", rpy->capacity);
|
||||
}
|
||||
}
|
||||
|
|
49
src/replay.h
49
src/replay.h
|
@ -6,4 +6,51 @@
|
|||
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
|
||||
*/
|
||||
|
||||
void replay_event(int, int);
|
||||
#ifndef REPLAY_H
|
||||
#define REPLAY_H
|
||||
|
||||
#include "stage.h"
|
||||
#include "player.h"
|
||||
|
||||
typedef struct ReplayEvent {
|
||||
int frame;
|
||||
char type;
|
||||
char key;
|
||||
} ReplayEvent;
|
||||
|
||||
typedef struct Replay {
|
||||
// initial game settings
|
||||
int stage;
|
||||
int seed;
|
||||
int diff;
|
||||
int points;
|
||||
|
||||
// initial player settings
|
||||
Character plr_char;
|
||||
ShotMode plr_shot;
|
||||
complex plr_pos;
|
||||
float plr_power;
|
||||
int plr_lifes;
|
||||
int plr_bombs;
|
||||
|
||||
ReplayEvent *events;
|
||||
int ecount;
|
||||
int capacity;
|
||||
|
||||
// The fields below should not be stored
|
||||
int active;
|
||||
} Replay;
|
||||
|
||||
enum {
|
||||
REPLAY_RECORD,
|
||||
REPLAY_PLAY
|
||||
};
|
||||
|
||||
void replay_init(Replay *rpy, StageInfo *stage, int seed, Player *plr);
|
||||
void replay_destroy(Replay *rpy);
|
||||
void replay_event(Replay *rpy, int type, int key);
|
||||
|
||||
#define REPLAY_ALLOC_INITIAL 100
|
||||
#define REPLAY_ALLOC_ADDITIONAL 100
|
||||
|
||||
#endif
|
||||
|
|
106
src/stage.c
106
src/stage.c
|
@ -8,6 +8,7 @@
|
|||
#include "stage.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <time.h>
|
||||
#include "global.h"
|
||||
#include "replay.h"
|
||||
#include "config.h"
|
||||
|
@ -17,18 +18,19 @@
|
|||
StageInfo stages[] = {
|
||||
// TODO: Give the stages actual titles/subtitles
|
||||
|
||||
{stage0_loop, False, "Stage 1", "(insert subtitle here)"},
|
||||
{stage1_loop, False, "Stage 2", "(insert subtitle here)"},
|
||||
{stage2_loop, False, "Stage 3", "(insert subtitle here)"},
|
||||
{stage3_loop, False, "Stage 4", "(insert subtitle here)"},
|
||||
{1, stage0_loop, False, "Stage 1", "(insert subtitle here)"},
|
||||
{2, stage1_loop, False, "Stage 2", "(insert subtitle here)"},
|
||||
{3, stage2_loop, False, "Stage 3", "(insert subtitle here)"},
|
||||
{4, stage3_loop, False, "Stage 4", "(insert subtitle here)"},
|
||||
|
||||
{NULL, False, NULL, NULL}
|
||||
{0, NULL, False, NULL, NULL}
|
||||
};
|
||||
|
||||
// NOTE: This returns the stage BY ID, not by the array index!
|
||||
StageInfo* stage_get(int n) {
|
||||
int i;
|
||||
for(i = 0; stages[i].loop; ++i)
|
||||
if(i == n)
|
||||
if(stages[i].id == n)
|
||||
return &(stages[i]);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ void stage_start() {
|
|||
global.game_over = 0;
|
||||
global.points = 0;
|
||||
global.nostagebg = False;
|
||||
|
||||
|
||||
global.plr.recovery = 0;
|
||||
}
|
||||
|
||||
|
@ -50,11 +52,55 @@ void stage_ingamemenu() {
|
|||
global.menu->quit = 1;
|
||||
}
|
||||
|
||||
void replay_input() {
|
||||
if(global.menu) {
|
||||
menu_input(global.menu);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
int sym = event.key.keysym.sym;
|
||||
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
if(sym == SDLK_ESCAPE)
|
||||
stage_ingamemenu();
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// I know this loop is not (yet) optimal - consider it a sketch
|
||||
int i;
|
||||
for(i = 0; i < global.replay.ecount; ++i) {
|
||||
ReplayEvent *e = &(global.replay.events[i]);
|
||||
|
||||
if(e->frame == global.frames) switch(e->type) {
|
||||
case EV_OVER:
|
||||
global.game_over = GAMEOVER_ABORT;
|
||||
break;
|
||||
|
||||
default:
|
||||
if(global.dialog && e->type == EV_PRESS && (e->key == KEY_SHOT || e->key == KEY_BOMB))
|
||||
page_dialog(&global.dialog);
|
||||
else
|
||||
player_event(&global.plr, e->type, e->key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
player_applymovement(&global.plr);
|
||||
}
|
||||
|
||||
void stage_input() {
|
||||
if(global.menu) {
|
||||
menu_input(global.menu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
|
@ -63,22 +109,21 @@ void stage_input() {
|
|||
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
printf("%d / %d\n", sym, SDLK_ESCAPE);
|
||||
|
||||
if(global.dialog && (key == KEY_SHOT || key == KEY_BOMB)) {
|
||||
page_dialog(&global.dialog);
|
||||
replay_event(&global.replay, EV_PRESS, key);
|
||||
} else if(sym == SDLK_ESCAPE) {
|
||||
stage_ingamemenu();
|
||||
} else {
|
||||
player_event(&global.plr, EV_PRESS, key);
|
||||
replay_event(EV_PRESS, key);
|
||||
replay_event(&global.replay, EV_PRESS, key);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
player_event(&global.plr,EV_RELEASE, key);
|
||||
replay_event(EV_RELEASE, key);
|
||||
replay_event(&global.replay, EV_RELEASE, key);
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
|
@ -311,11 +356,8 @@ void stage_logic(int time) {
|
|||
|
||||
global.frames++;
|
||||
|
||||
if(!global.dialog) {
|
||||
if(!global.boss)
|
||||
global.timer++;
|
||||
global.replaytimer++;
|
||||
}
|
||||
if(!global.dialog && !global.boss)
|
||||
global.timer++;
|
||||
|
||||
if(global.timer >= time)
|
||||
global.game_over = GAMEOVER_WIN;
|
||||
|
@ -345,20 +387,41 @@ void stage_end() {
|
|||
}
|
||||
}
|
||||
|
||||
void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime) {
|
||||
void stage_loop(StageInfo* info, StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime) {
|
||||
if(global.game_over == GAMEOVER_WIN) {
|
||||
global.game_over = 0;
|
||||
} else if(global.game_over) {
|
||||
return;
|
||||
}
|
||||
|
||||
int seed = time(0);
|
||||
srand(seed);
|
||||
|
||||
if(global.replaymode == REPLAY_RECORD) {
|
||||
replay_destroy(&global.replay);
|
||||
replay_init(&global.replay, info, seed, &global.plr);
|
||||
} else {
|
||||
printf("REPLAY_PLAY mode: %d events\n", global.replay.ecount);
|
||||
|
||||
srand(global.replay.seed);
|
||||
global.diff = global.replay.diff;
|
||||
global.points = global.replay.points;
|
||||
|
||||
global.plr.shot = global.replay.plr_shot;
|
||||
global.plr.cha = global.replay.plr_char;
|
||||
global.plr.pos = global.replay.plr_pos;
|
||||
global.plr.lifes = global.replay.plr_lifes;
|
||||
global.plr.bombs = global.replay.plr_bombs;
|
||||
global.plr.power = global.replay.plr_power;
|
||||
}
|
||||
|
||||
stage_start();
|
||||
start();
|
||||
|
||||
while(global.game_over <= 0) {
|
||||
if(!global.boss && !global.dialog)
|
||||
event();
|
||||
stage_input();
|
||||
((global.replaymode == REPLAY_PLAY)? replay_input : stage_input)();
|
||||
stage_logic(endtime);
|
||||
calc_fps(&global.fps);
|
||||
|
||||
|
@ -368,10 +431,13 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
|
|||
frame_rate(&global.lasttime);
|
||||
}
|
||||
|
||||
if(global.replaymode == REPLAY_RECORD)
|
||||
replay_event(&global.replay, EV_OVER, 0);
|
||||
|
||||
end();
|
||||
stage_end();
|
||||
}
|
||||
|
||||
|
||||
void draw_stage_title(int t, int dur, char *stage, char *subtitle) {
|
||||
if(t < 0 || t > dur)
|
||||
return;
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef void (*StageRule)(void);
|
|||
typedef void (*ShaderRule)(int);
|
||||
|
||||
typedef struct StageInfo {
|
||||
int id;
|
||||
StageRule loop;
|
||||
int hidden;
|
||||
// reserved for draw_stage_title when/if it's used
|
||||
|
@ -41,7 +42,7 @@ typedef struct StageInfo {
|
|||
extern StageInfo stages[];
|
||||
StageInfo* stage_get(int);
|
||||
|
||||
void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime);
|
||||
void stage_loop(StageInfo *info, StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime);
|
||||
|
||||
void apply_bg_shaders(ShaderRule *shaderrules);
|
||||
void draw_stage_title(int t, int dur, char *stage, char *subtitle);
|
||||
|
|
|
@ -520,7 +520,6 @@ void stage0_events() {
|
|||
|
||||
TIMER(&global.timer);
|
||||
|
||||
|
||||
// opening. projectile bursts
|
||||
FROM_TO(100, 160, 25) {
|
||||
create_enemy1c(VIEWPORT_W/2 + 70, 700, Fairy, stage0_burst, 1 + 0.6I);
|
||||
|
@ -606,5 +605,5 @@ void stage0_end() {
|
|||
|
||||
void stage0_loop() {
|
||||
ShaderRule list[] = { stage0_fog, NULL };
|
||||
stage_loop(stage0_start, stage0_end, stage0_draw, stage0_events, list, 5200);
|
||||
stage_loop(stage_get(1), stage0_start, stage0_end, stage0_draw, stage0_events, list, 5200);
|
||||
}
|
||||
|
|
|
@ -160,5 +160,5 @@ void stage1_draw() {
|
|||
|
||||
void stage1_loop() {
|
||||
ShaderRule shaderrules[] = { stage1_fog, stage1_bloom, NULL };
|
||||
stage_loop(stage1_start, stage1_end, stage1_draw, stage1_events, shaderrules, 5500);
|
||||
}
|
||||
stage_loop(stage_get(2), stage1_start, stage1_end, stage1_draw, stage1_events, shaderrules, 5500);
|
||||
}
|
||||
|
|
|
@ -91,5 +91,5 @@ void stage2_draw() {
|
|||
|
||||
void stage2_loop() {
|
||||
ShaderRule shaderrules[] = { stage2_fog, NULL };
|
||||
stage_loop(stage2_start, stage2_end, stage2_draw, stage2_events, shaderrules, 5500);
|
||||
}
|
||||
stage_loop(stage_get(3), stage2_start, stage2_end, stage2_draw, stage2_events, shaderrules, 5500);
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ void stage3_draw() {
|
|||
|
||||
void stage3_loop() {
|
||||
// ShaderRule shaderrules[] = { stage1_fog, stage1_bloom, NULL };
|
||||
stage_loop(stage3_start, stage3_end, stage3_draw, stage3_events, NULL, 5500);
|
||||
}
|
||||
stage_loop(stage_get(4), stage3_start, stage3_end, stage3_draw, stage3_events, NULL, 5500);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue