Duet/src/main.c

178 lines
4.5 KiB
C

#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <gint/gint.h>
#include <gint/cpu.h>
#include <gint/drivers/r61524.h>
#include <fxlibc/printf.h>
#include <string.h>
#include "duet.h"
level_t level0 = {
.tempo = 1.0,
.blocks = (rectmeta_t []){
{
.time = 0,
.shape = Shape_LongBar,
.position = Position_Left,
.action = Action_Normal
},
{
.time = 1,
.shape = Shape_LongBar,
.position = Position_Middle,
.action = Action_Normal
},
{
.time = 3,
.shape = Shape_LongBar,
.position = Position_Left,
.action = Action_Normal
},
}
};
void load_level(game_t *game, level_t const *lv)
{
memset(game, 0x00, sizeof *game);
game->level = lv;
game->current = lv->blocks;
game->time = -10.0;
}
int strcount(char const *str, int c)
{
int count = 0;
for(int i = 0; str[i]; i++)
count += (str[i] == c);
return count;
}
int main(void)
{
__printf_enable_fp();
/* Azur trickz */
r61524_set(0x010, 0x0010);
level_t const *story_levels[] = {
&level1, &level2, &level3, &level4, &level5, &level6, &level7,
&level8, &level9, &level10, NULL,
};
int story_position = 0;
game_t game;
load_level(&game, story_levels[story_position]);
volatile int need_frame = 1;
int timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
timer_start(timer);
while (1) {
level_t const *lv = game.level;
/* Time management */
while (need_frame == 0) sleep();
need_frame = 0;
float dt = (1.0 / 30) * lv->tempo * 2.7;
game.time += dt;
/* Input analysis */
bool rotate_left=false, rotate_right=false;
key_event_t e;
while ((e = pollevent()).type != KEYEV_NONE) {
if (e.type == KEYEV_DOWN && e.key == KEY_MENU)
gint_osmenu();
}
if (keydown(KEY_7)) {
rotate_left = true;
}
if (keydown(KEY_0)) {
rotate_right = true;
}
/* Level generation */
// Remove rectangles that have passed their lifetime by 4 tempo
for(int i = 0; i < game.cursor;) {
if(game.time > game.table[i].meta->time + 4)
game.table[i] = game.table[--game.cursor];
else
i++;
}
// Find rectangles that need to be loaded, 10 tempo in advance
rectmeta_t const *meta = game.current;
while(meta < lv->blocks + lv->block_count) {
if(meta - game.current > RECT_TABLE_SIZE - game.cursor)
break; /* oops, not enough array space left */
if(meta->time - 10 > game.time)
break;
meta++;
}
// Load everything up to meta
while(game.current < meta) {
rect_t *r = &game.table[game.cursor++];
r->meta = game.current++;
rect_load(r, r->meta);
}
// End of level
if(game.current >= lv->blocks + lv->block_count && game.cursor == 0) {
if(story_levels[++story_position] == NULL)
break;
load_level(&game, story_levels[story_position]);
need_frame = 1;
continue;
}
/* Physics */
// if(player_collision(&game))
// break;
for(int i = 0; i < game.cursor; i++) {
rect_physics(&game.table[i], game.table[i].meta, game.time);
}
if(rotate_left)
game.player_rota += 1.57 * dt;
if(rotate_right)
game.player_rota -= 1.57 * dt;
/* Rendering */
dclear(player_collision(&game) ? C_RED : C_BLACK);
if(game.time < -5 && lv->message != NULL) {
int x = DWIDTH/2 + 8 * (strcount(lv->message, '\n') + 1);
/* Split at newlines */
char const *str = lv->message;
while(*str) {
char const *end = strchrnul(str, '\n');
duet_text_opt(x, DHEIGHT/2, C_WHITE, C_NONE, DTEXT_CENTER,
DTEXT_MIDDLE, str, end - str);
x -= 16;
str = end + (*end != 0);
}
}
render_player(game.player_rota);
for(int i = 0; i < game.cursor; i++)
drectoid(&game.table[i], C_WHITE);
dupdate();
}
timer_stop(timer);
return (1);
}