Refactoring

This commit is contained in:
mibi88 2024-07-25 13:07:19 +02:00
parent f6d142c920
commit 25ea360713
15 changed files with 234 additions and 144 deletions

View file

@ -1,3 +1,26 @@
# Project structure # Project structure
TODO: Describe the 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.

View file

@ -4,9 +4,10 @@ Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.plan
## Contribuer! ## Contribuer!
Style du code [STYLE.md](STYLE.md). Style du code [STYLE.md](STYLE.md).
Structure du projet [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md). Structure du projet [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md).
## Avencement du projet ## Avancement du projet
A ce stade, on a déjà implémenté : A ce stade, on a déjà implémenté :
@ -17,12 +18,13 @@ A ce stade, on a déjà implémenté :
- [x] Multiple cartes avec importation automatique des fichiers `world` issus de Tiled - [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] Carte Multilayer (Background, Foreground + accessibilité / Dommages) avec transparence du calque Foreground
- [x] Personnage - [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) - [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] Fontes de caractères - [x] Fontes de caractères
- [x] Interaction - [x] Interaction
- [ ] NPC - [ ] NPC
- [x] Changement de map durant le jeu - [x] Changement de map durant le jeu
- [ ] Système d'événements - [ ] Système d'événements
- [ ] Pathfinding
## Crédits ## Crédits

44
README_en.md Normal file
View file

@ -0,0 +1,44 @@
# 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

View file

@ -11,6 +11,10 @@ single line.
Put the curly braces after if, else, while or for statements and declarations of Put the curly braces after if, else, while or for statements and declarations of
procedures on the same line. 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 (Mibi88) SlyVTT, Fcalva, should be use a doc generation thing or do we describe
the procedures as I did so far? the procedures as I did so far?
@ -20,9 +24,9 @@ Document your procedures as following:
/* procedure_name() /* procedure_name()
* *
* Describe what this procedure does. * Describe what this procedure does.
* arg1: Describe this argument. If the text is too long, wrap it to the next * arg1: Describe this argument. If the text is too long, wrap it to the
* line like this. * next line like this.
* arg2: Describe this argument, and so on. * long_name: Describe this argument, and so on.
*/ */
``` ```

View file

