time parameterization + forced rotation direction

This commit is contained in:
Lephenixnoir 2022-01-16 11:29:46 +01:00
parent 0498f076ba
commit d933944322
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 83 additions and 29 deletions

4
TODO Normal file
View File

@ -0,0 +1,4 @@
* Tighter than the original?
* Count number of turns, with optimal
* Add performance counters
* Check if level tempo is accounted for

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -10,7 +10,7 @@
#include <math.h>
//---
// Level strucutres
// Level structures
//---
typedef enum {
@ -149,7 +149,8 @@ extern level_t level5, level6, level7, level8;
extern level_t level9, level10, level11, level12;
extern level_t level13, level14, level15, level16;
extern level_t level17, level18, level19, level20;
extern level_t level21, level22;
extern level_t level21, level22, level23, level24;
extern level_t level25, level26, level27, level28;
extern episode_t episodes[];
extern int episode_count;

View File

@ -54,8 +54,15 @@ episode_t episodes[] = {
&level22,
},
},
{
.name = "guilt",
.level_count = 1,
.levels = (level_t *[]) {
&level22, // TODO
},
},
};
int episode_count = 4;
int episode_count = sizeof(episodes) / sizeof(episodes[0]);
void load_level(game_t *game, level_t const *lv)
{
@ -80,6 +87,20 @@ int strcount(char const *str, int c)
return count;
}
/* Round player rotation to closest multiple of M_PI */
float rpr(float rota)
{
if(fabs(rota) <= M_PI_2)
return 0;
return (rota < 0) ? -M_PI : M_PI;
}
/* Forced player rotation to go back to an even position */
float fpr(float rota, float duration)
{
return (rpr(rota) - rota) / duration;
}
void game_loop(int current_episode, int current_level)
{
game_t game;
@ -89,19 +110,34 @@ void game_loop(int current_episode, int current_level)
state_t state = State_Playing;
if(current_level == 0) {
state = State_EpisodeTransition;
game.time_episode_transition = 0;
game.time = -14.0;
}
/* Direction of time (with a factor regulating game speed) */
float const time_direction_forward = 2.7;
float const time_direction_rewind = -25;
/* Level time to start (negative to leave time before blocks arrive) */
float const LEVEL_START = -14.0;
/* Level time until which message is shown */
float const MESSAGE_END = -5.0;
/* Duration of death pause (seconds) */
float const DEATH_PAUSE_DURATION = 0.7;
/* Level time to restarting playing at after rewind */
float const REWIND_END = -5.0;
/* Duration of level transitions (seconds) */
float const TRANSITION_DURATION = 1.0;
/* Duration of episode transitions (seconds)
Warning: overlaps with pre-level, will lock player if too long x_x */
float const EPISODE_TRANSITION_DURATION = 3.0;
volatile int need_frame = 1;
int timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
if(timer >= 0) timer_start(timer);
/* Frame duration in real time */
float const FRAME_DURATION = 1.0 / 30;
if(current_level == 0) {
state = State_EpisodeTransition;
game.time_episode_transition = 0;
game.time = LEVEL_START;
}
while (1) {
level_t const *lv = game.level;
@ -116,38 +152,37 @@ void game_loop(int current_episode, int current_level)
time_direction = time_direction_rewind;
if(state == State_Dead) {
game.time_dead += (1.0 / 30);
if(game.time_dead >= 0.7) {
game.time_dead += FRAME_DURATION;
if(game.time_dead >= DEATH_PAUSE_DURATION) {
game.time_dead = 0;
game.forced_player_rota = game.player_rota / (game.time + 5.0);
game.forced_player_rota = fpr(game.player_rota,
REWIND_END - game.time);
state = State_Rewind;
}
continue;
continue; /* Pause effect */
}
if(state == State_Transition) {
time_direction = 1.0;
game.time_transition += (1.0 / 30);
if(game.time_transition >= 1.0) {
game.time_transition += FRAME_DURATION;
if(game.time_transition >= TRANSITION_DURATION) {
game.time_transition = 0;
game.player_rota = 0;
game.forced_player_rota = 0;
state = State_Playing;
}
}
if(state == State_EpisodeTransition) {
time_direction = 1.0;
game.time_episode_transition += (1.0 / 30);
if(game.time_episode_transition >= 1.0) {
game.player_rota = 0;
game.time_episode_transition += FRAME_DURATION;
if(game.time_episode_transition >= TRANSITION_DURATION) {
game.forced_player_rota = 0;
}
if(game.time_episode_transition >= 3.0) {
if(game.time_episode_transition >= EPISODE_TRANSITION_DURATION) {
game.time_episode_transition = 0;
state = State_Playing;
}
}
float dt = (1.0 / 30) * time_direction;
float dt = FRAME_DURATION * time_direction;
game.time += dt;
/* Input analysis */
@ -193,23 +228,24 @@ void game_loop(int current_episode, int current_level)
if(changed_episode) {
state = State_EpisodeTransition;
game.time_episode_transition = 0;
game.forced_player_rota = -game.player_rota / 1.0;
game.time = -13.0;
game.forced_player_rota = fpr(game.player_rota,
TRANSITION_DURATION);
game.time = LEVEL_START;
continue;
}
else {
state = State_Transition;
game.time_transition = 0;
game.forced_player_rota = -game.player_rota / 1.0;
game.forced_player_rota = fpr(game.player_rota,
TRANSITION_DURATION);
continue;
}
}
// End of rewind
if(state == State_Rewind && game.time <= -5.0) {
game.time = -5.0;
game.player_rota = 0.0;
game.forced_player_rota = 0.0;
if(state == State_Rewind && game.time <= REWIND_END) {
game.time = REWIND_END;
game.forced_player_rota = 0;
state = State_Playing;
continue;
}
@ -255,7 +291,7 @@ void game_loop(int current_episode, int current_level)
dma_memcpy(gint_vram + 396*(40*j), gint_vram, 396*2*lines);
}
if(state == State_Playing && game.time < -4.0 && lv->message) {
if(state == State_Playing && game.time < MESSAGE_END && lv->message) {
int x = DWIDTH/2 + 8 * (strcount(lv->message, '\n') + 1);
/* Split at newlines */

View File

@ -136,6 +136,9 @@ void rect_physics(rect_t *r, rectmeta_t const *meta, float absolute_time)
float speeding_period = fminf(2.0, fmaxf(0.0, time + 6.0));
r->x -= RECT_SPEED * speeding_period;
}
else if(meta->action == Action_FadeOut) {
// TODO
}
else if(meta->action == Action_OuterRotateLeft) {
float vr = 0.7; /* rad/tempo */
r->r = time * vr;
@ -144,4 +147,14 @@ void rect_physics(rect_t *r, rectmeta_t const *meta, float absolute_time)
float vr = 0.7; /* rad/tempo */
r->r = -time * vr;
}
else if(meta->action == Action_Slide) {
// TODO
}
else if(meta->action == Action_Speed2) {
/* Double speed permanently */
// TODO
}
else if(meta->action == Action_Speed3) {
// TODO
}
}