aboutsummaryrefslogtreecommitdiff
path: root/source/game.c
diff options
context:
space:
mode:
authorEmil Williams2026-02-11 22:40:44 +0000
committerEmil Williams2026-02-14 00:52:41 +0000
commitdc655ac2079e0eea55c56b6712bf6a2167b57845 (patch)
tree1006f06ddda24c87ffdf549ab7639c89703cc9fb /source/game.c
parentcd111fbabfa1f84c9c9aa35f1242d4edbec15b22 (diff)
downloadMonobomberman-dc655ac2079e0eea55c56b6712bf6a2167b57845.tar.xz
Monobomberman-dc655ac2079e0eea55c56b6712bf6a2167b57845.tar.zst
primitive implementation
added movement, explosions, the conception of death, and bugs
Diffstat (limited to 'source/game.c')
-rw-r--r--source/game.c213
1 files changed, 135 insertions, 78 deletions
diff --git a/source/game.c b/source/game.c
index 2ade12a..ea02cbb 100644
--- a/source/game.c
+++ b/source/game.c
@@ -1,49 +1,131 @@
#include "all.h"
-void GameInitialize(game_t * game, char * window_name) {
- SetConfigFlags(FLAG_WINDOW_RESIZABLE);
- SetTraceLogLevel(LOG_NONE);
- /* :config */
- game->horizontal = 1920;
- game->vertical = 1080;
- InitWindow(game->horizontal, game->vertical, window_name);
- game->ups = 60;
- game->fps = 30;
- game->font = DefaultFont("fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf");
- /* :setup */
- SetWindowState(FLAG_WINDOW_HIDDEN);
- InitAudioDevice();
- SetWindowPosition(0, 0);
- GuiLoadStyleDarkSimple();
- GuiSetFont(game->font);
- /* --- */
+static void GameInitialize(game_t * game, char * window_name);
+static void GameDeinitialize(game_t * game);
+static void GameLoop(game_t * game);
+static void GameReport(game_t * game, f32 fps, f32 ups, u32 total_fps, u32 total_ups);
+
+void GameStart(char * program_name) {
+ _Alignas(64) game_t game[1] = {0};
+ GameInitialize(game, program_name);
+ GameLoop(game);
+ GameDeinitialize(game);
}
-void GameDeinitialize(game_t * game) {
- SetWindowState(FLAG_WINDOW_HIDDEN);
- UnloadFont(game->font);
- CloseAudioDevice();
- CloseWindow();
+static void GameRecalculateViewport(game_t * game) {
+ game->config.resolution_x = GetScreenWidth();
+ game->config.resolution_y = GetScreenHeight();
+ game->camera = (Camera2D) {
+ .offset = (Vector2) { 0 },
+ .target = (Vector2) { 0 },
+ .rotation = 0.,
+ .zoom = fminf(
+ (float) game->config.resolution_x /
+ (game->config.map_x * game->config.spritesheet_scale),
+ (float) game->config.resolution_y /
+ (game->config.map_y * game->config.spritesheet_scale)),
+ };
}
-void GameLoop(game_t * game) {
-
- #define StepStart(prefix) \
- prefix##_delta = timespec_sub(now, prefix##_last); \
- if (timespec_cmp(prefix##_delta, prefix##_interval) >= 0) { (void) 0
+void GameResize(game_t * game) {
+ if (IsWindowResized()) {
+ GameRecalculateViewport(game);
+ }
+}
- #define StepStop(prefix) \
- prefix##s_per_second++; \
- prefix##_total++; \
- prefix##_last = timespec_add(prefix##_last, prefix##_interval); \
- if (timespec_cmp(prefix##_last, now) < 0) { \
- prefix##_last = now; \
- } \
+static void GameInitialize(game_t * game, char * window_name) {
+
+ game->config = (config_t) {
+ .resolution_x = 600,
+ .resolution_y = 600,
+ .fps = 60,
+ .ups = 30,
+ .font = "fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf",
+ .spritesheet = "assets/simple.png",
+ .spritesheet_scale = 128,
+ .map_x = 13,
+ .map_y = 13,
+ };
+ {
+ int t = game->config.spritesheet_scale;
+ /* better, but not really good, it's FINE */
+ Rectangle wall[2] = // group 0
+ {(Rectangle){ 0, 0, t, t},
+ (Rectangle){t - 1, 0, t, t}};
+
+ Rectangle explosion[2] = // group 1
+ {(Rectangle){t * 2 - 1, 0, t, t},
+ (Rectangle){t * 3 - 1, 0, t, t}};
+
+ Rectangle powerup[8] = // group 2
+ {(Rectangle){ 0, t, t, t},
+ (Rectangle){t - 1, t, t, t},
+ (Rectangle){t * 2 - 1, t, t, t},
+ (Rectangle){t * 3 - 1, t, t, t},
+ (Rectangle){ 0, t * 2, t, t},
+ (Rectangle){t - 1, t * 2, t, t},
+ (Rectangle){t * 2 - 1, t * 2, t, t},
+ (Rectangle){t * 3 - 1, t * 2, t, t}};
+
+ Rectangle player[4] = // group 3
+ {(Rectangle){ 0, t * 3, t, t},
+ (Rectangle){t - 1, t * 3, t, t},
+ (Rectangle){t * 2 - 1, t * 3, t, t},
+ (Rectangle){t * 3 - 1, t * 3, t, t}};
+
+ Rectangle bomb[4] = // group 4
+ {(Rectangle){ 0, t * 4, t, t},
+ (Rectangle){t - 1, t * 4, t, t},
+ (Rectangle){t * 2 - 1, t * 4, t, t},
+ (Rectangle){t * 3 - 1, t * 4, t, t}};
+
+ Rectangle enemy[4] = // group 5
+ {(Rectangle){ 0, t * 5, t, t},
+ (Rectangle){t - 1, t * 5, t, t},
+ (Rectangle){t * 2 - 1, t * 5, t, t},
+ (Rectangle){t * 3 - 1, t * 5, t, t}};
+
+ memcpy(game->tiles.wall, wall, sizeof(wall));
+ memcpy(game->tiles.explosion, explosion, sizeof(explosion));
+ memcpy(game->tiles.powerup, powerup, sizeof(powerup));
+ memcpy(game->players.player, player, sizeof(player));
+ memcpy(game->bombs.bomb, bomb, sizeof(bomb));
+ memcpy(game->enemies.enemy, enemy, sizeof(enemy));
}
+ MultiPlayer(game, game->config.map_x, game->config.map_y, 4);
+
+ game->tiles.color = (rand() % 4) | ((rand() % 4) << 2) | ((rand() % 4) << 4) | GAME_OPAQUE;
+ if (game->tiles.color == GAME_OPAQUE) { game->tiles.color |= GAME_WHITE; }
+
+ game->bombs.color[0] = GAME_WHITE | GAME_OPAQUE;
+ game->bombs.color[1] = GAME_RED | GAME_OPAQUE;
+
+ /* :config */
+ game->font = DefaultFont(game->config.font);
+
+ /* this is retarded (intentionally) */
+ RaylibInitialize(game->config.resolution_x-1, game->config.resolution_y-1, window_name, game->font);
+ SetWindowSize(game->config.resolution_x, game->config.resolution_y);
+ GameRecalculateViewport(game);
+
+ game->spritesheet = LoadTexture(game->config.spritesheet);
+ if (game->spritesheet.id <= 0) { abort(); }
+
+ ClearWindowState(FLAG_WINDOW_HIDDEN);
+}
+
+static void GameDeinitialize(game_t * game) {
+ UnloadTexture(game->spritesheet);
+ if (GetFontDefault().texture.id != game->font.texture.id) { UnloadFont(game->font); }
+ RaylibDeinitialize();
+}
+
+static void GameLoop(game_t * game) {
+
#define StepSimpleStart(prefix,linear) \
prefix##_delta = timespec_sub(now, prefix##_last); \
- if (timespec_cmp(prefix##_delta, (timespec_t){1.,0.}) >= 0) { \
+ if (timespec_cmp(prefix##_delta, linear) >= 0) { \
(void)0
#define StepSimpleStop(prefix) \
@@ -52,8 +134,8 @@ void GameLoop(game_t * game) {
timespec_t
now,
- update_interval = {0, (f64) TIMESPEC_HZ / game->ups},
- frame_interval = {0, (f64) TIMESPEC_HZ / game->fps},
+ update_interval = {0, (f64) TIMESPEC_HZ / game->config.ups},
+ frame_interval = {0, (f64) TIMESPEC_HZ / game->config.fps},
update_last, frame_last, print_last,
update_delta, frame_delta, print_delta,
wait;
@@ -66,32 +148,30 @@ void GameLoop(game_t * game) {
f64 interpolation = 0.;
- ClearWindowState(FLAG_WINDOW_HIDDEN);
-
clock_gettime(CLOCK_MONOTONIC, &now);
update_last = frame_last = print_last = now;
while (1) {
StepStart(update);
- if (GameUpdate(game, now)) { return; }
+ if (Update(game, now)) { return; }
StepStop(update);
StepStart(frame);
clock_gettime(CLOCK_MONOTONIC, &now);
interpolation =
CLAMP(
- TIMESPEC_TO_F64(update_delta)
- / TIMESPEC_TO_F64(update_interval),
- 0.0, 1.0f);
- GameRender(game, interpolation);
+ TIMESPEC_TO_F64(update_delta)
+ / TIMESPEC_TO_F64(update_interval),
+ 0.0, 1.0f);
+ Render(game, interpolation);
StepStop(frame);
clock_gettime(CLOCK_MONOTONIC, &now);
wait = timespec_sub(
timespec_min(
- timespec_add(update_last, update_interval),
- timespec_add(frame_last, frame_interval)),
+ timespec_add(update_last, update_interval),
+ timespec_add(frame_last, frame_interval)),
now);
if (timespec_cmp(wait, zero_seconds) > 0) {
@@ -100,10 +180,10 @@ void GameLoop(game_t * game) {
StepSimpleStart(print, one_second);
GameReport(game,
- round(frames_per_second / TIMESPEC_TO_F64(print_delta)),
- round(updates_per_second / TIMESPEC_TO_F64(print_delta)),
- frame_total,
- update_total);
+ round(frames_per_second / TIMESPEC_TO_F64(print_delta)),
+ round(updates_per_second / TIMESPEC_TO_F64(print_delta)),
+ frame_total,
+ update_total);
frames_per_second = updates_per_second = 0;
StepSimpleStop(print);
@@ -111,33 +191,10 @@ void GameLoop(game_t * game) {
}
}
-i16 GameUpdate(game_t * game, timespec_t now) {
- (void) now;
-
- PollInputEvents();
- if (IsWindowResized()) {
- game->horizontal = GetScreenWidth();
- game->vertical = GetScreenHeight();
- }
- switch (GetKeyPressed()) {
- case KEY_ESCAPE: return 1;
- }
- return 0;
-}
-
-void GameRender(game_t * game, f64 interpolation) {
- (void)interpolation;
-
- BeginDrawing();
- ClearBackground(BLACK);
- /* >>> */
-
- /* --- */
- rlDrawRenderBatchActive();
- SwapScreenBuffer();
-}
-
-void GameReport(game_t * game, f32 fps, f32 ups, u32 total_fps, u32 total_ups) {
+static void GameReport(game_t * game, f32 fps, f32 ups, u32 total_fps, u32 total_ups) {
+ (void)game;
+#ifndef NDEBUG
printf("[FPS|UPS|Total] (%3.0f : %3.0f) | [%7u/%7u]\n",
- fps, ups, total_fps, total_ups);
+ fps, ups, total_fps, total_ups);
+#endif
}