@ -48,7 +48,7 @@ void blit() {
} }
int showtext_opt(Game *game, bopti_image_t *face, char *text, int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i), int call_before_end(Game *game, unsigned int i),
bool start_anim, bool start_anim,
bool end_anim, bool end_anim,
@ -68,7 +68,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
/* Redrawing the entire screen, because maybe there was no dialog /* Redrawing the entire screen, because maybe there was no dialog
displayed before. */ displayed before. */
update_npc(game); update_npc(game);
draw(game); game_draw(game);
/* Fill the dialog box with white */ /* Fill the dialog box with white */
drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE);
@ -88,7 +88,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
}else{ }else{
/* Here I'm drawing the same as if start_anim is true, but whitout /* Here I'm drawing the same as if start_anim is true, but whitout
* making an animation. */ * making an animation. */
draw(game); game_draw(game);
drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE);
drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK);
dimage(4*PXSIZE, 2*PXSIZE, face); dimage(4*PXSIZE, 2*PXSIZE, face);
@ -191,7 +191,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
for(i=BOX_HEIGHT;i>0;i--){ for(i=BOX_HEIGHT;i>0;i--){
/* It is the same as the start animation. */ /* It is the same as the start animation. */
update_npc(game); update_npc(game);
draw(game); game_draw(game);
drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE);
drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK);
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE,
@ -206,11 +206,11 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
return return_int; return return_int;
} }
void showtext_dialog(Game *game, bopti_image_t *face, char *text, void dialogs_text(Game *game, bopti_image_t *face, char *text,
bool dialog_start, bool dialog_end) { bool dialog_start, bool dialog_end) {
/* Run showtext_opt with some default values. It makes it easier to use in /* Run showtext_opt with some default values. It makes it easier to use in
* simple dialogs. */ * simple dialogs. */
showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100,
true, 0, true); true, 0, true);
} }
@ -312,8 +312,8 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
for(i=DWIDTH/8+1;i>0;i--){ for(i=DWIDTH/8+1;i>0;i--){
/* I'm drawing the same box as on the start animation */ /* I'm drawing the same box as on the start animation */
update_npc(game); update_npc(game);
draw(game); game_draw(game);
showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, dialogs_text_opt(game, _face, _text, NULL, false, false, NULL, 0, false,
_i, false); _i, false);
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8), drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE);
@ -330,7 +330,7 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
return selected; return selected;
} }
int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount, bool end, char *choices, int choices_amount,
int default_choice) { int default_choice) {
/* Put some arguments in global pointers and variables to make them /* Put some arguments in global pointers and variables to make them
@ -342,16 +342,15 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start,
_text = text; _text = text;
/* Run showtext_opt and return his return value (the return value of /* Run showtext_opt and return his return value (the return value of
*_choice_call_before_end) */ *_choice_call_before_end) */
return showtext_opt(game, face, text, _choice_call_before_end, start, end, return dialogs_text_opt(game, face, text, _choice_call_before_end, start,
_choice_screen_call, 100, true, 0, true); end, _choice_screen_call, 100, true, 0, true);
} }
void initiate_dialog_sequence(Game *game, bopti_image_t *face, void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber ) uint32_t dialogNumber) {
{
Dialog *currentDiag = &game->map_level->dialogs[dialogNumber]; Dialog *currentDiag = &game->map_level->dialogs[dialogNumber];
/* we collect the information */ /* we collect the information */
@ -366,27 +365,23 @@ void initiate_dialog_sequence(Game *game, bopti_image_t *face,
int isQuestion = currentDiag->isQuestion; int isQuestion = currentDiag->isQuestion;
/* we treat the action - i.e. we show a dialog */ /* we treat the action - i.e. we show a dialog */
if (isQuestion == 1) /* we have to manage a question */ if (isQuestion == 1){
{ /* we have to manage a question */
int answer = showtext_dialog_ask( game, face, text, true, true, choices, 2, 0 ); int answer = dialogs_ask(game, face, text, true, true,
choices, 2, 0);
/* TO DO we need to split the strings conclusion1 and conclusion2 */ /* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */ /* to extract the "gift" part */
if (answer==0) if(answer==0){
{ dialogs_text(game, face, conclusion1, true, true);
showtext_dialog( game, face, conclusion1, true, true ); if (next1!=-1) dialogs_initiate_sequence(game, face, next1);
if (next1!=-1) initiate_dialog_sequence( game, face, next1 ); }else{
dialogs_text(game, face, conclusion2, true, true);
if (next2!=-1) dialogs_initiate_sequence(game, face, next2);
} }
else }else{
{ dialogs_text(game, face, text, true, true);
showtext_dialog( game, face, conclusion2, true, true ); if (nextOther!=-1) dialogs_initiate_sequence(game, face, nextOther);
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 );
} }
} }

View file

@ -7,7 +7,7 @@
#include "map.h" #include "map.h"
#include "config.h" #include "config.h"
/* showtext_opt() /* dialogs_text_opt()
* *
* Show some text in a box with word wrap for dialogs. * Show some text in a box with word wrap for dialogs.
* *
@ -35,17 +35,17 @@
* wait_continue: If I should wait that EXE is pressed after drawing a page. * wait_continue: If I should wait that EXE is pressed after drawing a page.
*/ */
int showtext_opt(Game *game, bopti_image_t *face, char *text, int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i), int call_before_end(Game *game, unsigned int i),
bool start_anim, bool start_anim,
bool end_anim, bool end_anim,
void for_each_screen(Game *game, unsigned int i), void for_each_screen(Game *game, unsigned int i),
int line_duration, bool update_screen, unsigned int start_i, int line_duration, bool update_screen,
bool wait_continue); unsigned int start_i, bool wait_continue);
/* showtext_dialog() /* dialogs_text()
* *
* Calls showtext_opt with default parameters. * Calls dialogs_text_opt with default parameters.
* *
* game: The game struct of the current game. * game: The game struct of the current game.
* face: A bopti_image_t of the face of the person who's saying this * face: A bopti_image_t of the face of the person who's saying this
@ -58,12 +58,12 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
* shown at the end of showtext_opt. * shown at the end of showtext_opt.
*/ */
void showtext_dialog(Game *game, bopti_image_t *face, char *text, void dialogs_text(Game *game, bopti_image_t *face, char *text,
bool dialog_start, bool dialog_end); bool dialog_start, bool dialog_end);
/* showtext_dialog_ask() /* dialogs_ask()
* *
* Like showtext_dialog, but lets the user choose between multiple possible * Like dialogs_text, but lets the user choose between multiple possible
* choices after displaying the text. * choices after displaying the text.
* *
* game: The game struct of the current game. * game: The game struct of the current game.
@ -83,12 +83,12 @@ void showtext_dialog(Game *game, bopti_image_t *face, char *text,
* default_choice: The choice choosen by default when the dialog just opened. * default_choice: The choice choosen by default when the dialog just opened.
*/ */
int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount, bool end, char *choices, int choices_amount,
int default_choice); int default_choice);
/* TODO: Doc. */ /* TODO: Doc. */
void initiate_dialog_sequence(Game *game, bopti_image_t *face, void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber); uint32_t dialogNumber);
#endif #endif

