suddenly, replays, thousands of them. (not really, just one for now)

This commit is contained in:
Andrew "Akari" Alexeyew 2012-07-14 20:46:03 +03:00
parent 3099cf95c0
commit ccc9f341db
14 changed files with 236 additions and 38 deletions

View file

@ -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() {

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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();
}
}

View file

@ -35,7 +35,7 @@ typedef struct {
complex pos;
short focus;
short fire;
short moving;
short moving;
short dir;
float power;

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}