From 74d30dc575fa97a666c7a04c46a178b282ac3469 Mon Sep 17 00:00:00 2001 From: mibi88 <76903855+mibi88@users.noreply.github.com> Date: Sat, 27 Jul 2024 15:26:55 +0200 Subject: [PATCH] Revert "Merge branch 'dev' of git.planet-casio.com:Slyvtt/Collab_RPG" This reverts commit 685e4b8824b1f210c43b0f0dc1a94ef560172aa0, reversing changes made to 9929e7bb08173286cd70e56f8f189f71b290bfb9. --- .gitignore | 1 - CMakeLists.txt | 78 +++++--------- PROJECT_STRUCTURE.md | 26 ----- README.md | 10 +- README_en.md | 44 -------- STYLE.md | 33 ------ assets-cg/NPC_Icon.png | Bin 0 -> 7249 bytes assets-cg/demo_PNJ.png | Bin 0 -> 4701 bytes assets-cg/demo_player.png | Bin 107 -> 5980 bytes assets-cg/ega64/tileset/tilesetEGA64_CG.png | Bin 11079 -> 41926 bytes assets-cg/npc/char/fxconv-metadata.txt | 3 - assets-cg/npc/char/npc_male.png | Bin 167 -> 0 bytes assets-cg/npc/face/fxconv-metadata.txt | 12 --- assets-cg/npc/face/npc_female.png | Bin 510 -> 0 bytes assets-cg/npc/face/npc_male.png | Bin 494 -> 0 bytes assets-cg/npc/face/npc_milkman.png | Bin 544 -> 0 bytes assets-cg/npc/face/npc_police.png | Bin 555 -> 0 bytes assets-fx/2bpp_palette.png | Bin 77 -> 0 bytes assets-fx/NPC_Icon.png | Bin 0 -> 5942 bytes assets-fx/demo_PNJ.png | Bin 0 -> 4701 bytes assets-fx/demo_player.png | Bin 107 -> 105 bytes assets-fx/fxconv-metadata.txt | 10 +- assets-fx/npc/char/fxconv-metadata.txt | 3 - assets-fx/npc/char/npc_male.png | Bin 118 -> 0 bytes assets-fx/npc/face/fxconv-metadata.txt | 12 --- assets-fx/npc/face/npc_female.png | Bin 327 -> 0 bytes assets-fx/npc/face/npc_male.png | Bin 306 -> 0 bytes assets-fx/npc/face/npc_milkman.png | Bin 326 -> 0 bytes assets-fx/npc/face/npc_police.png | Bin 354 -> 0 bytes assets/converters.py | 79 +++++++------- assets/level0.tmx | 5 +- assets/level1.tmx | 3 +- assets/level2.tmx | 4 +- clean | 1 - src/config.h | 44 ++------ src/dialogs.c | 110 ++++++++++---------- src/dialogs.h | 42 ++++---- src/events.h | 64 ------------ src/game.c | 43 ++++---- src/game.h | 27 ++--- src/main.c | 8 +- src/map.c | 21 ++-- src/map.h | 49 ++------- src/memory.c | 2 +- src/memory.h | 10 +- src/npc.c | 10 +- src/npc.h | 2 - src/player.c | 101 ++++++------------ src/player.h | 57 ++++------ 49 files changed, 288 insertions(+), 626 deletions(-) delete mode 100644 PROJECT_STRUCTURE.md delete mode 100644 README_en.md delete mode 100644 STYLE.md create mode 100644 assets-cg/NPC_Icon.png create mode 100644 assets-cg/demo_PNJ.png delete mode 100644 assets-cg/npc/char/fxconv-metadata.txt delete mode 100644 assets-cg/npc/char/npc_male.png delete mode 100644 assets-cg/npc/face/fxconv-metadata.txt delete mode 100644 assets-cg/npc/face/npc_female.png delete mode 100644 assets-cg/npc/face/npc_male.png delete mode 100644 assets-cg/npc/face/npc_milkman.png delete mode 100644 assets-cg/npc/face/npc_police.png delete mode 100644 assets-fx/2bpp_palette.png create mode 100644 assets-fx/NPC_Icon.png create mode 100644 assets-fx/demo_PNJ.png delete mode 100644 assets-fx/npc/char/fxconv-metadata.txt delete mode 100644 assets-fx/npc/char/npc_male.png delete mode 100644 assets-fx/npc/face/fxconv-metadata.txt delete mode 100644 assets-fx/npc/face/npc_female.png delete mode 100644 assets-fx/npc/face/npc_male.png delete mode 100644 assets-fx/npc/face/npc_milkman.png delete mode 100644 assets-fx/npc/face/npc_police.png delete mode 100644 src/events.h diff --git a/.gitignore b/.gitignore index f834a6a..085829e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ /build-fx /build-cg /build-cg-push -/build-fxg3a /*.g1a /*.g3a diff --git a/CMakeLists.txt b/CMakeLists.txt index aa873c1..65291bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,7 @@ include(GenerateG1A) include(GenerateG3A) include(Fxconv) -find_package(Gint 2.11 REQUIRED) -# Gint 2.11 is required, because we're using the new macros like GINT_RENDER_RGB +find_package(Gint 2.9 REQUIRED) find_package(LibProf 2.4 REQUIRED) #set the color mode either to 1b or 2b @@ -37,12 +36,9 @@ set(ASSETS set(ASSETS_cg assets-cg/demo_player.png - assets-cg/npc/char/npc_male.png + assets-cg/demo_PNJ.png assets-cg/SignAction.png - assets-cg/npc/face/npc_male.png - assets-cg/npc/face/npc_female.png - assets-cg/npc/face/npc_milkman.png - assets-cg/npc/face/npc_police.png + assets-cg/NPC_Icon.png assets-cg/SGN_Icon.png assets-cg/INFO_Icon.png assets-cg/player_face.png @@ -63,12 +59,9 @@ set(ASSETS_cg_EGA64 set(ASSETS_fx assets-fx/demo_player.png - assets-fx/npc/char/npc_male.png + assets-fx/demo_PNJ.png assets-fx/SignAction.png - assets-fx/npc/face/npc_male.png - assets-fx/npc/face/npc_female.png - assets-fx/npc/face/npc_milkman.png - assets-fx/npc/face/npc_police.png + assets-fx/NPC_Icon.png assets-fx/SGN_Icon.png assets-fx/INFO_Icon.png assets-fx/player_face.png @@ -92,8 +85,29 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} ) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} ) -elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A) - add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} ) +endif() + +# fx colormode +if("${COLORMODE_fx}" STREQUAL 1b) + target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT) +endif() + + +if("${COLORMODE_fx}" STREQUAL 2b) + target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT) +endif() + +# cg colormode +if("${COLORMODE_cg}" STREQUAL 1b) + target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT) +endif() + +if("${COLORMODE_cg}" STREQUAL 2b) + target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT) +endif() + +if("${COLORMODE_cg}" STREQUAL EGA64) + target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOREGA) endif() target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage) @@ -101,14 +115,6 @@ target_link_libraries(myaddin LibProf::LibProf Gint::Gint) if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) - # fx colormode - if("${COLORMODE_fx}" STREQUAL 1b) - target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT) - endif() - - if("${COLORMODE_fx}" STREQUAL 2b) - target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT) - endif() if("${COLORMODE_fx}" STREQUAL 1b) generate_g1a(TARGET myaddin OUTPUT "RPG_1b.g1a" @@ -121,20 +127,7 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) endif() - elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) - # cg colormode - if("${COLORMODE_cg}" STREQUAL 1b) - target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT) - endif() - - if("${COLORMODE_cg}" STREQUAL 2b) - target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT) - endif() - - if("${COLORMODE_cg}" STREQUAL EGA64) - target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOREGA) - endif() if("${COLORMODE_cg}" STREQUAL 1b) generate_g3a(TARGET myaddin OUTPUT "RPG_1b.g3a" @@ -151,19 +144,4 @@ elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) NAME "RPG PC EGA" ICONS assets-cg/ega64/icon-uns-ega64.png assets-cg/ega64/icon-sel-ega64.png) endif() - - -elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A) - - if("${COLORMODE_fx}" STREQUAL 1b) - generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a" - NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png) - endif() - - if("${COLORMODE_fx}" STREQUAL 2b) - generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a" - NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png) - endif() - - endif() diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md deleted file mode 100644 index 8ddbd80..0000000 --- a/PROJECT_STRUCTURE.md +++ /dev/null @@ -1,26 +0,0 @@ -# Project structure - - * `assets` contains the tiled maps, and the tiled map converters. - * `assets-cg` contains the assets for cg calculators like the cg-50. - * `assets-fx` contains the assets for monochrome calculators. - * `captures` contains screenshots. - * `src` This folder contains the source code. - * `config.h` This header file contains defines for the size of various - things on screen, like the size of a tile in the tilemap, the size of the - dialog box, etc. - * `dialogs.c` and `dialogs.h` contain various functions to display dialogs - and also let the user respond. - * `events.c` and `events.h` parse tags in the messages that are displayed - using the dialogs procedures to modify variables (and soon, call - procedures). - * `game.c` and `game.h` handles the rendering, the input, etc. - * `main.c` handles the USB connection and the gint gray rendering, for 2bpp - rendering on monochrome calculators. Contains the mainloop. Also contains - code to display debug informations. - * `map.c` and `map.h` contain code to render, get a tile in the map, see if - the tile is walkable, etc. - * `mapdata.h` contains the available maps. - * `memory.c` and `memory.h` procedures to handle arrays (currently: search - in an array of short ints). - * `npc.c` and `npc.h` npc rendering and movement (and soon pathfinding). - * `player.c` and `player.h` handle the player movement, collision, etc. diff --git a/README.md b/README.md index 09d5ec3..03c5af6 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,7 @@ Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html) -## Contribuer! -Style du code [STYLE.md](STYLE.md). - -Structure du projet [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md). - -## Avancement du projet +## Avencement du projet A ce stade, on a déjà implémenté : @@ -18,13 +13,12 @@ A ce stade, on a déjà implémenté : - [x] Multiple cartes avec importation automatique des fichiers `world` issus de Tiled - [x] Carte Multilayer (Background, Foreground + accessibilité / Dommages) avec transparence du calque Foreground - [x] Personnage -- [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés + limite d'un kibibyte) +- [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés) - [x] Fontes de caractères - [x] Interaction - [ ] NPC - [x] Changement de map durant le jeu - [ ] Système d'événements -- [ ] Pathfinding ## Crédits diff --git a/README_en.md b/README_en.md deleted file mode 100644 index 7a892d8..0000000 --- a/README_en.md +++ /dev/null @@ -1,44 +0,0 @@ -# Planet Casio Collaborative Project - -(maybe I should've used google translate) - -More informations can be found here (in french): -[Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html) - -## Contribute! -Style guidelines [STYLE.md](STYLE.md). - -Project structure [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md). - -## Current state - -What we've implemented so far: - -- [x] Screenshots via USB -- [x] Displaying the current map at the players position -- [x] Handling keyboard inputs -- [x] Handling collisions. -- [x] Multiple maps with automatic `world` files import (made with Tiled) -- [x] Multilayer map (Background, Foreground + accessibility / damage) with - foreground layer transparency. -- [x] Player character. -- [x] Dialogs from external `json` files (line jumps and words bigger than the - screen are unsupported + 1 kibibyte per message limit) -- [x] Font -- [x] Interaction -- [ ] NPC -- [x] Changing map in game. -- [ ] Event system -- [ ] Pathfinding - - -## Credits - -The tiles are from Game Boy Top-down RPG Fantasy Tileset (FREE) -"Background Assets by Gumpy Function (gumpyfunction.itch.io)" -[Tiles Background Assets by Gumpy Function](https://gumpyfunction.itch.io/game-boy-rpg-fantasy-tileset-free) - -Converted to greyscale with gimp. - -1-bit (black and white) version by Shadow15510 -CG (palette EGA64) color version by Fcalva diff --git a/STYLE.md b/STYLE.md deleted file mode 100644 index dc9e7e7..0000000 --- a/STYLE.md +++ /dev/null @@ -1,33 +0,0 @@ -# Style guidelines in Collab RPG - -(Mibi88) Fcalva, SlyVTT: What do you think of this? - -Wrap the code on 80 columns. Align the wrapped code with the last parantheses, -etc. - -Use curly braces with if, else, while and for statements if they can't hold on a -single line. - -Put the curly braces after if, else, while or for statements and declarations of -procedures on the same line. - -No spaces around parantheses, one space after a comma. - -Variables names in sneak_case. - -(Mibi88) SlyVTT, Fcalva, should be use a doc generation thing or do we describe -the procedures as I did so far? - -Document your procedures as following: - -```C -/* procedure_name() - * - * Describe what this procedure does. - * arg1: Describe this argument. If the text is too long, wrap it to the - * next line like this. - * long_name: Describe this argument, and so on. - */ -``` - -Have I forgotten something? diff --git a/assets-cg/NPC_Icon.png b/assets-cg/NPC_Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e9cc81921b5f2657915dd33d759f9e273020b46a GIT binary patch literal 7249 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 literal 0 HcmV?d00001 diff --git a/assets-cg/demo_PNJ.png b/assets-cg/demo_PNJ.png new file mode 100644 index 0000000000000000000000000000000000000000..8198c5931a59c0c185c422ed67b214b778ce33f0 GIT binary patch literal 4701 zcmeHKc~leU77vyRMYe~6h(693cqqjrlaT!p1OZLN00snW-6qLQ7|BK!5^+Hh@rh6r ztX3W_=tEHv7YddtARypMg(8YjaYYX*3bvr7>iZH<;k^FiIj{ebb0(SjzTf@bdw=(S z_hdFlgw3(DakC*12zCN~un7EGn=Wfh@U0x10KPw4oEWuGCqfL6TBE{nIST1ks!<3v z;uwKoy!C9SO4AP6)>dlM+^e!2o$9NWV~HEwD;?UNNZkAG&YtJdG zd!NW0W~zInk^fq;M>BVP(RY&0E~)6g5Pze8^3>ZllO|;(wr%Vsd!E%_BS)0tLhm!>d#lgNAHIFdT+ngI z_~krScV_tWs{>rwmHp=} zkN)g`_;OT>+da&dn%YMwr`s*qm~zZe_iW*H=g>T%J|{lr(s`)STXbO7?j0qCQQO21 z{&6C&dhu5+vnSraqIb+@E4$=b`RhGGmz>bS&L)blpDto%Jpk;e^|sSpMnkfaq(< z0U>420#B8WJ4duV#!t1h46s|Z!AV#r4~Cm83LyQC3%=G{zhrq{obS0lq;Ll+DZ2|3L$IOUzzv6Ysb>-H{R}QA%caXVfHCGijLSvKTr?!Mm zOjys_zo9*{J-OCL`Nt9svhSaQ?mcZDD-^5ku77*8blj%H*~|O$l6tC_*6sXd$t3?S z_SbLYX053x&L6n{SS@a!c_}qU>U-%$n%uwdaa`--kc|#bFN*Ko_1<(F+zNXt`5DW6 z8EfrIemdyB)Z^ua1KB>mAN3iyeCn=q>*~^h@QbOBW>oY)7VO$GC;YP9y*vOj{+dzz zX#S)MZC~zpw_fK~_czqMTh^*7y(4RQmGm3y`i=+P&5s4q1cHSJ9uyQI2nu?C&cNx) z-MzJPZcW65x}?MVLnc_gv%Tk7RdPq{weyIhjSV&W1UFxhR_mGSng42R#b*C`R)H^^ z+nsaYD0OOh%S8W%%ou>IgE<-l|)>e_^xz@35eon}}X+6sAvs14Y z?e)rjQU7y0#%Ulo2$$We%dhu#X9jtt3kn_=U|m!0pE%wna#V*43UVBevaZjo%_!KO zeL1gy(xhB4U+Z$0HKKKJ-35g<2^5K(EvesQ~n#7!fsvN`@&41!cH}Ru_^0NQMIX zQwwbrnC=u2s#WPV5;PSV}@U2oq&s7z<`FN3v^Gn9hJ`&_Ef;6l4P$$eax{-7KZ|NVFjqHR%M? zd`U2yL}f%#VJ?l$g{eL;jSIs>%22`-)2V)+u^;7sH1RV7hK&JWH@F7I3z$}v594Y` zGn0&e;b*88f1w9JJ?i9>^c|IJRIX1_;FG|k-8CxLCn@kr;L+~-zsY6u@r4Iff`35< z@H(UEZ9V~Bg~o_O=L8c7M>0HU;OPrB|0^wlFmAl*vLNK-x`IV3oj@33^~l=6dWr@7 zuyZX~q6&foqpWW%*b?YOfUL*F9DJA5YA^lV%4*{DoUO0;lW*EDUAqOh*=LMtpW(I! b>&vr?X4u*!w6<0PV}c+gEVyXa^5p*l{ImZ0 literal 0 HcmV?d00001 diff --git a/assets-cg/demo_player.png b/assets-cg/demo_player.png index 7c1da00eb6988b570c732a4e62908d67d942a06f..04c4d34e3fb3e8de9e04e87710feb7d90715a058 100644 GIT binary patch literal 5980 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 delta 78 zcmcbkmpwt*gTctt#W93qX6%`RoD7BnOa}^ozrR_{V&-1c(Is`o)veoVO|o|TXTL?} ioX5@|Saa*-=Z}orzwolZPfA?O00f?{elF{r5}E++tRTw( diff --git a/assets-cg/ega64/tileset/tilesetEGA64_CG.png b/assets-cg/ega64/tileset/tilesetEGA64_CG.png index 44ba3a79db6e5f6de5611dc8318d0b3e872cac3c..86428c6e4f569be4eebaf553f1a1c4b7fe5c3099 100755 GIT binary patch literal 41926 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 diff --git a/assets-cg/npc/char/fxconv-metadata.txt b/assets-cg/npc/char/fxconv-metadata.txt deleted file mode 100644 index b7658e5..0000000 --- a/assets-cg/npc/char/fxconv-metadata.txt +++ /dev/null @@ -1,3 +0,0 @@ -npc_male.png: - type: bopti-image - name: demo_PNJ_img diff --git a/assets-cg/npc/char/npc_male.png b/assets-cg/npc/char/npc_male.png deleted file mode 100644 index f4d654b78a21d9e7ef7fc130ef3eeb94c69d9e5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6@;qG}Lo_B%y|9t@kb?;Gh3|sF zDZM;Gvq}=JUU&$yos^1voS~<1K~^U3&)3|@P02@eHIsPwQeU=C@UTccdHyfof0YBK zpTCGi3stR|Dpp&}y`zTX`5AlRdpw(e?q1mPxS`rrCQ4}0;jo(vvu{3R^x7hntR4F% Q4rnujr>mdKI;Vst0PJKwUH||9 diff --git a/assets-cg/npc/face/fxconv-metadata.txt b/assets-cg/npc/face/fxconv-metadata.txt deleted file mode 100644 index 664ce84..0000000 --- a/assets-cg/npc/face/fxconv-metadata.txt +++ /dev/null @@ -1,12 +0,0 @@ -npc_male.png: - type: bopti-image - name: npc_male -npc_female.png: - type: bopti-image - name: npc_female -npc_milkman.png: - type: bopti-image - name: npc_milkman -npc_police.png: - type: bopti-image - name: npc_police diff --git a/assets-cg/npc/face/npc_female.png b/assets-cg/npc/face/npc_female.png deleted file mode 100644 index 16321ae9686c47ee3c62fd877c6c897e4b36d061..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 510 zcmV=!V<@N#i(@>;zhwbMhtx|8*_PpFo5o&;e(F z00BW!N-RihXsX?cW?!oPM|g~42YdscQYpjwBk-kV4)qKY?gZ>vs+f0^Kt)gP1ompq z8n3q$5h=J6*ajf`z^muqkUN2G0CIf#OCQL3bSI!kLPaT@P?27eJArB+(A**v@=A&C zLExE1G3%f;0@bS^w?v{+Qzln~1cdn?JpI(C-I#m7RmO@74H8gvVm$qxo+y*coxps0 z1RuC4mCwnyRc6vjYjL28K&gS6GFp%B1hxSzJ`ts=ng5dBo4_j$&+Y{Ne*kd`&Yi$w zA1Li|x9orEj^Iw9xEDxC7p6NQJjmqM%Nyfw1X~;d&eMm0+UrRSYLY8SfdDpIH%AKfznVBdy-aI zIPOpbXW$FKfkV(;Dx8qm&{(?#%_i0U!#zf^1Ac)|DQby(zg~nyb^`HPTIzg8PX!Z5 z=|0k1b^_Y~_G0Nf=3h~E0^0!OJP=s}mgNymufdnu3CO!Z(4387I0OfkPvAc(!9t>3 z0x6SWj6`+<+W^dYz@NX^`mo0JS_c8g*iHC(Zk(^|1k}^;Z9j@vaT-<*oRNZMp8L4U z!8It)P9XYbl$t=1Z${=!D9P$Rrgamry4Q996hJ`T1r=~jlo7QZ03{Ou#9VNiXz)kq zK%0Lkoq)CuE_Ao5o=&{FA39j?Jt3%P!liqDcTdgz**#+b zerxO53Cy}7v7G^lodNacQAP1y-Vr|JN-N)8AsYB2`~ZKRLv1YXv_ z5x8}BS|0x?O7m;EBdCGK3p_fw1+m!)jHa@8Un{{)_tf0`&b9g>g>nc?x%bs5<<`1B kg>ndBbe}?v*K>9Pe_?%HEo_NO=l}o!07*qoM6N<$g7zQWWB>pF diff --git a/assets-cg/npc/face/npc_milkman.png b/assets-cg/npc/face/npc_milkman.png deleted file mode 100644 index 98b92bfda1f2cec54fc9a2b23eab17ab935e6568..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmV+*0^j|KP)bd*Cg=Cvd)y*>ixOym^+b7VdAft)Ig6SFC_9;G1jq?~3yvs4PXJJAt6KUOD``(>EaUHPORILmma(4om23jVw4oX|iV)k-IJPrXZ%h(ngeyPdzz&`;?MssxG zm%x-cE}ygN!Y_fjrs)FmU9md>^E;t+Oly8YiP)WhNdtj=Of?EtKWW_wj5-%A66_%~ z5Z?8=?azr0000U0^5~a<_8BncThVOqjewa6HO=sG zG}3Yi$f3)TD7A}P27$nRH0k?PJE`gfCgp)yoGl^`Gyy^(g_3cOc1?g|QeK^ao!)d>{u zhCOBbe-O4M@=u`QHj`y!DG9AywzX89K+%m!$!UpYle;Ye2LwiQK;D*|xtw}y<6Ck@ z&;p$>^nYU#qi?yK@u#;Y@!a2vUPhj_i+!dP{1A}Q!!6o2`7P_x(-0Z?Zg|FT0gHkk t0@h8LHWy@F%#NvzB#`zYZ_la|_yJ?9dnngfgi-(i002ovPDHLkV1iqg{-^)| diff --git a/assets-fx/2bpp_palette.png b/assets-fx/2bpp_palette.png deleted file mode 100644 index 05dc19da38d7d0adb4bde11eacaf2b43cd4a6cde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7!2%?oUYxrTNQrp5IEHY{OiuW5{>k|RB8Luq b_;1f3Xvw_P-D`3tP@cil)z4*}Q$iB}#ljW* diff --git a/assets-fx/NPC_Icon.png b/assets-fx/NPC_Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b353607ca16e021c204289bfe22ad0b705ac7309 GIT binary patch literal 5942 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 b>&vr?X4u*!w6<0PV}c+gEVyXa^5p*l{ImZ0 literal 0 HcmV?d00001 diff --git a/assets-fx/demo_player.png b/assets-fx/demo_player.png index 7c1da00eb6988b570c732a4e62908d67d942a06f..e522e612611bb1d9bae1b69e51e570bc385878f4 100644 GIT binary patch delta 74 zcmd1KoS@=r;OXKR!Z9;B<;VF3rU;1u7YWH33L;G@NeK-rfA$MFgdJp>nB1~DA<-d- dFR(pLmqALAL-@kV>#Ynx;OXk;vd$@?2>{z68K3|F delta 76 zcmd1Io}l7xk5tY$HDuj%NLy5j2AZM7y@yZy7@B6H4T g=MSv8b@KB^#_eBt+21E6E@l7%Pgg&ebxsLQ0K1bQDgXcg diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt index 12e9d02..499f659 100644 --- a/assets-fx/fxconv-metadata.txt +++ b/assets-fx/fxconv-metadata.txt @@ -2,6 +2,10 @@ demo_player.png: type: bopti-image name: demo_player_img +demo_PNJ.png: + type: bopti-image + name: demo_PNJ_img + player_face.png: type: bopti-image name: player_face_img @@ -14,6 +18,10 @@ INFO_Icon.png: type: bopti-image name: INFO_Icon_img +NPC_Icon.png: + type: bopti-image + name: NPC_Icon_img + SGN_Icon.png: type: bopti-image name: SGN_Icon_img @@ -26,4 +34,4 @@ font.png: grid.padding: 1 grid.border: 0 proportional: true - height: 5 + height: 5 \ No newline at end of file diff --git a/assets-fx/npc/char/fxconv-metadata.txt b/assets-fx/npc/char/fxconv-metadata.txt deleted file mode 100644 index b7658e5..0000000 --- a/assets-fx/npc/char/fxconv-metadata.txt +++ /dev/null @@ -1,3 +0,0 @@ -npc_male.png: - type: bopti-image - name: demo_PNJ_img diff --git a/assets-fx/npc/char/npc_male.png b/assets-fx/npc/char/npc_male.png deleted file mode 100644 index 639504e9570e3a5665dffcd87298f86dcfd5ce8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^93afW0wnX;%77$;t*47)2*=FSGY5Ga90Z&$nqPik zw&3c^i*g?~xb^;HZe-Co;=J{UK=4wP8ygo~DGxeSwp7&iZDDv-h4DXm_5Nu7H)};? Qeu7N$boFyt=akR{0IRbn!2kdN diff --git a/assets-fx/npc/face/fxconv-metadata.txt b/assets-fx/npc/face/fxconv-metadata.txt deleted file mode 100644 index 664ce84..0000000 --- a/assets-fx/npc/face/fxconv-metadata.txt +++ /dev/null @@ -1,12 +0,0 @@ -npc_male.png: - type: bopti-image - name: npc_male -npc_female.png: - type: bopti-image - name: npc_female -npc_milkman.png: - type: bopti-image - name: npc_milkman -npc_police.png: - type: bopti-image - name: npc_police diff --git a/assets-fx/npc/face/npc_female.png b/assets-fx/npc/face/npc_female.png deleted file mode 100644 index b8ac9b6e831cc1bda72121d5f870e38df24e01a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 327 zcmV-N0l5B&P)kdg0003FNkl~*c;c@ILKk#qk*KgE&?*N_>-Ni2|G1baSSAydfSxhG1s5fU(P#|NZ zN@D0$eG_Lvqo63=wc>P|@7XI*;zFq1toMAGkdg0002_NklCdwX|s7J*LfUVQa zO;<4wUc`@f^6K?*(fDp#FX<;%CA7pbEXKry-65ye|r5Szu{kLx14!4OG~_*o~|V9w}& zhz3Ig(m!(Nu{qW=6>R|0xTPxn@DAA|M{NfP`&bL&1%8KWkKGex-v9sr07*qoM6N<$ Efkdg0003ENkl*@&`NJOlgPBT9OZzuFFRSH!g<>F)Fp5k@*-(Go%42uqle zta&T9N=s1(HHjU*P6$|}j&&^sfm$R?u^{B4zyAo;JQt6$H&b8+FJ%3Z{UOLXKO|u8 z8uE$+^c3b+7Sd~&e`$PX?!`6R+&dhz%51J0P7(RI=qx^yQx+7HPj7)I$x%uGvbm~= z;ua7ZNYzZZE+8!iWO9hevB#~JoO;wEYau!|7`kdg0003gNklsz<0>5@+&#phEnq7Dd-}# zR}xSJ?>b`pI~(pUh~u*^ajmF}q**M1An33FWVpl(2FKtU6ws0TyObx<281;i4-37* zynZ8zRqz)|Uqp)64R5fP$x-&+ruVW$I5J_tFGwAFiQ@uylK=n!07*qoM6N<$g4e{5 A?*IS* diff --git a/assets/converters.py b/assets/converters.py index 7143aba..7b19bc8 100644 --- a/assets/converters.py +++ b/assets/converters.py @@ -6,7 +6,6 @@ import pathlib import csv import os -DEBUG = 0 def convert(input, output, params, target): if params["custom-type"] == "map": @@ -35,8 +34,8 @@ def convert_world(input, output, params, target): data = json.load(open(input, "r")) nbMaps = ["fileName" in i for i in data["maps"]].count(True) - if DEBUG: print( "We have to treat ", nbMaps, " maps") - if DEBUG: print( "So let's go ... ") + print( "We have to treat ", nbMaps, " maps") + print( "So let's go ... ") structWorld = fxconv.Structure() #structExtra = fxconv.Structure() @@ -52,26 +51,26 @@ def convert_world(input, output, params, target): nameJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" commandline = 'tiled --export-map json ' + nameTMX + ' ' + nameJSON - if DEBUG: print( "TILED COMMAND LINE FOR MAPS : ", commandline ) + print( "TILED COMMAND LINE FOR MAPS : ", commandline ) os.system( commandline ) mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" - if DEBUG: print("Map ", i , " name : ", mapPath ) + print("Map ", i , " name : ", mapPath ) xmin = data["maps"][i]["x"] - if DEBUG: print( "xmin = ", xmin ) + print( "xmin = ", xmin ) ymin = data["maps"][i]["y"] - if DEBUG: print( "ymin = ", ymin ) + print( "ymin = ", ymin ) xmax = data["maps"][i]["x"] + data["maps"][i]["width"] - if DEBUG: print( "xmax = ", xmax ) + print( "xmax = ", xmax ) ymax = data["maps"][i]["y"] + data["maps"][i]["height"] - if DEBUG: print( "ymax = ", ymax ) + print( "ymax = ", ymax ) map = get_tile_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax) - if DEBUG: print( "Map = ", map ) + print( "Map = ", map ) structWorld += fxconv.ptr( map ) structWorld += fxconv.u32(0) @@ -86,7 +85,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): #find the tileset in use. it's a relative path (like ../tileset.tsx) nameTileset = data["tilesets"][0]["source"].replace(".tsx","") - if DEBUG: print(nameTileset) + print(nameTileset) #the name of the tileset without the .something nameTilesetFree = nameTileset.split("/")[-1] #count the number of "back" (cd ..) to locate the tileset on the computer @@ -96,7 +95,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): tilesetJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".json" commandline = 'tiled --export-tileset json ' + tilesetTSX + ' ' + tilesetJSON - if DEBUG: print( "TILED COMMAND LINE FOR TILESET : ", commandline ) + print( "TILED COMMAND LINE FOR TILESET : ", commandline ) os.system( commandline ) tileset = open(tilesetJSON, "r") @@ -106,14 +105,14 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): #find the ID of the first tile in the walkable tileset () indexWalkable = data["tilesets"][1]["firstgid"] - if DEBUG: print(indexWalkable) + print(indexWalkable) #Extract from the json the width, height w, h = data["width"], data["height"] #nbTileLayer is the number of "true" layers (without ObjectsLayer) nbTilelayer = ["data" in i for i in data["layers"]].count(True) - 1 - if DEBUG: print( nbTilelayer) + print( nbTilelayer) #index of the various layers (may change from one map to another) layer_walkable = 0 @@ -136,7 +135,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): datavalid = data["layers"][i] if datavalid["name"]=="Walkable": layer_walkable = i - if DEBUG: print( "Walkable Tile Data in layer : ", layer_walkable) + print( "Walkable Tile Data in layer : ", layer_walkable) break elif i==nbTilelayer: print( "ERROR : No Walkable layer data !!!" ) @@ -169,7 +168,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): nameDialog = data["properties"][0]["value"] dialogfile = "/".join(input.split("/")[:-nbRetour]) + "/" + nameDialog - if DEBUG: print( "THE DIALOGS ARE CONTAINED IN THE FILE : ", dialogfile ) + print( "THE DIALOGS ARE CONTAINED IN THE FILE : ", dialogfile ) nbdiag = 0 diagdata = fxconv.Structure() @@ -193,7 +192,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): datavalid = data["layers"][i] if datavalid["name"]=="Background": layer_background = i - if DEBUG: print( "Background Tile Data in layer : ", layer_background) + print( "Background Tile Data in layer : ", layer_background) break elif i==nbTilelayer: print( "ERROR : No Background layer data !!!" ) @@ -211,10 +210,10 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): datavalid = data["layers"][i] if datavalid["name"]=="Foreground": layer_foreground = i - if DEBUG: print( "Foreground Tile Data in layer : ", layer_foreground) + print( "Foreground Tile Data in layer : ", layer_foreground) break elif i==nbTilelayer: - print( "ERROR : No Foreground layer data !!!" ) + printf( "ERROR : No Foreground layer data !!!" ) layer_data = bytes() layer = data["layers"][layer_foreground] @@ -228,11 +227,11 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): - if DEBUG: print( "WE ARE COMPUTING THE EXTRA DATA OF THE MAP : ", input ) + print( "WE ARE COMPUTING THE EXTRA DATA OF THE MAP : ", input ) data = json.load(open(input, "r")) nblayer = ["id" in i for i in data["layers"]].count(True) - 1 - if DEBUG: print( "I found ", nblayer, " of extradata") + print( "I found ", nblayer, " of extradata") #index of the various layers (may change from one map to another) layer_extradata = 0 @@ -242,7 +241,7 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): datavalid = data["layers"][i] if datavalid["name"]=="ExtraData": layer_extradata = i - if DEBUG: print( "Extra Data in layer : ", layer_extradata) + print( "Extra Data in layer : ", layer_extradata) break elif i==nblayer: print( "ERROR : No ExtraData layer data !!!" ) @@ -273,7 +272,6 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): path_length = 0 xdata = None ydata = None - face_type = "MALE" #we now fill all the properties of this item for j in i["properties"]: @@ -283,45 +281,42 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): elif j["name"]=="needAction": needAction = j[ "value" ] else: - #Extra properties for NPCs (path and face) + #Extra properties for NPCs (path) if tpe=="NPC": - if j["name"]=="face": - face_type = j["value"] - elif j["name"]=="hasPath": + if j["name"]=="hasPath": pathID = None path = j[ "value" ] if path==1: - if DEBUG: print( "PNJ has path - NOW LOOKING FOR RELEVANT DATA" ) + print( "PNJ has path - NOW LOOKING FOR RELEVANT DATA" ) # we start looking for path data with first the ID of the path Object for u in i["properties"]: if u["name"]=="path": pathID = u[ "value" ] - if DEBUG: print( "path ID is identified : ID= ", pathID ) + print( "path ID is identified : ID= ", pathID ) for v in layer["objects"]: if v[ "id" ] == pathID: - if DEBUG: print( "path data found : " ) + print( "path data found : " ) xdata = bytes() ydata = bytes() for w in v[ "polyline" ]: path_length = path_length + 1 - if DEBUG: print( "X= ", w[ "x" ], " Y= ", w[ "y" ] ) + print( "X= ", w[ "x" ], " Y= ", w[ "y" ] ) xdata += fxconv.u16( int( w[ "x" ] ) ) ydata += fxconv.u16( int( w[ "y" ] ) ) else: - if DEBUG: print( "PNJ has no Path" ) + print( "PNJ has no Path" ) else: print( "UNIDENTIFIED PROPERTY : ", j["name"]) - if DEBUG: - print( "OBJECT X= ", x, " Y= ", y, "STR= ", dialogID ) - print( " Type= ", tpe, " Name= ", nme, "Face =", face_type) - print( " Action?= ", needAction ) + print( "OBJECT X= ", x, " Y= ", y, "STR= ", dialogID ) + print( " Type= ", tpe, " Name= ", nme ) + print( " Action?= ", needAction ) @@ -329,7 +324,6 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): structData += fxconv.u32( int(y) ) structData += fxconv.string( nme ) structData += fxconv.string( tpe ) - structData += fxconv.string(face_type) structData += fxconv.u32( int(dialogID) ) structData += fxconv.u32( int(needAction) ) @@ -351,8 +345,9 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): #else we do nothing (yet) else: - if DEBUG: print( "Skip this object" ) + print( "Skip this object" ) + return nbExtraData, structData @@ -377,16 +372,16 @@ def convert_font(input, output, params, target): def convert_dialogs(input, output, params, target): - if DEBUG: print( "WE ARE COMPUTING THE DIALOGS FROM : ", input ) + print( "WE ARE COMPUTING THE DIALOGS FROM : ", input ) data = json.load(open(input, "r")) structDialogs = fxconv.Structure() nbdialogs = 0 for d in data["dialogs"]: - if DEBUG: print( int(d[ "ID" ])) + print( int(d[ "ID" ])) # print( d[ "dialog" ] ) - if DEBUG: print( int(d[ "isQuestion" ]) ) + print( int(d[ "isQuestion" ]) ) # print( d[ "choice" ].replace('$', chr(0)) ) # print( d[ "conclusion1" ] ) # print( int(d[ "next1" ] ) ) @@ -407,4 +402,4 @@ def convert_dialogs(input, output, params, target): return nbdialogs, structDialogs - #fxconv.elf(structDialogs, output, "_" + params["name"], **target) + #fxconv.elf(structDialogs, output, "_" + params["name"], **target) \ No newline at end of file diff --git a/assets/level0.tmx b/assets/level0.tmx index 553ed3b..4cf2838 100644 --- a/assets/level0.tmx +++ b/assets/level0.tmx @@ -1,5 +1,5 @@ - + @@ -117,7 +117,6 @@ - @@ -127,7 +126,6 @@ - @@ -137,7 +135,6 @@ - diff --git a/assets/level1.tmx b/assets/level1.tmx index b635cb5..c3af03c 100644 --- a/assets/level1.tmx +++ b/assets/level1.tmx @@ -1,5 +1,5 @@ - + @@ -100,7 +100,6 @@ - diff --git a/assets/level2.tmx b/assets/level2.tmx index b29cf1c..3592373 100644 --- a/assets/level2.tmx +++ b/assets/level2.tmx @@ -1,5 +1,5 @@ - + @@ -37,7 +37,7 @@ 250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,297,298,299,300,0,0,0,225,226,227,228,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0, 274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,202,203,204,0,0,0,0,249,250,251,252,249,250,251,252,0,0,258,259,263,264,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,307,311,288,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,3,3,288,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,201,202,203,204,0,0,0,0,0,0,0,0,0,0,0,0,0,273,274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/clean b/clean index bcc4d2a..445982d 100755 --- a/clean +++ b/clean @@ -6,7 +6,6 @@ cd .. rm -r build-cg rm -r build-cg-push rm -r build-fx -rm -r build-fxg3a rm *.g1a rm *.g3a diff --git a/src/config.h b/src/config.h index a899255..ed692b7 100644 --- a/src/config.h +++ b/src/config.h @@ -2,55 +2,27 @@ #define CONFIG_H -#define USB_FEATURE 0 -#define DEBUGMODE 0 - -#include - -/* Enable GrayMode on either FX and FX_G3A targets */ -#if GINT_RENDER_MONO && defined(COLOR2BIT) +#if !defined(FXCG50) && defined(COLOR2BIT) #define GRAYMODEOK 1 #endif +#define USB_FEATURE 0 +#define DEBUGMODE 0 -#if GINT_RENDER_RGB - /* The tile size */ +#ifdef FXCG50 #define T_HEIGHT 16 #define T_WIDTH 16 - /* The size of a pixel */ - #define PXSIZE 2 - #define PATH_COLOR C_RED - /* The size of the player */ - #define P_WIDTH 16 - #define P_HEIGHT 16 #else - /* The tile size */ #define T_HEIGHT 8 #define T_WIDTH 8 - /* The pixel size */ - #define PXSIZE 1 - #define PATH_COLOR C_BLACK - /* The player size */ - #define P_WIDTH 8 - #define P_HEIGHT 8 #endif - -/* SPEED should NOT be 8 or bigger: it may cause bugs when handling - * collisions! */ -#define SPEED (PXSIZE*2) - -/* The face size (in the dialogs) */ -#define F_WIDTH (32*PXSIZE) -#define F_HEIGHT (32*PXSIZE) - -/* the color of the text to go to the next dialog phase */ -/* it improves readability to have something lighter */ -#if GRAYMODEOK || (GINT_RENDER_RGB && !defined(COLOR1BIT)) - #define NEXT_COLOR C_DARK +#ifdef FXCG50 + #define PXSIZE 2 #else - #define NEXT_COLOR C_BLACK + #define PXSIZE 1 #endif + #endif diff --git a/src/dialogs.c b/src/dialogs.c index 23a7890..4757303 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -25,11 +25,20 @@ extern font_t fontRPG; uint32_t *lightVRAMcurrent, *darkVRAMcurrent; #endif //GRAYMODEOK +/* the color of the text to go to the next dialog phase */ +/* it improves readability to have somathing lighter */ +#if GRAYMODEOK || (defined(FXCG50) && !defined(COLOR1BIT)) + #define NEXT_COLOR C_DARK +#else + #define NEXT_COLOR C_BLACK +#endif -void blit() { + +void blit() +{ dupdate(); - #if GRAYMODEOK && !GINT_HW_CG + #if GRAYMODEOK dgray_getvram( &lightVRAMnext, &darkVRAMnext ); dgray_getscreen( &lightVRAMcurrent, &darkVRAMcurrent ); @@ -39,14 +48,13 @@ void blit() { } -int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(Game *game, unsigned int i), - bool start_anim, - bool end_anim, - void for_each_screen(Game *game, unsigned int i), - int line_duration, bool update_screen, unsigned int start_i, - bool wait_continue) { - text = events_parse_string(&game->handler, text); +int showtext_opt(Game *game, bopti_image_t *face, char *text, + int call_before_end(Game *game, unsigned int i), + bool start_anim, + bool end_anim, + void for_each_screen(Game *game, unsigned int i), + int line_duration, bool update_screen, unsigned int start_i, + bool wait_continue) { dfont(&FONT_USED); unsigned int i, n, y = PXSIZE, l = 0; int line_max_chars, return_int = 0; @@ -59,7 +67,7 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, /* Redrawing the entire screen, because maybe there was no dialog displayed before. */ update_npc(game); - game_draw(game); + draw(game); /* Fill the dialog box with white */ drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); @@ -79,7 +87,7 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, }else{ /* Here I'm drawing the same as if start_anim is true, but whitout * making an animation. */ - game_draw(game); + draw(game); drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE); drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK); dimage(4*PXSIZE, 2*PXSIZE, face); @@ -140,12 +148,7 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, if(l>=max_lines_amount-1){ /* If we drew one entire screen. */ /* Wait that the SHIFT key is pressed if we should. */ - if(wait_continue){ - while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & - ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){ - sleep(); - } - } + if(wait_continue) while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep(); /* Clear the text area. */ drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2, C_WHITE); @@ -169,12 +172,7 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite..."); /* Update the screen and wait for SHIFT being pressed, if needed. */ if(update_screen) blit(); - if(wait_continue){ - while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & - ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){ - sleep(); - } - } + if(wait_continue) while(getkey_opt( GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep(); } if(call_before_end) return_int = call_before_end(game, i); if(end_anim){ @@ -182,11 +180,11 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, for(i=BOX_HEIGHT;i>0;i--){ /* It is the same as the start animation. */ update_npc(game); - game_draw(game); + draw(game); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, - DIMAGE_NONE); + DIMAGE_NONE); dupdate(); @@ -197,12 +195,12 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, return return_int; } -void dialogs_text(Game *game, bopti_image_t *face, char *text, - bool dialog_start, bool dialog_end) { +void showtext_dialog(Game *game, bopti_image_t *face, char *text, + bool dialog_start, bool dialog_end) { /* Run showtext_opt with some default values. It makes it easier to use in * simple dialogs. */ - dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, - true, 0, true); + showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, + true, 0, true); } @@ -303,9 +301,9 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) { for(i=DWIDTH/8+1;i>0;i--){ /* I'm drawing the same box as on the start animation */ update_npc(game); - game_draw(game); - dialogs_text_opt(game, _face, _text, NULL, false, false, NULL, 0, false, - _i, false); + draw(game); + showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, + _i, false); drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, @@ -321,9 +319,9 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) { return selected; } -int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start, - bool end, char *choices, int choices_amount, - int default_choice) { +int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, + bool end, char *choices, int choices_amount, + int default_choice) { /* Put some arguments in global pointers and variables to make them * accessible by _choice_call_before_end. */ _choices = choices; @@ -333,16 +331,16 @@ int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start, _text = text; /* Run showtext_opt and return his return value (the return value of *_choice_call_before_end) */ - return dialogs_text_opt(game, face, text, _choice_call_before_end, start, - end, _choice_screen_call, 100, true, 0, true); + return showtext_opt(game, face, text, _choice_call_before_end, start, end, + _choice_screen_call, 100, true, 0, true); } -void dialogs_initiate_sequence(Game *game, bopti_image_t *face, - uint32_t dialogNumber) { - Dialog *currentDiag = &game->map_level->dialogs[dialogNumber]; +void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNumber ) +{ + Dialog *currentDiag = &game->map_level->dialogs[ dialogNumber ]; /* we collect the information */ char *text = currentDiag->dialog; @@ -356,23 +354,27 @@ void dialogs_initiate_sequence(Game *game, bopti_image_t *face, int isQuestion = currentDiag->isQuestion; /* we treat the action - i.e. we show a dialog */ - if (isQuestion == 1){ - /* we have to manage a question */ - int answer = dialogs_ask(game, face, text, true, true, - choices, 2, 0); + if (isQuestion == 1) /* we have to manage a question */ + { + int answer = showtext_dialog_ask( game, face, text, true, true, choices, 2, 0 ); /* TO DO we need to split the strings conclusion1 and conclusion2 */ /* to extract the "gift" part */ - if(answer==0){ - dialogs_text(game, face, conclusion1, true, true); - if (next1!=-1) dialogs_initiate_sequence(game, face, next1); - }else{ - dialogs_text(game, face, conclusion2, true, true); - if (next2!=-1) dialogs_initiate_sequence(game, face, next2); + if (answer==0) + { + showtext_dialog( game, face, conclusion1, true, true ); + if (next1!=-1) initiate_dialog_sequence( game, face, next1 ); } - }else{ - dialogs_text(game, face, text, true, true); - if (nextOther!=-1) dialogs_initiate_sequence(game, face, nextOther); + else + { + showtext_dialog( game, face, conclusion2, true, true ); + if (next2!=-1) initiate_dialog_sequence( game, face, next2 ); + } + } + else + { + showtext_dialog( game, face, text, true, true ); + if (nextOther!=-1) initiate_dialog_sequence( game, face, nextOther ); } } \ No newline at end of file diff --git a/src/dialogs.h b/src/dialogs.h index d019d65..39729b7 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -5,9 +5,11 @@ #include #include "game.h" #include "map.h" -#include "config.h" -/* dialogs_text_opt() +#define F_WIDTH (32*PXSIZE) +#define F_HEIGHT (32*PXSIZE) + +/* showtext_opt() * * Show some text in a box with word wrap for dialogs. * @@ -35,17 +37,17 @@ * wait_continue: If I should wait that EXE is pressed after drawing a page. */ -int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(Game *game, unsigned int i), - bool start_anim, - bool end_anim, - void for_each_screen(Game *game, unsigned int i), - int line_duration, bool update_screen, - unsigned int start_i, bool wait_continue); +int showtext_opt(Game *game, bopti_image_t *face, char *text, + int call_before_end(Game *game, unsigned int i), + bool start_anim, + bool end_anim, + void for_each_screen(Game *game, unsigned int i), + int line_duration, bool update_screen, unsigned int start_i, + bool wait_continue); -/* dialogs_text() +/* showtext_dialog() * - * Calls dialogs_text_opt with default parameters. + * Calls showtext_opt with default parameters. * * game: The game struct of the current game. * face: A bopti_image_t of the face of the person who's saying this @@ -58,12 +60,12 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text, * shown at the end of showtext_opt. */ -void dialogs_text(Game *game, bopti_image_t *face, char *text, - bool dialog_start, bool dialog_end); +void showtext_dialog(Game *game, bopti_image_t *face, char *text, + bool dialog_start, bool dialog_end); -/* dialogs_ask() +/* showtext_dialog_ask() * - * Like dialogs_text, but lets the user choose between multiple possible + * Like showtext_dialog, but lets the user choose between multiple possible * choices after displaying the text. * * game: The game struct of the current game. @@ -83,12 +85,10 @@ void dialogs_text(Game *game, bopti_image_t *face, char *text, * default_choice: The choice choosen by default when the dialog just opened. */ -int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start, - bool end, char *choices, int choices_amount, - int default_choice); +int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, + bool end, char *choices, int choices_amount, + int default_choice); -/* TODO: Doc. */ -void dialogs_initiate_sequence(Game *game, bopti_image_t *face, - uint32_t dialogNumber); +void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNumber ); #endif diff --git a/src/events.h b/src/events.h deleted file mode 100644 index 0cd503d..0000000 --- a/src/events.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef EVENTS_H -#define EVENTS_H - -/* The max amount of variables that can be bound. */ -#define MAX_VARIABLES 32 -/* The max. size of the message buffer. - * WARNING: Bigger messages will be truncated! */ -#define MESSAGE_BUFFER_SZ 1024 -/* The maximal size of a token. Bigger tokens will be truncated. */ -#define TOKEN_MAX_SZ 1024 - -typedef struct { - int *variables[MAX_VARIABLES]; - char *var_names[MAX_VARIABLES]; - unsigned int vars; -} EventHandler; - -typedef enum { - T_NULL, - T_VAR_EDIT, - T_AMOUNT -} Token; - -typedef enum { - OP_NULL, - OP_SET, - OP_ADD, - OP_SUB, - OP_DIV, - OP_MUL, - OP_MOD, - OP_AMOUNT -} Operation; - -/* events_init_handler() - * - * Initialize an event handler. - * handler: The Event handler to initialize. - */ -void events_init_handler(EventHandler *handler); -/* events_bind_variable() - * - * Bind a variable. Binding a variable allows it to be modified by messages - * passed to the event handler using tags written as following: - * `variable+number` (The backticks delimit the tag). Available operators: - * '=': Assign a value to the variable. - * '+': Addition. - * '-': Substraction. - * '*': Multiplication. - * '/': Division. - * '%': Modulo. - * handler: The event handler. - * var: A pointer to the variable to bind. - * name: The name of the variable. This is the name that will be used to - * refer to this variable in a tag. - */ -int events_bind_variable(EventHandler *handler, int *var, char *name); -/* events_parse_string() - * handler: The event handler. - * message: The message to parse. - */ -char *events_parse_string(EventHandler *handler, char *message); - -#endif diff --git a/src/game.c b/src/game.c index 32b4104..899dbc4 100644 --- a/src/game.c +++ b/src/game.c @@ -27,16 +27,18 @@ void game_logic(Game *game) { update_npc( game ); /* we check if interactions are possible close to the player */ - for( uint32_t i=0; imap_level->nbextradata; i++ ){ + for( uint32_t i=0; imap_level->nbextradata; i++ ) + { /* simple distance check along X and Y axis */ /* Be careful to use world coordinates, not local (i.e.map) ones */ - if ((abs((int) game->player.wx - + if ( (abs((int) game->player.wx - (int) game->map_level->extradata[i].x*PXSIZE ) < MAX_INTERACTION_DISTANCE*PXSIZE) && (abs((int) game->player.wy - (int) game->map_level->extradata[i].y*PXSIZE ) < MAX_INTERACTION_DISTANCE*PXSIZE) - && strcmp(game->map_level->extradata[i].type, "NPC") != 0){ + && strcmp( game->map_level->extradata[i].type, "NPC") !=0 ) + { /* the player can do something */ game->player.canDoSomething = true; /* we mark the action for futur treatment in player_action() */ @@ -47,16 +49,18 @@ void game_logic(Game *game) { } } - for(uint32_t i=0; iplayer.wx - + if ( (abs((int) game->player.wx - (int) npcRPG[i].curx*PXSIZE ) < MAX_INTERACTION_DISTANCE*PXSIZE) && (abs((int) game->player.wy - (int) npcRPG[i].cury*PXSIZE ) < MAX_INTERACTION_DISTANCE*PXSIZE) - && strcmp( game->map_level->extradata[i].type, "NPC") !=0){ + && strcmp( game->map_level->extradata[i].type, "NPC") !=0 ) + { /* the player can do something */ game->player.canDoSomething = true; /* we mark the action for futur treatment in player_action() */ @@ -76,31 +80,33 @@ void game_logic(Game *game) { } -void game_render_indicator(Game *game) { +void render_indicator(Game *game) +{ /* nothing to do for the player so we quit */ - if(game->player.canDoSomething==false) return; + if (game->player.canDoSomething==false) + return; /* else we draw a small indicator on the screen */ dimage(5, 5, &SignAction_img); } -void game_draw(Game *game) { +void draw(Game *game) { /* Draw everything. */ - dclear(C_WHITE); - map_render_by_layer(game, BACKGROUND); - npc_draw(game); + render_map_by_layer(game, BACKGROUND); + npc_draw( game ); player_draw(game); - map_render_by_layer(game, FOREGROUND); - game_render_indicator(game); - dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life); - dprint(8, 16, C_BLACK, "Mana: %d", game->mana); + render_map_by_layer(game, FOREGROUND); + render_indicator( game ); } /* Key management */ -void game_get_inputs(Game *game) { - clearevents(); +void get_inputs(Game *game) { + key_event_t ev; + while((ev = pollevent()).type != KEYEV_NONE){ + /**/ + } /* Key binding for the Player action */ @@ -137,3 +143,4 @@ void game_get_inputs(Game *game) { #endif //USB_FEATURE } + diff --git a/src/game.h b/src/game.h index 8b0eb3a..8d24797 100644 --- a/src/game.h +++ b/src/game.h @@ -70,7 +70,6 @@ typedef struct { char *name; /* its class (NPC, SGN, INFO, ... )*/ char *type; - char *face; /* the ID of the first element of the dialog */ /* (to be aligned with "dialogs.json" IDs)*/ @@ -151,27 +150,15 @@ typedef struct { /* (Mibi88) TODO: Describe what this function is doing. */ void game_logic(Game *game); -/* game_draw() - * - * Draws everything on screen. - * game: The game struct. - */ -void game_draw(Game *game); +/* Draws everything on screen. */ +void draw(Game *game); -/* game_render_indicator() - * - * This render a small sign on the upper left corner of the screen - * if the player can do an action - * game: The game struct. - */ -void game_render_indicator(Game *game); +/* This render a small sign on the upper lecft corner of the screen */ +/* if the player can do an action */ +void render_indicator(Game *game); -/* game_get_inputs() - * - * Handle key presses. - * game: The game struct. - */ -void game_get_inputs(Game *game); +/* Handle key presses. */ +void get_inputs(Game *game); #endif diff --git a/src/main.c b/src/main.c index 27e5656..0375212 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,7 @@ Game game = { , false, false, false }; -/* screen capture management code. TODO: Clean this up! */ +/* screen capture management code */ #if USB_FEATURE @@ -128,9 +128,9 @@ int main(void) { dclear(C_WHITE); /* render the map */ - game_draw(&game); + draw(&game); - #if DEBUGMODE && GINT_RENDER_RGB + #if DEBUGMODE && FXCG50 if (game.debug_map) { dfont( NULL ); @@ -181,7 +181,7 @@ int main(void) { #endif /* Management of the inputs */ - game_get_inputs(&game); + get_inputs(&game); /* Run the game at max. 50fps */ while(game.frame_duration < 20) sleep(); /* Reset frame_duration for the next frame */ diff --git a/src/map.c b/src/map.c index bb6efad..d378263 100644 --- a/src/map.c +++ b/src/map.c @@ -8,7 +8,7 @@ extern Map *worldRPG[]; //extern ExtraData *extraRPG[]; -void map_render(Game *game) { +void render_map(Game *game) { Map *map_level = game->map_level; Player *player = &game->player; @@ -104,7 +104,7 @@ void map_render(Game *game) { } } -void map_render_by_layer(Game *game, int layer) { +void render_map_by_layer(Game *game, int layer) { Map *map_level = game->map_level; Player *player = &game->player; @@ -194,7 +194,7 @@ void map_render_by_layer(Game *game, int layer) { } } -short int map_get_tile(Game *game, int x, int y, int l) { +short int get_tile(Game *game, int x, int y, int l) { Map *map_level = game->map_level; @@ -204,7 +204,7 @@ short int map_get_tile(Game *game, int x, int y, int l) { map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; } -short int map_get_walkable(Game *game, int x, int y) { +short int get_walkable(Game *game, int x, int y) { Map *map_level = game->map_level; /* Get the tile at (x, y). Returns the tile ID or MAP_OUTSIDE if she's not @@ -214,25 +214,26 @@ short int map_get_walkable(Game *game, int x, int y) { } /* return the pointer to the map containing the given position */ -Map *map_get_for_coordinates( Game *game, int x, int y ) +Map *get_map_for_coordinates( Game *game, int x, int y ) { /* check if the current map contains the point */ if (x>= (int)game->map_level->xmin && x< (int)game->map_level->xmax && - y>= (int)game->map_level->ymin && y< (int)game->map_level->ymax){ + y>= (int)game->map_level->ymin && y< (int)game->map_level->ymax) return game->map_level; - } /* else we check in worldRPG if there is a mal containing that point */ int i = 0; Map *current = worldRPG[i]; - do{ + do + { if (x>= (int)current->xmin && x< (int)current->xmax && y>= (int)current->ymin && y< (int)current->ymax) return current; i++; current = worldRPG[i]; - }while (current!=NULL); + } + while (current!=NULL); /* else we return NULL cause the point is a not within a map */ return NULL; -} +} \ No newline at end of file diff --git a/src/map.h b/src/map.h index 184948d..1586186 100644 --- a/src/map.h +++ b/src/map.h @@ -19,48 +19,21 @@ -/* map_render() - * - * Draws the map map on the entire screen to be viewed by the player player. - * game: The game struct. - */ -void map_render(Game *game); +/* Draws the map map on the entire screen to be viewed by the player player. */ +void render_map(Game *game); -/* map_render_by_layer() - * - * Draws the map layer on the entire screen to be viewed by the player player. - * game: The game struct. - * layer: The layer to render. +/* Draws the map layer on the entire screen to be viewed by the player player. */ -void map_render_by_layer(Game *game, int layer); +void render_map_by_layer(Game *game, int layer); -/* map_get_tile() - * - * Get the tile at (x, y) of the map map. If the tile is located outside of the - * screen, MAP_OUTSIDE is returned. - * game: The game struct. - * x: The coordinates of the tile. - * y: The coordinates of the tile. - * l: The layer of the tile. - */ -short int map_get_tile(Game *game, int x, int y, int l); +/* Get the tile at (x, y) of the map map. If the tile is located outside of the + * screen, MAP_OUTSIDE is returned. */ +short int get_tile(Game *game, int x, int y, int l); -/* map_get_walkable() - * - * Returns what is in the walkable layer at (x, y). - * game: The game struct. - * x: The coordinates of the tile. - * y: The coordinates of the tile. - */ -short int map_get_walkable(Game *game, int x, int y); +/* Returns what is in the walkable layer at (x, y). */ +short int get_walkable(Game *game, int x, int y); -/* map_get_for_coordinates() - * - * return the pointer to the map containing the given position. - * game: The game struct. - * x: The coordinates to look at. - * y: The coordinates to look at. - */ -Map* map_get_for_coordinates(Game *game, int x, int y ); +/* return the pointer to the map containing the given position */ +Map* get_map_for_coordinates(Game *game, int x, int y ); #endif diff --git a/src/memory.c b/src/memory.c index 9bfcb47..9e3e58a 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,6 +1,6 @@ #include "memory.h" -bool memory_is_in(short int *array, short int array_length, short int item) { +bool is_in(short int *array, short int array_length, short int item) { short int i; for(i=0;i -/* memory_is_in() - * - * returns true if item is in array. - * array: The array to search in. - * array_length: The length of the array. - * item: The item to search for. - */ -bool memory_is_in(short int *array, short int array_length, short int item); + +bool is_in(short int *array, short int array_length, short int item); #endif diff --git a/src/npc.c b/src/npc.c index 3f87086..86a62b7 100644 --- a/src/npc.c +++ b/src/npc.c @@ -14,6 +14,15 @@ extern bopti_image_t demo_PNJ_img; +/* the color of the text to go to the next dialog phase */ +/* it improves readability to have somathing lighter */ +#if defined(FXCG50) + #define PATH_COLOR C_RED +#else + #define PATH_COLOR C_BLACK +#endif + + NPC *npcRPG; uint32_t nbNPC = 0; @@ -97,7 +106,6 @@ void reload_npc(Game *game) npcRPG[currentNPC].xpath = Data->xpath; npcRPG[currentNPC].ypath = Data->ypath; npcRPG[currentNPC].paused = false; - npcRPG[currentNPC].face = Data->face; currentNPC++; } } diff --git a/src/npc.h b/src/npc.h index a7dd906..e7e1e12 100644 --- a/src/npc.h +++ b/src/npc.h @@ -31,8 +31,6 @@ typedef struct /* is the current NPC in pause (during dialog) */ bool paused; - - char *face; } NPC; diff --git a/src/player.c b/src/player.c index 58d8e37..2274b11 100644 --- a/src/player.c +++ b/src/player.c @@ -6,28 +6,6 @@ #include "npc.h" #include -#define FACES 4 - -struct Face { - const char *name; - bopti_image_t *face; -}; - -extern bopti_image_t demo_player_img; -extern bopti_image_t npc_male; -extern bopti_image_t npc_female; -extern bopti_image_t npc_milkman; -extern bopti_image_t npc_police; -extern bopti_image_t SGN_Icon_img; -extern bopti_image_t INFO_Icon_img; - -const struct Face faces[FACES] = { - {"MALE", &npc_male}, - {"FEMALE", &npc_female}, - {"MILKMAN", &npc_milkman}, - {"POLICE", &npc_police} -}; - const char one_px_mov[8] = { 0, -1, /* Up */ 0, 1, /* Down */ @@ -105,13 +83,18 @@ void player_move(Game *game, Direction direction) { player->wy = game->map_level->ymin * PXSIZE + player->y; } -void player_action(Game *game) { - register size_t i; - /* already doing something (action IS NOT with an NPC) */ - if(game->player.isDoingAction) return; - if(game->player.canDoSomething && !game->player.isInteractingWithNPC){ - /* we can do something */ +extern bopti_image_t demo_player_img; +extern bopti_image_t NPC_Icon_img; +extern bopti_image_t SGN_Icon_img; +extern bopti_image_t INFO_Icon_img; + + +void player_action(Game *game) { + if( game->player.isDoingAction ) return; /* alreday doing something (action IS NOT with an NPC ) */ + + if( game->player.canDoSomething && !game->player.isInteractingWithNPC ) /* we can do something */ + { /* we indicate that the player is occupied */ game->player.isDoingAction = true; @@ -123,33 +106,23 @@ void player_action(Game *game) { /* we use the correct image as per the class of the item */ - if (strcmp("INFO", currentData->type)==0){ + if (strcmp("INFO", currentData->type)==0) face = &INFO_Icon_img; - }else if (strcmp("SGN", currentData->type)==0){ + //else if (strcmp("NPC", currentData->type)==0) + // face = &NPC_Icon_img; + else if (strcmp("SGN", currentData->type)==0) face = &SGN_Icon_img; - }else{ - /* It's a NPC */ - /* (Mibi88) TODO: Use string hash + strcmp if the hashes match for - * fast string comparison. */ - face = NULL; - for(i=0;iface)){ - face = current_face.face; - } - } - if(!face) face = &npc_male; - - } + else face = &demo_player_img; uint32_t dialogStart = currentData->dialogID; - dialogs_initiate_sequence(game, face, dialogStart); + initiate_dialog_sequence( game, face, dialogStart ); /* when done we release the occupied status of the player */ game->player.isDoingAction = false; - }else if(game->player.canDoSomething && game->player.isInteractingWithNPC){ - /* we can do something (action IS with an NPC) */ + } + else if( game->player.canDoSomething && game->player.isInteractingWithNPC ) /* we can do something (action IS with an NPC ) */ + { /* we indicate that the player is occupied */ game->player.isDoingAction = true; @@ -157,28 +130,14 @@ void player_action(Game *game) { /* we use the correct image as per the class of the item */ - ExtraData *currentData = &game->map_level->extradata[game->player.whichAction]; - bopti_image_t *face = &npc_male; - /* It's a NPC */ - /* (Mibi88) TODO: Use string hash + strcmp if the hashes match for - * fast string comparison. */ - face = NULL; - for(i=0;iface)){ - face = current_face.face; - } - if(!face) face = &npc_male; - } - dtext(2, 64, C_BLACK, currentData->type); + bopti_image_t *face = &NPC_Icon_img; uint32_t dialogStart = currentNPC->dialogID; - /* we set this NPC to paused to avoid changing its position while - * talking (the rest of the NPCs pursue their action) */ + /* we setr this NPC to paused to avoid changing its position while talking (the rest of the NPCs pursue their action)*/ currentNPC->paused = true; - dialogs_initiate_sequence(game, face, dialogStart); + initiate_dialog_sequence( game, face, dialogStart ); /* when done we release the occupied status of the player */ game->player.isDoingAction = false; @@ -215,13 +174,15 @@ bool player_collision(Game *game, Direction direction, /* check where the player is expected to go on the next move */ /* if outside the map, we check if there is a map on the other */ /* side of the current map*/ - if (map_get_walkable(game, player_tile_x, player_tile_y) == MAP_OUTSIDE){ + if (get_walkable(game, player_tile_x, player_tile_y) == MAP_OUTSIDE) + { // we compute the expected world coordinates accordingly // while taking care of the scaling between fx and cg models (PXSIZE) int worldX = (player->wx+dx) / PXSIZE; int worldY = (player->wy+dy) / PXSIZE; - Map *map = map_get_for_coordinates(game, worldX, worldY); - if (map!=NULL && map!=game->map_level){ + Map *map = get_map_for_coordinates(game, worldX, worldY ); + if (map!=NULL && map!=game->map_level) + { Map *backupmap = game->map_level; int backupx = player->x; int backupy = player->y; @@ -236,7 +197,7 @@ bool player_collision(Game *game, Direction direction, player->x = (worldX - map->xmin ) * PXSIZE; player->y = (worldY - map->ymin ) * PXSIZE; - int on_walkable = map_get_walkable(game, player->x/T_WIDTH, + int on_walkable = get_walkable(game, player->x/T_WIDTH, player->y/T_HEIGHT); int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ? @@ -256,7 +217,7 @@ bool player_collision(Game *game, Direction direction, /* we update the list of NPCs in the current map */ /* to follow the trajectories */ - reload_npc(game); + reload_npc( game ); return false; } @@ -270,7 +231,7 @@ bool player_collision(Game *game, Direction direction, if(player_tile_y < 0) player_tile_y = player_tile_y/T_HEIGHT-1; else player_tile_y = player_tile_y/T_HEIGHT; - int on_walkable = map_get_walkable(game, player_tile_x, player_tile_y); + int on_walkable = get_walkable(game, player_tile_x, player_tile_y); int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ? walkable_speed[on_walkable] : 0; diff --git a/src/player.h b/src/player.h index a36d988..7b69716 100644 --- a/src/player.h +++ b/src/player.h @@ -1,8 +1,21 @@ #ifndef PLAYER_H #define PLAYER_H +/* The size of the player. */ +#ifdef FXCG50 + #define P_WIDTH 16 + #define P_HEIGHT 16 +#else + #define P_WIDTH 8 + #define P_HEIGHT 8 +#endif + +/* SPEED should NOT be 8 or bigger: it may cause bugs when handling + * collisions! */ +#define SPEED PXSIZE*2 + #include -#include "config.h" + #include "game.h" #include "memory.h" @@ -12,53 +25,27 @@ /* only methods propotypes are now in dedicated header files */ -/* player_draw() - * - * Draws the player. This function should be called after drawing the - * map! - * game: The game struct which contains the player struct used. - */ +/* Draws the player player. This function should be called after drawing the + * map! */ void player_draw(Game *game); -/* player_move() - * - * Move the player in a direction. - * game: The game struct. - * direction: The direction to move the player in. - */ +/* Move the player player in the direction direction. */ void player_move(Game *game, Direction direction); /* (Mibi88) TODO: Describe this function please, I've no idea what she's for! */ void player_action(Game *game); -/* player_collision() - * - * Check if the player is in collision with the map or a NPC. Checkpos is used - * to check the axis where the player is not moving. - * game: The game struct. - * direction: The direction the player is moving in. - * nomov_axis_check: The axis that isn't changed by this movement. - */ +/* Check if the player is in collision with the map or a NPC. Checkpos is used + * to check the axis where the player is not moving. */ bool player_collision(Game *game, Direction direction, Checkpos nomov_axis_check); -/* player_fix_position() - * - * Fix the position of the player so that he's not a bit inside of a hard block - * after a collision. - * game: The game struct. - * fix_x: If we should fix the position on the X axis. - * fix_y: If we should fix the position on the Y axis. - */ +/* Fix the position of the player so that he's not a bit inside of a hard block + * after a collision. */ void player_fix_position(Game *game, bool fix_x, bool fix_y); -/* player_damage() - * - * Apply damage to player - * game: The game struct. - * amount: The amount of damage to apply. - */ +/* Apply damage to player */ void player_damage(Game *game, int amount); #endif