View file

@ -27,8 +27,7 @@ void game_logic(Game *game) {
update_npc( game ); update_npc( game );
/* we check if interactions are possible close to the player */ /* we check if interactions are possible close to the player */
for( uint32_t i=0; i<game->map_level->nbextradata; i++ ) for( uint32_t i=0; i<game->map_level->nbextradata; i++ ){
{
/* simple distance check along X and Y axis */ /* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */ /* Be careful to use world coordinates, not local (i.e.map) ones */
if ((abs((int) game->player.wx - if ((abs((int) game->player.wx -
@ -37,8 +36,7 @@ void game_logic(Game *game) {
&& (abs((int) game->player.wy - && (abs((int) game->player.wy -
(int) game->map_level->extradata[i].y*PXSIZE ) (int) game->map_level->extradata[i].y*PXSIZE )
< MAX_INTERACTION_DISTANCE*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 */ /* the player can do something */
game->player.canDoSomething = true; game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */ /* we mark the action for futur treatment in player_action() */
@ -49,8 +47,7 @@ void game_logic(Game *game) {
} }
} }
for( uint32_t i=0; i<nbNPC; i++ ) for(uint32_t i=0; i<nbNPC; i++){
{
/* simple distance check along X and Y axis */ /* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */ /* Be careful to use world coordinates, not local (i.e.map) ones */
if ((abs((int) game->player.wx - if ((abs((int) game->player.wx -
@ -59,8 +56,7 @@ void game_logic(Game *game) {
&& (abs((int) game->player.wy - && (abs((int) game->player.wy -
(int) npcRPG[i].cury*PXSIZE ) (int) npcRPG[i].cury*PXSIZE )
< MAX_INTERACTION_DISTANCE*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 */ /* the player can do something */
game->player.canDoSomething = true; game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */ /* we mark the action for futur treatment in player_action() */
@ -80,34 +76,30 @@ void game_logic(Game *game) {
} }
void render_indicator(Game *game) { void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */ /* nothing to do for the player so we quit */
if (game->player.canDoSomething==false) if(game->player.canDoSomething==false) return;
return;
/* else we draw a small indicator on the screen */ /* else we draw a small indicator on the screen */
dimage(5, 5, &SignAction_img); dimage(5, 5, &SignAction_img);
} }
void draw(Game *game) { void game_draw(Game *game) {
/* Draw everything. */ /* Draw everything. */
render_map_by_layer(game, BACKGROUND); map_render_by_layer(game, BACKGROUND);
npc_draw(game); npc_draw(game);
player_draw(game); player_draw(game);
render_map_by_layer(game, FOREGROUND); map_render_by_layer(game, FOREGROUND);
render_indicator( game ); game_render_indicator(game);
dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life); dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life);
dprint(8, 16, C_BLACK, "Mana: %d", game->mana); dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
} }
/* Key management */ /* Key management */
void get_inputs(Game *game) { void game_get_inputs(Game *game) {
key_event_t ev; clearevents();
while((ev = pollevent()).type != KEYEV_NONE){
/**/
}
/* Key binding for the Player action */ /* Key binding for the Player action */
@ -144,4 +136,3 @@ void get_inputs(Game *game) {
#endif //USB_FEATURE #endif //USB_FEATURE
} }

View file

@ -155,27 +155,27 @@ typedef struct {
/* (Mibi88) TODO: Describe what this function is doing. */ /* (Mibi88) TODO: Describe what this function is doing. */
void game_logic(Game *game); void game_logic(Game *game);
/* draw() /* game_draw()
* *
* Draws everything on screen. * Draws everything on screen.
* game: The game struct. * game: The game struct.
*/ */
void draw(Game *game); void game_draw(Game *game);
/* render_indicator() /* game_render_indicator()
* *
* This render a small sign on the upper left corner of the screen * This render a small sign on the upper left corner of the screen
* if the player can do an action * if the player can do an action
* game: The game struct. * game: The game struct.
*/ */
void render_indicator(Game *game); void game_render_indicator(Game *game);
/* get_inputs() /* game_get_inputs()
* *
* Handle key presses. * Handle key presses.
* game: The game struct. * game: The game struct.
*/ */
void get_inputs(Game *game); void game_get_inputs(Game *game);
#endif #endif

View file

@ -125,7 +125,7 @@ int main(void) {
dclear(C_WHITE); dclear(C_WHITE);
/* render the map */ /* render the map */
draw(&game); game_draw(&game);
#if DEBUGMODE && GINT_RENDER_RGB #if DEBUGMODE && GINT_RENDER_RGB
if (game.debug_map) if (game.debug_map)
@ -178,7 +178,7 @@ int main(void) {
#endif #endif
/* Management of the inputs */ /* Management of the inputs */
get_inputs(&game); game_get_inputs(&game);
/* Run the game at max. 50fps */ /* Run the game at max. 50fps */
while(game.frame_duration < 20) sleep(); while(game.frame_duration < 20) sleep();
/* Reset frame_duration for the next frame */ /* Reset frame_duration for the next frame */

View file

@ -8,7 +8,7 @@ extern Map *worldRPG[];
//extern ExtraData *extraRPG[]; //extern ExtraData *extraRPG[];
void render_map(Game *game) { void map_render(Game *game) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
Player *player = &game->player; Player *player = &game->player;
@ -104,7 +104,7 @@ void render_map(Game *game) {
} }
} }
void render_map_by_layer(Game *game, int layer) { void map_render_by_layer(Game *game, int layer) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
Player *player = &game->player; Player *player = &game->player;
@ -194,7 +194,7 @@ void render_map_by_layer(Game *game, int layer) {
} }
} }
short int get_tile(Game *game, int x, int y, int l) { short int map_get_tile(Game *game, int x, int y, int l) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
@ -204,7 +204,7 @@ short int get_tile(Game *game, int x, int y, int l) {
map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE;
} }
short int get_walkable(Game *game, int x, int y) { short int map_get_walkable(Game *game, int x, int y) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
/* Get the tile at (x, y). Returns the tile ID or MAP_OUTSIDE if she's not /* Get the tile at (x, y). Returns the tile ID or MAP_OUTSIDE if she's not
@ -214,7 +214,7 @@ short int get_walkable(Game *game, int x, int y) {
} }
/* return the pointer to the map containing the given position */ /* return the pointer to the map containing the given position */
Map *get_map_for_coordinates( Game *game, int x, int y ) Map *map_get_for_coordinates( Game *game, int x, int y )
{ {
/* check if the current map contains the point */ /* check if the current map contains the point */
if (x>= (int)game->map_level->xmin && x< (int)game->map_level->xmax && if (x>= (int)game->map_level->xmin && x< (int)game->map_level->xmax &&

View file

@ -19,22 +19,22 @@
/* render_map() /* map_render()
* *
* Draws the map map on the entire screen to be viewed by the player player. * Draws the map map on the entire screen to be viewed by the player player.
* game: The game struct. * game: The game struct.
*/ */
void render_map(Game *game); void map_render(Game *game);
/* render_map_by_layer() /* map_render_by_layer()
* *
* Draws the map layer on the entire screen to be viewed by the player player. * Draws the map layer on the entire screen to be viewed by the player player.
* game: The game struct. * game: The game struct.
* layer: The layer to render. * layer: The layer to render.
*/ */
void render_map_by_layer(Game *game, int layer); void map_render_by_layer(Game *game, int layer);
/* get_tile() /* map_get_tile()
* *
* Get the tile at (x, y) of the map map. If the tile is located outside of the * Get the tile at (x, y) of the map map. If the tile is located outside of the
* screen, MAP_OUTSIDE is returned. * screen, MAP_OUTSIDE is returned.
@ -43,24 +43,24 @@ void render_map_by_layer(Game *game, int layer);
* y: The coordinates of the tile. * y: The coordinates of the tile.
* l: The layer of the tile. * l: The layer of the tile.
*/ */
short int get_tile(Game *game, int x, int y, int l); short int map_get_tile(Game *game, int x, int y, int l);
/* get_walkable() /* map_get_walkable()
* *
* Returns what is in the walkable layer at (x, y). * Returns what is in the walkable layer at (x, y).
* game: The game struct. * game: The game struct.
* x: The coordinates of the tile. * x: The coordinates of the tile.
* y: The coordinates of the tile. * y: The coordinates of the tile.
*/ */
short int get_walkable(Game *game, int x, int y); short int map_get_walkable(Game *game, int x, int y);
/* get_map_for_coordinates() /* map_get_for_coordinates()
* *
* return the pointer to the map containing the given position. * return the pointer to the map containing the given position.
* game: The game struct. * game: The game struct.
* x: The coordinates to look at. * x: The coordinates to look at.
* y: The coordinates to look at. * y: The coordinates to look at.
*/ */
Map* get_map_for_coordinates(Game *game, int x, int y ); Map* map_get_for_coordinates(Game *game, int x, int y );
#endif #endif

View file

@ -1,6 +1,6 @@
#include "memory.h" #include "memory.h"
bool is_in(short int *array, short int array_length, short int item) { bool memory_is_in(short int *array, short int array_length, short int item) {
short int i; short int i;
for(i=0;i<array_length;i++){ for(i=0;i<array_length;i++){
if(array[i] == item){ if(array[i] == item){

View file

@ -2,8 +2,14 @@
#define MEMORY_H #define MEMORY_H
#include <stdbool.h> #include <stdbool.h>
/* memory_is_in()
bool is_in(short int *array, short int array_length, short int item); *
* 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);
#endif #endif

View file

@ -91,10 +91,11 @@ extern bopti_image_t INFO_Icon_img;
void player_action(Game *game) { void player_action(Game *game) {
if( game->player.isDoingAction ) return; /* alreday doing something (action IS NOT with an NPC ) */ /* 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 */ if(game->player.canDoSomething && !game->player.isInteractingWithNPC){
{ /* we can do something */
/* we indicate that the player is occupied */ /* we indicate that the player is occupied */
game->player.isDoingAction = true; game->player.isDoingAction = true;
@ -116,13 +117,12 @@ void player_action(Game *game) {
uint32_t dialogStart = currentData->dialogID; uint32_t dialogStart = currentData->dialogID;
initiate_dialog_sequence( game, face, dialogStart ); dialogs_initiate_sequence(game, face, dialogStart);
/* when done we release the occupied status of the player */ /* when done we release the occupied status of the player */
game->player.isDoingAction = false; game->player.isDoingAction = false;
} }else if(game->player.canDoSomething && game->player.isInteractingWithNPC){
else if( game->player.canDoSomething && game->player.isInteractingWithNPC ) /* we can do something (action IS with an NPC ) */ /* we can do something (action IS with an NPC) */
{
/* we indicate that the player is occupied */ /* we indicate that the player is occupied */
game->player.isDoingAction = true; game->player.isDoingAction = true;
@ -133,11 +133,12 @@ void player_action(Game *game) {
bopti_image_t *face = &NPC_Icon_img; bopti_image_t *face = &NPC_Icon_img;
uint32_t dialogStart = currentNPC->dialogID; uint32_t dialogStart = currentNPC->dialogID;
/* we setr this NPC to paused to avoid changing its position while talking (the rest of the NPCs pursue their action)*/ /* we set this NPC to paused to avoid changing its position while
* talking (the rest of the NPCs pursue their action) */
currentNPC->paused = true; currentNPC->paused = true;
initiate_dialog_sequence( game, face, dialogStart ); dialogs_initiate_sequence(game, face, dialogStart);
/* when done we release the occupied status of the player */ /* when done we release the occupied status of the player */
game->player.isDoingAction = false; game->player.isDoingAction = false;
@ -174,15 +175,13 @@ bool player_collision(Game *game, Direction direction,
/* check where the player is expected to go on the next move */ /* 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 */ /* if outside the map, we check if there is a map on the other */
/* side of the current map*/ /* side of the current map*/
if (get_walkable(game, player_tile_x, player_tile_y) == MAP_OUTSIDE) if (map_get_walkable(game, player_tile_x, player_tile_y) == MAP_OUTSIDE){
{
// we compute the expected world coordinates accordingly // we compute the expected world coordinates accordingly
// while taking care of the scaling between fx and cg models (PXSIZE) // while taking care of the scaling between fx and cg models (PXSIZE)
int worldX = (player->wx+dx) / PXSIZE; int worldX = (player->wx+dx) / PXSIZE;
int worldY = (player->wy+dy) / PXSIZE; int worldY = (player->wy+dy) / PXSIZE;
Map *map = get_map_for_coordinates(game, worldX, worldY ); Map *map = map_get_for_coordinates(game, worldX, worldY);
if (map!=NULL && map!=game->map_level) if (map!=NULL && map!=game->map_level){
{
Map *backupmap = game->map_level; Map *backupmap = game->map_level;
int backupx = player->x; int backupx = player->x;
int backupy = player->y; int backupy = player->y;
@ -197,7 +196,7 @@ bool player_collision(Game *game, Direction direction,
player->x = (worldX - map->xmin ) * PXSIZE; player->x = (worldX - map->xmin ) * PXSIZE;
player->y = (worldY - map->ymin ) * PXSIZE; player->y = (worldY - map->ymin ) * PXSIZE;
int on_walkable = get_walkable(game, player->x/T_WIDTH, int on_walkable = map_get_walkable(game, player->x/T_WIDTH,
player->y/T_HEIGHT); player->y/T_HEIGHT);
int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ? int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ?
@ -231,7 +230,7 @@ bool player_collision(Game *game, Direction direction,
if(player_tile_y < 0) player_tile_y = player_tile_y/T_HEIGHT-1; if(player_tile_y < 0) player_tile_y = player_tile_y/T_HEIGHT-1;
else player_tile_y = player_tile_y/T_HEIGHT; else player_tile_y = player_tile_y/T_HEIGHT;
int on_walkable = get_walkable(game, player_tile_x, player_tile_y); int on_walkable = map_get_walkable(game, player_tile_x, player_tile_y);
int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ? int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ?
walkable_speed[on_walkable] : 0; walkable_speed[on_walkable] : 0;

View file

@ -12,27 +12,53 @@
/* only methods propotypes are now in dedicated header files */ /* only methods propotypes are now in dedicated header files */
/* Draws the player player. This function should be called after drawing the /* player_draw()
* map! */ *
* Draws the player. This function should be called after drawing the
* map!
* game: The game struct which contains the player struct used.
*/
void player_draw(Game *game); void player_draw(Game *game);
/* Move the player player in the direction direction. */ /* player_move()
*
* Move the player in a direction.
* game: The game struct.
* direction: The direction to move the player in.
*/
void player_move(Game *game, Direction direction); void player_move(Game *game, Direction direction);
/* (Mibi88) TODO: Describe this function please, I've no idea what she's for! */ /* (Mibi88) TODO: Describe this function please, I've no idea what she's for! */
void player_action(Game *game); void player_action(Game *game);
/* Check if the player is in collision with the map or a NPC. Checkpos is used /* player_collision()
* to check the axis where the player is not moving. */ *
* 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.
*/
bool player_collision(Game *game, Direction direction, bool player_collision(Game *game, Direction direction,
Checkpos nomov_axis_check); Checkpos nomov_axis_check);
/* Fix the position of the player so that he's not a bit inside of a hard block /* player_fix_position()
* after a collision. */ *
* 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.
*/
void player_fix_position(Game *game, bool fix_x, bool fix_y); void player_fix_position(Game *game, bool fix_x, bool fix_y);
/* Apply damage to player */ /* player_damage()
*
* Apply damage to player
* game: The game struct.
* amount: The amount of damage to apply.
*/
void player_damage(Game *game, int amount); void player_damage(Game *game, int amount);
#endif #endif