From 8dba2daeb3c9321d8eb284df0b9076e18addf0c4 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Thu, 20 Aug 2020 17:04:31 +0200 Subject: [PATCH] add a walkable map --- CMakeLists.txt | 2 ++ MystNB.g1a | Bin 31076 -> 32920 bytes assets-fx/fxconv-metadata.txt | 8 ++--- assets-fx/spritesheet.png | Bin 0 -> 1071 bytes src/engine.c | 56 ++++++++++++++++++++++++++++++++ src/engine.h | 55 ++++++++++++++++++++++++++++++++ src/main.c | 58 +++++++++++++++++++++++++++++++++- 7 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 assets-fx/spritesheet.png create mode 100644 src/engine.c create mode 100644 src/engine.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 80b750c..cf3f26d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ find_package(Gint 2.1 REQUIRED) set(SOURCES src/main.c + src/engine.c # ... ) # Shared assets, fx-9860G-only assets and fx-CG-50-only assets @@ -20,6 +21,7 @@ set(ASSETS set(ASSETS_fx assets-fx/levels.png assets-fx/title.png + assets-fx/spritesheet.png assets-fx/font_mystere.png # ... ) diff --git a/MystNB.g1a b/MystNB.g1a index 43edceff9eb059c3c32c9af8236fe59169e5dd29..c7d39564d44201c09e1c8e55a85a895ffbaa6c16 100644 GIT binary patch delta 4528 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 Bbvgh5 delta 2848 zcmZ8jaZH=X6~FH=AI7G{allXq5#kU?fZ7KkjJOUn!~vHOK$IXxfH;&KA0 zCRXvs)))>=D61;kL=~cFW&NV4sel~vO7f|p+K zgeA5^fqA|aP>s3{%Nr*wYAOPax)x!la|p|4MENL6lJak~`X#Iw8~NJaTa#?RvwdQ_ zZ+o2TKB)bKn*BUI_DdS$=b_k-L6l+LfJ9^F#^MI>%Ln5=q^~~YDX&!0mJOxz zm2V_j2dA+kitB(~l4IuJ$j65b{TVUO;42QX)S@5{2{WTW1`S~?YlI!Ch77SE4e+#s z%|<)em~CMmF^z5HfrB?KEfB%#K#4OVPQ8m6A1p{g>dY1yi5=n0SWXSwe9&kSWYTD& z`da>lv4|e@@#jW6h?0M(E=oRBL0CeN2TUfKSiz@E1%iZ3dGxrKCnR;qhmo|C+k7~w zTxCr&JeXvmC%2X7Nd?rBG=bD_R#_IKhqi6k-+rs@&0_s(ct}%~K~PS@l3l#o{JtD9 zQ`XHz60NA_IVq`vRHRr0=}9qxC?hE!Q|qfpN4E=`Lbe#rrs#!h0gM-bdGH1RWwqWX z%(ku6A2Ca^6`OzS1I3qSqOwTk;d(x9v6w_oT2_#{%|)p=dzFZAQcv)CO9=%r9P6S- zgNpxHyrdJ8BDq&4(q&3B2Ki*hBV9dw|7?=5hC$wwX{R|;%1q|OkAF#F5DM+ZSL49a2LG(jA4X0Nu$naCROkidiSjdlxiBhz{Wv zr-R2yDyt@};33krAvyrEmFel}PYJ7iPS_P3t0vg|q@H_Dm&6w~f~`=OV3#y}_H=`# zU>vits@Rq&NO3nFYxY&Y9VUnjRje1HqSU&60**!spPBZn8$FR28XxfAoOx^#eS2*qGIO7*(_Sa55!drMyHzdu83*6CKci>n z`TFZtdgcjFaePhf>pbM>5~TXp#{Jb{0hvDJxp$wIyGh#jt3Zu%F^Q zn*Cw1lvo-OaCXi_&rWdnxh&ZcQhoc*HH(0soGa2fLK@XAhH0)!45i(n&(#v|2&svs@W0kS-H<&r`Yg=^8?10jp6zPcbB#a?QH27z4RCEDpSdmvOId;&*R)3y3z!~ zN~dtb{M_#zlYc&}_E_>8X2~S><`tMh?Z*Ke&ayS`E^nY9cgxEK*(k3AQQQ|QC2?_1 zRD7c=PmbgTTJOagdZAsJyZE7G6x~-bv41JWSJg#R%e;}B@ns#{&I{LyrsjRgB<7Zh zBRIaZh8l`8_2%@h?#FBM_Dg@r+H)yx7ECQ$TacVPS43&Tiz8Y(#hrBpM$s{5zc7iM z+|p$}QrAH*)hnBIkE4uzT0AX-2r5Ka9U-hQnJ+Xf$zJqbA5ms5Kax@}Gr}%c13f?h zm<1jJn9^wAfu&OfB zYxzVpBn&FcGe}tH6T-SCfiINKe!E8QhL3KKGBYqBSv@F>rx0iW2JwO+wiYA! zSzw*8s}3LlSr$;O)DCu0xz~g3dHCGTUk!DnsZYb6|5_|n5vKqE diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt index 961995f..3a685d7 100644 --- a/assets-fx/fxconv-metadata.txt +++ b/assets-fx/fxconv-metadata.txt @@ -1,10 +1,6 @@ -levels.png: +*.png: type: bopti-image - name: img_levels - -title.png: - type: bopti-image - name: img_title + name_regex: (.*)\.png img_\1 font_mystere.png: type: font diff --git a/assets-fx/spritesheet.png b/assets-fx/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..3bbfcd1f723d35b5281998c7aeb854c1641c3cb2 GIT binary patch literal 1071 zcmV+~1kn45P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00WmvL_t(|+U;Chj_V){Ehwv= z1$5PwxIg6zh@XT6?1EIyOa{!c0ULZmL;Ad5yUZ&``yd>Dsr);A-hmRJso&P^X)_Yf z3iw000sn#WMbQ8l9pt)EFGm zrp>6*Bi9=K2sH>HR6nU@U(Fh%e)ap;D3o!^`jt$^I2Q58CnG)tVC0Omh`$}nsMBAP2fWz!{+*u9f>9Uu^cJLr*X?t(e;!t-nQg z8-b^Y z$eMk1;({MluUEddkMwzm_7p0?U(QlWz9z>6>HO`hl7BR_AvL3&$U{ugh6B|jU)u+; z62$l=vsoKQTI|pY2s<4;x5RCNx#jSt&{aNQMCw{2`{aV8fL2l9N*~f3zv%E+#vTQC z5G8=Z@t3$9JXN0q1m)@}+1&FHe89*Ao`?^C6rcdDq5yR=y}}1z>FC~*KZYf8M{7x{ z;3);9h8)2MjK~E^WQqwHiSh4NU^aJfJ0DL#Y*a*iK(7K|N_PSw)58a7Uo{!&hELnjD};t7pROfjX7B;zf$UB`0Lynv z2os5WfZRz>yHR`qq_5~ytl$IkOsDj9#|LOm-x@qn{Sorr@d46$T0Btw5%M=5Fu80# zU~+NK2WV5+qh5WN%6H|0?s|t`%Liy=M~}uIkxsvIP`h+Lz#PS@f~?set@^tMa}G=+=iOx11tw%t9-!W-BnO=pyUIvcQ+;O2J1ue?x~9vV2KZK8w2jV z-|+bT01v@<1wH`6Bf2AIIS`**5SNxN+OVAP=N&YMG6|*XG8d#Z(uh-Uul&si>>&Kx zW%B{6-4F0)d{X(Ky<8 literal 0 HcmV?d00001 diff --git a/src/engine.c b/src/engine.c new file mode 100644 index 0000000..d5fe81d --- /dev/null +++ b/src/engine.c @@ -0,0 +1,56 @@ +#include +#include +#include "engine.h" + +#define CELL_X(x) (-2 + 10 * (x)) +#define CELL_Y(y) (-3 + 10 * (y)) + +//--- +// Rendering +//--- + +static void engine_draw_player(struct player const *player) +{ + extern bopti_image_t img_spritesheet; + + dsubimage(CELL_X(player->x) - 1, CELL_Y(player->y) - 5, + &img_spritesheet, player->dir * 12, 0, 12, 16, DIMAGE_NONE); +} + +void engine_draw(struct game const *game) +{ + dclear(C_WHITE); + + for(int p = 0; game->players[p]; p++) + { + engine_draw_player(game->players[p]); + } +} + +//--- +// Physics +//--- + +/* Check whether a cell of the map is walkable */ +static int map_walkable(struct map const *map, int x, int y) +{ + /* TODO: Read the map's data array */ + return (x >= 1) && (y >= 1) && (x < map->w - 1) && (y < map->h - 1); +} + +int engine_move(struct game *game, struct player *player, int dir) +{ + int dx = (dir == DIR_RIGHT) - (dir == DIR_LEFT); + int dy = (dir == DIR_DOWN) - (dir == DIR_UP); + + /* Always update the direction */ + player->dir = dir; + + /* Only move the player if the destination is walkable */ + if(!map_walkable(game->map, player->x + dx, player->y + dy)) return 0; + + player->x += dx; + player->y += dy; + + return 1; +} diff --git a/src/engine.h b/src/engine.h new file mode 100644 index 0000000..2dc81bf --- /dev/null +++ b/src/engine.h @@ -0,0 +1,55 @@ +#ifndef _MYSTNB_ENGINE_H +#define _MYSTNB_ENGINE_H + +#include + +#define PLAYER_COUNT 1 + +/* Directions */ +#define DIR_DOWN 0 +#define DIR_RIGHT 1 +#define DIR_UP 2 +#define DIR_LEFT 3 + +/* struct player: A player on the map, triggering actions as they move */ +struct player +{ + /* Position in map */ + int x, y; + /* Direction currently facing */ + int dir; + /* Animation and frame */ + struct animation const *anim; + int frame; +}; + +/* struct map: A map with moving doors, collectibles, and fog */ +struct map +{ + /* Width and height */ + int w, h; + /* Whether fog is enabled */ + int fog; + /* Raw data */ + uint8_t *data; +}; + +/* struct game: A running game with a map and some players */ +struct game +{ + /* Current map */ + struct map *map; + /* Players */ + struct player *players[PLAYER_COUNT + 1]; + /* Current game time (ms) */ + int time; +}; + +/* Draw the current game frame from scratch; does not dupdate() */ +void engine_draw(struct game const *game); + +/* Try to move a player along a direction. Returns 1 if the move is successful, + 0 otherwise (collisions or out-of-bounds moves) */ +int engine_move(struct game *game, struct player *player, int direction); + +#endif /* _MYSTNB_ENGINE_H */ diff --git a/src/main.c b/src/main.c index 0a72769..19f21d4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,8 @@ #include #include +#include "engine.h" + static void draw_menu(int selected) { extern bopti_image_t img_title; @@ -31,7 +33,7 @@ static void draw_menu(int selected) } } -int main(void) +static int main_menu(void) { extern font_t font_mystere; dfont(&font_mystere); @@ -52,5 +54,59 @@ int main(void) selected++; } + return selected; +} + +/* Returns a direction to move in */ +static int get_inputs(void) +{ + int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; + + while(1) + { + int key = getkey_opt(opt, NULL).key; + + if(key == KEY_DOWN) return DIR_DOWN; + if(key == KEY_RIGHT) return DIR_RIGHT; + if(key == KEY_UP) return DIR_UP; + if(key == KEY_LEFT) return DIR_LEFT; + } +} + +int main(void) +{ + GUNUSED int level = main_menu(); + + struct player singleplayer = { + .x = 2, + .y = 3 + }; + struct map map = { + .w = 13, + .h = 7 + }; + struct game game = { + .map = &map, + .players = { &singleplayer, NULL }, + .time = 0, + }; + + int level_finished = 0; + + while(!level_finished) + { + int turn_finished = 0; + while(!turn_finished) + { + engine_draw(&game); + dupdate(); + + int dir = get_inputs(); + turn_finished = engine_move(&game, &singleplayer, dir); + } + + /* Update doors, etc */ + } + return 1; }