RogueLife/src/main.c

233 lines
6.4 KiB
C
Raw Normal View History

#include "map.h"
#include "level.h"
#include "render.h"
#include "geometry.h"
#include "entities.h"
2021-06-04 15:14:12 +02:00
#include "game.h"
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/usb.h>
#include <gint/usb-ff-bulk.h>
#include <gint/kprint.h>
#include <gint/cpu.h>
#include <gint/timer.h>
#include <gint/std/stdlib.h>
2021-06-02 15:40:32 +02:00
#include <libprof.h>
#include <stdlib.h>
static bool getkey_global_shortcuts(key_event_t e)
{
if(usb_is_open() && e.key == KEY_OPTN && !e.shift && !e.alpha) {
usb_fxlink_screenshot(true);
return true;
}
return false;
}
2021-06-02 09:38:59 +02:00
extern level_t lv_demo;
int main(void)
{
getkey_set_feature_function(getkey_global_shortcuts);
kprint_enable_fp();
srand(0xc0ffee);
2021-06-02 15:40:32 +02:00
prof_init();
usb_interface_t const *interfaces[] = { &usb_ff_bulk, NULL };
usb_open(interfaces, GINT_CALL_NULL);
2021-06-04 15:14:12 +02:00
game_t game = { 0 };
map_t *m = &game.map;
camera_t *c = &game.camera;
2021-06-04 15:14:12 +02:00
game_load(&game, &lv_demo);
//---
2021-06-04 15:14:12 +02:00
// Load random entities on the map
//---
2021-06-04 15:14:12 +02:00
entity_movement_params_t emp_none = {
.min_speed = fix(0),
.max_speed = fix(0),
.accel_time = fix(0),
.decel_time = fix(0),
};
entity_movement_params_t emp_player = {
.min_speed = PLAYER_SPEED / 4,
.max_speed = PLAYER_SPEED,
.accel_time = fix(1) / 4,
.decel_time = fix(1) / 4,
};
for(int i = 0; i < 10; i++) {
2021-06-02 16:45:02 +02:00
entity_t *e = malloc(sizeof *e);
if(!e) continue;
int x=1, y=1;
for(int i = 0; i < 1000; i++) {
x = rand() % m->width;
y = rand() % m->height;
struct tile *t = map_tile(m, x, y);
if(t && !t->solid) break;
}
2021-06-04 15:14:12 +02:00
e->movement.x = fix(x) + fix(1) / 2;
e->movement.y = fix(y) + fix(1) / 2;
e->movement.vx = 0;
e->movement.vy = 0;
e->movement.facing = rand() % 4;
e->movement.accel_duration = 0;
e->movement_params = &emp_none;
if(rand() % 2) {
2021-06-04 15:14:12 +02:00
e->hitbox = (shape_t){ SHAPE_RECT,
.rect = { .l=-fix(1)/4, .r=fix(1)/4, .t=-fix(1)/4, .b=fix(1)/4 },
2021-06-02 16:45:02 +02:00
.color = C_GREEN,
};
}
else {
2021-06-04 15:14:12 +02:00
e->hitbox = (shape_t){ SHAPE_CIRCLE,
.circle = { .x=0, .y=0, .r=fix(1)/4 },
2021-06-02 16:45:02 +02:00
.color = C_GREEN,
};
}
2021-06-04 15:14:12 +02:00
game_add_entity(&game, e);
}
2021-06-04 15:14:12 +02:00
entity_t *player = game.entities[5];
game.player = player;
player->hitbox.color = C_BLUE;
player->movement_params = &emp_player;
//---
// Main loop
//---
volatile int frame_tick = 1;
int timer_id = timer_configure(TIMER_ANY, 1000000 / FRAME_RATE,
GINT_CALL_SET(&frame_tick));
if(timer_id >= 0)
timer_start(timer_id);
2021-06-02 16:45:02 +02:00
/* Lock inputs for keys until release */
bool lock_plus = false;
bool lock_minus = false;
bool lock_optn = false;
2021-06-02 16:45:02 +02:00
bool lock_shift = false;
2021-06-02 15:40:32 +02:00
uint32_t time_render = 0;
while(1) {
while(!frame_tick) sleep();
/* Assume the frame is not late */
fixed_t dt = fix(1) / FRAME_RATE;
2021-06-02 15:40:32 +02:00
time_render = prof_exec({
dclear(C_RGB(2,1,1));
2021-06-04 15:14:12 +02:00
render_game(&game);
2021-06-02 15:40:32 +02:00
dprint(1, 1, C_WHITE, "Frame: %.3j ms", time_render);
dupdate();
});
clearevents();
if(keydown(KEY_MENU))
gint_osmenu();
if(keydown(KEY_EXIT))
break;
/* Camera speed */
fixed_t vx = CAMERA_SPEED_X;
fixed_t vy = CAMERA_SPEED_Y;
/* Camera movement for this frame */
if(keydown(KEY_4) || keydown(KEY_7) || keydown(KEY_1))
camera_move(c, -fmul(dt, vx), 0);
if(keydown(KEY_6) || keydown(KEY_9) || keydown(KEY_3))
camera_move(c, fmul(dt, vx), 0);
if(keydown(KEY_8) || keydown(KEY_7) || keydown(KEY_9))
camera_move(c, 0, -fmul(dt, vy));
if(keydown(KEY_2) || keydown(KEY_1) || keydown(KEY_3))
camera_move(c, 0, fmul(dt, vy));
if(keydown(KEY_PLUS)) {
if(!lock_plus) camera_zoom(c, c->zoom + 1);
lock_plus = true;
}
else lock_plus = false;
if(keydown(KEY_MINUS)) {
if(!lock_minus) camera_zoom(c, c->zoom - 1);
lock_minus = true;
}
else lock_minus = false;
if(keydown(KEY_OPTN)) {
if(!lock_optn && usb_is_open()) usb_fxlink_screenshot(true);
lock_optn = true;
}
else lock_optn = false;
/* Player movement */
2021-06-04 15:14:12 +02:00
int dir = -1;
if(keydown(KEY_UP)) dir = UP;
if(keydown(KEY_DOWN)) dir = DOWN;
if(keydown(KEY_LEFT)) dir = LEFT;
if(keydown(KEY_RIGHT)) dir = RIGHT;
2021-06-02 16:45:02 +02:00
2021-06-04 15:14:12 +02:00
entity_movement_t next = (dir >= 0)
? entity_move(player, dir, dt)
: entity_still(player, dt);
2021-06-04 15:14:12 +02:00
shape_t player_hitbox = player->hitbox;
shape_translate(&player_hitbox, (fpoint_t){ next.x, next.y });
2021-06-02 16:45:02 +02:00
2021-06-04 15:14:12 +02:00
if(!game_shape_collides(&game, player, &player_hitbox)) {
player->movement = next;
}
else {
player->movement.facing = next.facing;
player->movement.vx = fix(0);
player->movement.vy = fix(0);
player->movement.accel_duration = fix(0);
}
2021-06-02 16:45:02 +02:00
/* Attack */
if(keydown(KEY_SHIFT) && !lock_shift) {
//~ Attacks
fixed_t reach2 = fmul(ATTACK_REACH, ATTACK_REACH);
fixed_t angle_cos2 = fmul(ATTACK_ANGLE_COS, ATTACK_ANGLE_COS);
2021-06-04 15:14:12 +02:00
fpoint_t dir = fdir(player->movement.facing);
2021-06-02 16:45:02 +02:00
2021-06-04 15:14:12 +02:00
for(int i = 0; i < game.entity_count; i++) {
entity_t *e = game.entities[i];
if(e == player) continue;
2021-06-02 16:45:02 +02:00
/* Distance to player */
2021-06-04 15:14:12 +02:00
fixed_t dx = e->movement.x - player->movement.x;
fixed_t dy = e->movement.y - player->movement.y;
2021-06-02 16:45:02 +02:00
fixed_t dist2 = fmul(dx, dx) + fmul(dy, dy);
if(dist2 > reach2) continue;
/* Attack angle */
fixed_t dotp = fmul(dir.x, dx) + fmul(dir.y, dy);
if(dotp < 0 || fmul(dotp, dotp) < fmul(dist2, angle_cos2))
continue;
/* Inflict damage */
2021-06-04 15:14:12 +02:00
e->hitbox.color = C_RED;
2021-06-02 16:45:02 +02:00
}
//~
}
lock_shift = keydown(KEY_SHIFT);
}
timer_stop(timer_id);
2021-06-02 15:40:32 +02:00
prof_quit();
usb_close();
2021-06-02 10:06:10 +02:00
return 1;
}