From 272d60b0aac66b0a6ef1fba6fcd2efb4c6d12bea Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Mon, 14 Aug 2023 18:40:36 +0200 Subject: [PATCH 01/10] preparing stuff for map change when reaching borders during gameplay --- README.md | 8 +++---- assets/level1.tmx | 42 ++++++++++++++++----------------- assets/level2.tmx | 60 +++++++++++++++++++++++------------------------ assets/level3.tmx | 52 ++++++++++++++++++++-------------------- clean | 1 + src/game.h | 3 ++- src/main.c | 8 +++---- src/map.c | 28 ++++++++++++++++++++++ src/map.h | 3 +++ src/player.c | 23 ++++++++++++++++++ 10 files changed, 142 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 76bbeeb..9189464 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,20 @@ Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.plan ## Avencement du projet - A ce stade, on a déjà implémenté : - [x] Screenshots, etc. par USB -- [x] Affichage de la map selon la position du joueur +- [x] Affichage de la map courante selon la position du joueur - [x] Gestion des touches - [x] Gestion des collisions +- [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 (sauts de lignes et mots plus grands que l'écran pas supportés) - [ ] Fontes de caractères - [ ] Interaction - [ ] NPC -- [ ] Changement de map +- [ ] Changement de map durant le jeu (en cours) ## Crédits @@ -27,5 +27,5 @@ Les tiles sont issues de Game Boy Top-down RPG Fantasy Tileset (FREE) Converties en niveau de gris avec Gimp -Une version 1-bit (N&B) à été réalisée par Shadow15510 +Une version 1-bit (N&B) à été réalisée par Shadow15510 Et une version couleur CG à été réalisée par Fcalva diff --git a/assets/level1.tmx b/assets/level1.tmx index 9fd42bb..300ef70 100644 --- a/assets/level1.tmx +++ b/assets/level1.tmx @@ -1,7 +1,7 @@ - + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -58,32 +58,32 @@ 276,0,0,273,274,275,276,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,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,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,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,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,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,412,412,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,412,412,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,414,414,414,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0, -0,0,0,414,414,414,414,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,414,414,414,414,414,414,414,414,0,0,0,0,414,414, -0,0,414,414,414,414,414,414,414,414,414,414,414,414,0,0,0,0,0,0,0,0,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, -412,414,414,414,414,414,414,414,414,414,414,414,414,414,0,0,412,412,0,0,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, -0,414,414,414,414,414,414,414,414,414,414,414,414,414,414,0,0,0,0,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, -0,0,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,0,0,414,414,414,414,414,414,414,414,414,414,414, -0,0,0,414,414,414,414,414,414,0,0,0,414,414,414,414,414,414,414,414,414,414,414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,414,414,414,414,414,414,414, -0,0,0,0,414,414,414,414,0,0,0,0,414,414,414,414,414,414,414,414,414,414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,414,414,414, -412,412,412,412,412,412,0,0,0,0,0,0,0,0,414,414,414,414,414,414,414,414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,414,414,414, -0,0,0,0,412,412,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,0, +0,0,0,0,0,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0, +0,0,0,412,412,412,412,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,412,412,412,412,412,412,412,412,0,0,0,0,412,412, +0,0,412,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +410,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,410,410,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,412,412,412,412,412,412,412,412,412,412,412, +0,0,0,412,412,412,412,412,412,0,0,0,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412, +0,0,0,0,412,412,412,412,0,0,0,0,412,412,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412, +410,410,410,410,410,410,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,412,412,412, +0,0,0,0,410,410,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,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,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0, -412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -412,412,412,412,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,412,412,0,0,0,0,0,0,0,0,0,0, -412,412,412,412,0,0,0,0,0,0,0,0,0,0,412,412,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,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,412,412,412,412,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,412,412,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,0,412,412,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,412,412,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,412,412,412,412,0,0,0,0,0,0,412,412,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,412,412,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0, +410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +410,410,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0, +410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,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,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,410,410,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,410,410,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,410,410,410,410,0,0,0,0,0,0,410,410,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,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/assets/level2.tmx b/assets/level2.tmx index 0d65f1f..35d297c 100644 --- a/assets/level2.tmx +++ b/assets/level2.tmx @@ -1,7 +1,7 @@ - + 2,2,2,2,386,2,2,2,2,2,2,325,2,290,265,2,349,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299, @@ -12,13 +12,13 @@ 2,2,2,2,2,2,2,2,2,2,2,2,2,290,266,2,2,2,385,2,297,298,299,300,2,2,2,2,2,2,2,9,10,2,2,283,283,3,115,111,112,113,3,312,312,131,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,386,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,34,385,2,283,283,3,114,114,115,114,3,312,312,132,385,2, 2,386,2,2,2,2,2,2,2,2,2,2,2,313,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2, -2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,149,150,151,152,149,150,151,152,149,150,151,152,149,150,151,152,2,2,282,283,3,3,3,3,3,3,287,288,132,2,2, -2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,2,2,2,2,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,312,132,2,2, -2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2, -2,2,2,2,2,385,2,2,2,2,2,2,2,386,313,2,2,149,149,150,151,149,150,151,152,149,150,151,152,149,150,151,152,2,2,282,330,308,308,308,308,308,308,311,312,132,2,2, +2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,374,375,151,152,149,150,151,152,149,150,374,375,149,150,151,152,2,2,282,283,3,3,3,3,3,3,287,288,132,2,2, +2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,208,209,352,353,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,312,132,2,2, +2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,232,233,376,377,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2, +2,2,2,2,2,385,2,2,2,2,2,2,2,386,313,2,2,149,149,374,375,149,150,151,152,374,375,151,152,149,150,151,152,2,2,282,330,308,308,308,308,308,308,311,312,132,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,2,2,2,2,2,385,2,2,385,2,2,2,2,2,2,330,331,331,331,331,331,331,331,331,336,132,2,2, 2,297,298,299,300,2,2,2,2,2,2,2,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,90,91,92,162,163,164,165,90,91,92,132,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,149,150,151,152,149,150,151,152,149,150,151,152,149,150,151,152,2,2,114,115,116,186,187,188,189,114,115,116,132,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,149,150,151,152,149,150,154,154,149,150,151,152,149,150,151,152,2,2,114,115,116,186,187,188,189,114,115,116,132,2,2, 2,385,386,386,2,2,2,2,2,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,110,113,110,210,211,212,213,113,110,113,133,2,2, 2,385,2,2,2,2,2,2,2,2,2,2,2,290,265,2,2,2,2,2,2,2,2,386,2,2,2,2,385,2,2,2,2,2,2,2,2,2,234,290,265,237,2,2,2,2,385,2, 2,2,2,2,2,2,297,298,299,300,2,2,2,386,266,2,2,2,2,2,2,2,2,386,386,2,2,2,2,2,2,2,2,2,2,2,160,161,386,386,266,2,2,2,2,385,385,2, @@ -39,13 +39,13 @@ 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, 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,0,0,0,0,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,125,126,127,128,125,126,127,128,125,126,127,128,125,126,127,128,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,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,273,274,275,276,0,0,0,0,0,0,0,0,0,0,350,351,127,128,125,126,127,128,125,126,350,351,125,126,127,128,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,184,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,201,202,203,204,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,0,0, -0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,0,125,125,126,127,125,126,127,128,125,126,127,128,125,126,127,128,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,125,125,350,351,125,126,127,128,350,351,127,128,125,126,127,128,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,0,0,0,0,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,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,125,126,127,128,125,126,127,128,125,126,127,128,125,126,127,128,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,125,126,173,128,125,126,130,174,125,126,127,128,125,126,127,128,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,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,0,0,0,0,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,136,137,0,0,0,0,0,0,0,0,0,0, @@ -60,29 +60,29 @@ -0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412, -0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,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,412,412,0,0,0,0, -412,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,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,0,412,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,412,412,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,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,412,412,412,412,412,412,412,412,412,412,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,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,412,412,0,0,412,412,412,412,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,412,412,412,412,412,412,412,412,412,412,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,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,412,412,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,412,412,412,412,412,412,412,412,412,412,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,412,412,412,412,412,412,412,412,412,412,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,412,412,412,412,0,0,412,412,412,412,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410, +0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,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,410,410,0,0,0,0, +410,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,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,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,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,410,410,410,410,410,410,410,410,410,410,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,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,410,410,0,0,410,410,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,410,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,411,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,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,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,410,410,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,410,410,410,410,410,410,410,410,410,410,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,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,410,410,410,410,0,0,410,410,410,410,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,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,412,412,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,412,412,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,410,410,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,410,410,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,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,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,412,412,412,412,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,0,0, -0,412,412,412,412,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,0,0, -0,412,412,412,412,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,0,0, +0,410,410,410,410,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,0,0, +0,410,410,410,410,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,0,0, +0,410,410,410,410,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,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,0,0,0,0,0,0,0,0,0 diff --git a/assets/level3.tmx b/assets/level3.tmx index f260e15..ea2adeb 100644 --- a/assets/level3.tmx +++ b/assets/level3.tmx @@ -1,7 +1,7 @@ - + 300,2,2,297,298,299,300,2,2,2,2,297,298,299,300,2,2,2,2,2,2,339,340,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -58,32 +58,32 @@ 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,0,0,0,0,0,0,0 - + -0,0,0,0,412,412,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,412,412,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,0,0,0,0,0,412,412,0,0,0,0,412,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,0,412,412, -412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,412,412, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,0, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,0, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,0, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,412,0,0,412,412,412,412,0,0,412,0,0,0, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,412,412,0,0,0,412,412,412,412,0,0,412,412,412,412,0,0,0, -412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,412,412,412,412,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,412,412,412,412,412,412,412,412,0,412,412,412,412,0,412,412,412,412,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,412, -0,0,412,0,0,0,0,0,0,412,0,412,412,412,412,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,412,0,0,0,0,0,0,412,0,412,412,412,412,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0, -0,0,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0, -0,0,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0, -0,0,412,0,0,412,412,412,412,412,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,0,0,0,0,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0, -0,0,412,412,412,412,0,0,412,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,0,0,0,0,412,0,0,0,0,412,412,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,412,412,412,0,0,412,412,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,412,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,412,0,0,0,0,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,412,412,0,412,412,412,412,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,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,412,412,412,412,0,412,412,0,0,0,0,0,412,412,412,412,0,0, -0,0,412,412,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,412,412,412,412,0,412,412,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,0,0,0,0,0,0,0,412,0,0,0,0,0,0 +0,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,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,0,0,0,0,0,410,410,0,0,0,0,410,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,410,410, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,410,0,0,0, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,410,410,410,410,410,410,410,410,0,410,410,410,410,0,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410, +0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,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,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0, +0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, +0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, +0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, +0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,410,410,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,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,410,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,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,410,410,410,410,0,410,410,0,0,0,0,0,410,410,410,410,0,0, +0,0,410,410,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,0,0,0 diff --git a/clean b/clean index 6cf836c..3e99971 100755 --- a/clean +++ b/clean @@ -1,5 +1,6 @@ cd assets rm -f *.json +rm -r __pycache__ cd .. rm -r build-cg rm -r build-fx diff --git a/src/game.h b/src/game.h index e13f3d4..b8b8615 100644 --- a/src/game.h +++ b/src/game.h @@ -23,8 +23,9 @@ typedef enum { /* Struct that define player parameters */ typedef struct { - int x, y; /* The position of the player */ + int x, y; /* The position of the player int the current map */ unsigned int px, py; /* The position of the player on screen */ + int wx, wy; /* position of the player in the world */ unsigned short int life; /* How many lives the player still has between 0 * and 100. */ char speed; /* The speed of the movement of the player. */ diff --git a/src/main.c b/src/main.c index deadd41..f448a84 100644 --- a/src/main.c +++ b/src/main.c @@ -32,11 +32,11 @@ extern Map *worldRPG[]; /* Game data (defined in "game.h")*/ Game game = { NULL, - {10*PXSIZE, 48*PXSIZE, 0, 0, 100, SPEED}, + {10*PXSIZE, 48*PXSIZE, 0, 0, 0, 0, 100, SPEED}, false, false, false, 0 /* debug variables*/ - , true, true + , false, false }; /* screen capture management code */ @@ -93,7 +93,7 @@ int main(void) { } timer_start(timer); - game.map_level = worldRPG[0]; + game.map_level = worldRPG[2]; #if USB_FEATURE @@ -137,7 +137,7 @@ int main(void) { { dfont( NULL ); drect( 5, 55,390, 75, C_WHITE ); - dprint( 10, 60, C_BLUE, "X= %d - Y= %d", game.player.x, game.player.y ); + dprint( 10, 60, C_BLUE, "X= %d - Y= %d / Wx= %d - Wy= %d", game.player.x, game.player.y, game.player.wx, game.player.wy ); } #endif diff --git a/src/map.c b/src/map.c index 7ea491d..e04091b 100644 --- a/src/map.c +++ b/src/map.c @@ -4,6 +4,9 @@ #include +extern Map *worldRPG[]; + + void render_map(Game *game) { Map *map_level = game->map_level; @@ -193,6 +196,7 @@ void render_map_by_layer(Game *game, int layer) { short int get_tile(Game *game, int x, int y, int l) { Map *map_level = game->map_level; + /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if * she's not found. */ return x>=0 && x < map_level->w && y>=0 && y < map_level->h ? @@ -208,3 +212,27 @@ short int get_walkable(Game *game, int x, int y) { map_level->walkable[y * map_level->w + x] : MAP_OUTSIDE; } +/* return the pointer to the map containing the given position */ +Map *get_map_for_coordinates( Game *game, int x, int y ) +{ + /* check if the current map contains the point */ + if (x>=game->map_level->xmin && xmap_level->xmax && + y>=game->map_level->ymin && ymap_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 + { + if (x>=current->xmin && xxmax && + y>=current->ymin && yymax) + return current; + i++; + current = worldRPG[i]; + } + 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 e255291..1586186 100644 --- a/src/map.h +++ b/src/map.h @@ -33,4 +33,7 @@ short int get_tile(Game *game, int x, int y, int l); /* Returns what is in the walkable layer at (x, y). */ short int get_walkable(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/player.c b/src/player.c index 07a347e..48f0f4b 100644 --- a/src/player.c +++ b/src/player.c @@ -35,19 +35,24 @@ void player_draw(Game *game) { void player_move(Game *game, Direction direction) { Player *player = &game->player; + /* How this player movement will modify the player x and y. */ char dx, dy; + /* If the player will collide with a hard tile or if the will go outside of * the map. */ if(player_collision(game, direction, P_CENTER)){ + /* If the will collide with the center of the player. */ dx = one_px_mov[direction*2]*player->speed; dy = one_px_mov[direction*2+1]*player->speed; + player_fix_position(game, dx, dy); } else{ if(player_collision(game, direction, P_RIGHTDOWN) || player_collision(game, direction, P_LEFTUP)){ + /* If the will collide with the edges of the player. */ /* I fix his position so he won't be partially in the tile. */ /* I invert dx and dy to fix the axis where he is not moving on. */ @@ -55,14 +60,20 @@ void player_move(Game *game, Direction direction) { */ dx = one_px_mov[direction*2]*player->speed; dy = one_px_mov[direction*2+1]*player->speed; + player_fix_position(game, dx==0, dy==0); } + /* If he won't collide with the center, so I just move him normally */ dx = one_px_mov[direction*2]*player->speed; dy = one_px_mov[direction*2+1]*player->speed; + player->x += dx; player->y += dy; } + + player->wx = game->map_level->xmin * PXSIZE + player->x; + player->wy = game->map_level->ymin * PXSIZE + player->y; } void player_action(Game *game) { @@ -77,38 +88,50 @@ bool player_collision(Game *game, Direction direction, /* Where is the tile where he will go to from his position. */ char dx = one_px_mov[direction*2]; char dy = one_px_mov[direction*2+1]; + if(!dx){ dx += nomov_axis_check; }else if(!dy){ dy += nomov_axis_check; } + dx = dx*(P_WIDTH/2+1); dy = dy*(P_HEIGHT/2+1); + /* The tile he will go to. */ int player_tile_x = player->x+dx; int player_tile_y = player->y+dy; + /* Handle a negative position diffrently than a positive one. */ if(player_tile_x < 0) player_tile_x = player_tile_x/T_WIDTH-1; else player_tile_x = player_tile_x/T_WIDTH; + 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 = get_walkable(game, player_tile_x, player_tile_y); + int speed = on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX ? walkable_speed[on_walkable] : 0; + /* if he's on a hard tile */ if(!speed){ return true; /* He will collide with it. */ } + player->speed = speed; + return false; /* He won't collide with a hard tile. */ } void player_fix_position(Game *game, bool fix_x, bool fix_y) { Player *player = &game->player; + /* I fix his poition on x or/and on y if y need to, so that he won't be over * the hard tile that he collided with. */ if(fix_x) player->x = player->x/T_WIDTH*T_WIDTH+P_WIDTH/2; + if(fix_y) player->y = player->y/T_HEIGHT*T_HEIGHT+P_HEIGHT/2; } From cb24bee3f80fe86bbcfa365a478ab42260d958b9 Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Mon, 14 Aug 2023 20:46:51 +0200 Subject: [PATCH 02/10] implementation of map change during gameplay by crossing map borders --- src/main.c | 6 +++--- src/map.c | 6 +++--- src/player.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/main.c b/src/main.c index f448a84..09153bb 100644 --- a/src/main.c +++ b/src/main.c @@ -32,11 +32,11 @@ extern Map *worldRPG[]; /* Game data (defined in "game.h")*/ Game game = { NULL, - {10*PXSIZE, 48*PXSIZE, 0, 0, 0, 0, 100, SPEED}, + {10*PXSIZE, 48*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED}, false, false, false, 0 /* debug variables*/ - , false, false + , false, true }; /* screen capture management code */ @@ -93,7 +93,7 @@ int main(void) { } timer_start(timer); - game.map_level = worldRPG[2]; + game.map_level = worldRPG[0]; #if USB_FEATURE diff --git a/src/map.c b/src/map.c index e04091b..df771d0 100644 --- a/src/map.c +++ b/src/map.c @@ -199,7 +199,7 @@ short int get_tile(Game *game, int x, int y, int l) { /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if * she's not found. */ - return x>=0 && x < map_level->w && y>=0 && y < map_level->h ? + return (x>=0 && x < map_level->w && y>=0 && y < map_level->h) ? map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; } @@ -208,7 +208,7 @@ 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 * found. */ - return x>=0 && x < map_level->w && y>=0 && y < map_level->h ? + return (x>=0 && x < map_level->w && y>=0 && y < map_level->h) ? map_level->walkable[y * map_level->w + x] : MAP_OUTSIDE; } @@ -231,7 +231,7 @@ Map *get_map_for_coordinates( Game *game, int x, int y ) 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; diff --git a/src/player.c b/src/player.c index 48f0f4b..d495c1b 100644 --- a/src/player.c +++ b/src/player.c @@ -41,6 +41,7 @@ void player_move(Game *game, Direction direction) { /* If the player will collide with a hard tile or if the will go outside of * the map. */ + if(player_collision(game, direction, P_CENTER)){ /* If the will collide with the center of the player. */ @@ -102,7 +103,32 @@ bool player_collision(Game *game, Direction direction, int player_tile_x = player->x+dx; int player_tile_y = player->y+dy; - /* Handle a negative position diffrently than a positive one. */ + /* 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 (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 = get_map_for_coordinates(game, worldX, worldY ); + if (map!=NULL && map!=game->map_level) + { + game->map_level = map; + + player->wx = worldX * PXSIZE; + player->wy = worldY * PXSIZE; + + player->x = (worldX - map->xmin ) * PXSIZE; + player->y = (worldY - map->ymin ) * PXSIZE; + + return false; + } + } + + + /* Handle a negative position differently than a positive one. */ if(player_tile_x < 0) player_tile_x = player_tile_x/T_WIDTH-1; else player_tile_x = player_tile_x/T_WIDTH; @@ -111,7 +137,7 @@ bool player_collision(Game *game, Direction direction, int on_walkable = 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; /* if he's on a hard tile */ From 217221cd6c737b21f781a43d685cbf3a45c8bf1e Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Mon, 14 Aug 2023 21:15:38 +0200 Subject: [PATCH 03/10] added a verification on walkability of the target tile on next map --- README.md | 4 ++-- src/main.c | 8 ++++---- src/player.c | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9189464..f4df062 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ A ce stade, on a déjà implémenté : - [ ] Fontes de caractères - [ ] Interaction - [ ] NPC -- [ ] Changement de map durant le jeu (en cours) +- [x] Changement de map durant le jeu ## Crédits @@ -28,4 +28,4 @@ Les tiles sont issues de Game Boy Top-down RPG Fantasy Tileset (FREE) Converties en niveau de gris avec Gimp Une version 1-bit (N&B) à été réalisée par Shadow15510 -Et une version couleur CG à été réalisée par Fcalva +Et une version couleur CG (palette EGA64) à été réalisée par Fcalva diff --git a/src/main.c b/src/main.c index 3d8cfd4..7a84413 100644 --- a/src/main.c +++ b/src/main.c @@ -32,11 +32,11 @@ extern Map *worldRPG[]; /* Game data (defined in "game.h")*/ Game game = { NULL, - {10*PXSIZE, 48*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED}, + {12*PXSIZE, 36*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED}, false, false, false, 0 /* debug variables*/ - , false, true + , false, false }; /* screen capture management code */ @@ -108,13 +108,13 @@ int main(void) { dgray(DGRAY_ON); #endif - +/* showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0); if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true); else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true); else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true); - +*/ do{ /* clear screen */ diff --git a/src/player.c b/src/player.c index d495c1b..3cb1efc 100644 --- a/src/player.c +++ b/src/player.c @@ -115,6 +115,12 @@ bool player_collision(Game *game, Direction direction, 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; + int backupwx = player->wx; + int backupwy = player->wy; + game->map_level = map; player->wx = worldX * PXSIZE; @@ -123,6 +129,24 @@ bool player_collision(Game *game, Direction direction, player->x = (worldX - map->xmin ) * PXSIZE; player->y = (worldY - map->ymin ) * PXSIZE; + int on_walkable = get_walkable(game, player->x/T_WIDTH, + player->y/T_HEIGHT); + + int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX) ? + walkable_speed[on_walkable] : 0; + + /* if he's on a hard tile and we need to revert the changes as */ + /* tile on the next side of the border is not walkable */ + + if(!speed){ + game->map_level = backupmap; + player->x = backupx; + player->y = backupy; + player->wx = backupwx; + player->wy = backupwy; + return true; /* He will collide with it. */ + } + return false; } } From df33d2f090665b9db5ff4aa5578c68b70372ac09 Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Tue, 15 Aug 2023 12:55:06 +0200 Subject: [PATCH 04/10] added a new 1bit (N&B) target for CG to test the maps in the emulator --- CMakeLists.txt | 22 ++++++++++++++++++---- TODO.txt | 6 ++++++ assets-cg/demo_PNJ.png | Bin 0 -> 4759 bytes assets-cg/fxconv-metadata.txt | 4 ++++ assets-cg/levels/fxconv-metadata.txt | 4 ++++ assets-cg/levels/tileset1b_CG.png | Bin 0 -> 43967 bytes assets-fx/demo_PNJ.png | Bin 0 -> 4701 bytes assets-fx/fxconv-metadata.txt | 4 ++++ assets-fx/levels/backup/tileset1b.png | Bin 0 -> 40631 bytes assets/level0.tmx | 21 ++++++++++++++++++--- 10 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 TODO.txt create mode 100644 assets-cg/demo_PNJ.png create mode 100644 assets-cg/levels/tileset1b_CG.png create mode 100644 assets-fx/demo_PNJ.png create mode 100644 assets-fx/levels/backup/tileset1b.png diff --git a/CMakeLists.txt b/CMakeLists.txt index b641aaf..5a9e915 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ find_package(LibProf 2.4 REQUIRED) #set the color mode either to 1b or 2b set(COLORMODE_fx 2b) -#set the color mode either to 2b or EGA64 -set(COLORMODE_cg EGA64) +#set the color mode either to 1b, 2b or EGA64 +set(COLORMODE_cg 1b) fxconv_declare_converters(assets/converters.py) @@ -35,10 +35,15 @@ set(ASSETS set(ASSETS_cg assets-cg/demo_player.png + assets-cg/demo_PNJ.png assets-cg/player_face.png assets-cg/font.png ) +set(ASSETS_cg_1b + assets-cg/levels/tileset1b_CG.png +) + set(ASSETS_cg_2b assets-cg/levels/tileset2b_CG.png ) @@ -49,6 +54,7 @@ set(ASSETS_cg_EGA64 set(ASSETS_fx assets-fx/demo_player.png + assets-fx/demo_PNJ.png assets-fx/player_face.png assets-fx/font.png # ... @@ -64,7 +70,7 @@ set(ASSETS_fx_2b # ... ) -fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} ${ASSETS_fx_1b} ${ASSETS_fx_2b} ${ASSETS_cg_2b} ${ASSETS_cg_EGA64} WITH_METADATA) +fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} ${ASSETS_fx_1b} ${ASSETS_fx_2b} ${ASSETS_cg_1b} ${ASSETS_cg_2b} ${ASSETS_cg_EGA64} WITH_METADATA) if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} ) @@ -83,11 +89,14 @@ if("${COLORMODE_fx}" STREQUAL 2b) 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() @@ -111,6 +120,11 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) + if("${COLORMODE_cg}" STREQUAL 1b) + generate_g3a(TARGET myaddin OUTPUT "PrjPC1b.g3a" + NAME "Col RPG 1bit" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) + endif() + if("${COLORMODE_cg}" STREQUAL 2b) generate_g3a(TARGET myaddin OUTPUT "PrjPC2b.g3a" NAME "Col RPG Grey" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..e9f2bcf --- /dev/null +++ b/TODO.txt @@ -0,0 +1,6 @@ +- Jeu de tuile 1bit pour CG pour avoir la version 1bit vérifiable en fonctionnement dans l'émulateur de Heath +- corriger les tuiles 1bit pour les rivières (tiles 1 2 3 et 4) avec niveaux de diphering pour tiles 1 et 3 (gris 33% et 66%) +- ajouter face pour dialogue pour PNJ +- ajouter indicateur visuel pour action joueur quand on est proche d'un PNJ ou d'un panneau + +- faire des fonts lisibles avec le set `print` disponible intégralement \ No newline at end of file diff --git a/assets-cg/demo_PNJ.png b/assets-cg/demo_PNJ.png new file mode 100644 index 0000000000000000000000000000000000000000..f776fdc951995e380a53bd405b4897a315157d67 GIT binary patch literal 4759 zcmeHKdpMM78y}sBFk1~J)-+maHAi!N*N7Y^1|gyJ_0G&YdNGG)2IH`4OE#(vOI>VM zu@04N%jzhKu(eUCv>}Ab+I*z8?WlcbsJOoUr|bImKXYC0%yanNzx%#_&;8ujyeYok z?uPni`WOtxkmupz2Y#`dM{frBu6)TFz+k4!;sSzHesBz4u8@h*NCdBnl_PjWjfycC zbz9T^)zN?0%t`JFu3vs313UNE3mcoWEv}3V?HyF-&?UVM#<$I<&kCOV($Twiq^pMe zdi$}j`f!@cPo z^tqbc&)8uBZ%7iYB$j`H@7;%=Y2nV#$0lK4E>DG02QOpO!Zt%?bN0TJGaPVd3KUQK zU#QhT;9^bFzs46AdYoeAnAaiak`VyXH2g>vAvSl)m1;&Ji|Y;a9mVTt&;enrD5Mv-{3YtcUKwX}5z3SMiQVI=Yv*r_W$E*U>jnLtKLw*6H+m zi1CLqE}pmc)G1wnd)1gPG{)if9Lc$PlM%to5VT}w6sFJLl~TVk{L+<v%9TJ1o1m6!xxYa(H+;ATrPFXluZ+xTZ?Fv?Xmt zNO)`2{XmnD<5~Mo^=Fu@OSt6u`)}c)EBA)R544_pxWOp=i&mfeGZ<}$AFm46YjZLz z5VLUfmJ}l~reX2io$ZcW4V$*#>6>q5tk`}hGkrAeN%s#%;ytsd*xd#{MW6Y}pz0Hg zzRn(#<(->*yD|)>-{mRtPIC)d8^TJ;E}rmbZ-ZugTRt!)KSB~7IaJ;|no=zvve$ zx3%ggudj{PerGvy-8O8r(zx%i$h7Q5@@tpD5z9}=wgb;Y>7(7FI!kUm%R6rqP>aFn zSfS3&zC35=cUKQwxC6OqHLL1;=QkuC&Uc-!`*uzb_CjU1zvc8*=6d`ytj_i6*IJBUv3i0snJCPab;Z=>y64D)w9}4 zS1o!p1I~`&4ka}_d69|?cs8mTSKq{%JnL_V8*g-oInAVI{(ssU3LBSw%5=8g%`53I5f7O69{+K`4=eZK zmE>TLvTk|R?>0cld^P5xpgg3&VjG~YBv)fh$k`8GH&~?u=|gJ>nFIf1G!K zFfKyK5fN56=-aCyKp;U>FkUT*lqw-Lm!Rc^z*w_PCg8OYRRot1#P`KJ%M=KnPNI`2 zL{~K$O(Qty#9$C{o3hUH`` zi9(i0$P+D;D%WU0G9J)BS||fR!zcS8N?DXbh`2^0QkB(23X$-=y*x@0sZB>DBqNcC z1VEL*D|M1fcOKvOy@f`CFjOMfS^=>qAyugOgIJSd)9h%|nHUH#f6qG!{VsPc7@+uk z$VDcM(uBuz;Sx0dA(2doiXiQf#fDiz5ravzqlno=x*Z!KvJr$vM3@4E$z+H*R0cAE ziYHa7V5tz%Pyuoh3V2vF3WH8zv4{*R2PV>KOaW0Kw4)GdGyzk@q6=UqojHNRM}dN> zgd-C8&DurY>#;Z9N2qXi9g*9~w2(%U;7sy$Gz$%#{Kqiai5;P&zjg0@|XZ$SwMGt^_%E?FRJ0;hYTpy*tM}eoRYf7$< zQsAS&Q`Plx_~6EdqEInkMjccfnwe?6IPO*=)H-uo8nYn5TJk zFgXVnfJI#ukMFAcP|sLzAvxW}@+nvf;<-2l*j&v@_cX#R)^lFh^XA9(roH(IG&iQ% zvdpDP!;1`xx;bw?yVkO0yFqo^zyeOLVX_go_K#R=-=dPaYpy^s$$PvHUdpdUi#Aro i*Hw-7RT*@)p3~tk$5|?&Eq8$r4A0furEKNKZGQt2?Gn)d literal 0 HcmV?d00001 diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt index 2d52907..a631b2a 100644 --- a/assets-cg/fxconv-metadata.txt +++ b/assets-cg/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 diff --git a/assets-cg/levels/fxconv-metadata.txt b/assets-cg/levels/fxconv-metadata.txt index 5caafd2..de727b0 100644 --- a/assets-cg/levels/fxconv-metadata.txt +++ b/assets-cg/levels/fxconv-metadata.txt @@ -1,3 +1,7 @@ +tileset1b_CG.png: + type: bopti-image + name: img_tilesetnpp + tileset2b_CG.png: type: bopti-image name: img_tilesetnpp diff --git a/assets-cg/levels/tileset1b_CG.png b/assets-cg/levels/tileset1b_CG.png new file mode 100644 index 0000000000000000000000000000000000000000..089c983d7ae21901db68a5ff8b7c0dfb9a4a15f8 GIT binary patch literal 43967 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 b>&vr?X4u*!w6<0PV}c+gEVyXa^5p*l{ImZ0 literal 0 HcmV?d00001 diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt index 0bfccdd..0ca3da4 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 diff --git a/assets-fx/levels/backup/tileset1b.png b/assets-fx/levels/backup/tileset1b.png new file mode 100644 index 0000000000000000000000000000000000000000..63f9c7b9863c876ac466fccaa6c0b9d4f9496d38 GIT binary patch literal 40631 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 z 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 - + @@ -90,10 +90,25 @@ - + - + + + + + + + + + + + + + + + + From 6075e47ba808aeedf9da5bf9fa4f41e6690bf16b Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Tue, 15 Aug 2023 16:50:51 +0200 Subject: [PATCH 05/10] try to import Extra Data from world and maps --- assets/converters.py | 89 ++++++++++++++++++++++++++++++++++---- assets/fxconv-metadata.txt | 1 + assets/level0.tmx | 9 ++-- src/game.h | 5 +++ src/main.c | 4 +- src/map.c | 1 + 6 files changed, 95 insertions(+), 14 deletions(-) diff --git a/assets/converters.py b/assets/converters.py index ce4c33d..a7ab5ae 100644 --- a/assets/converters.py +++ b/assets/converters.py @@ -29,13 +29,11 @@ def convert_world(input, output, params, target): structWorld = fxconv.Structure() for i in range(nbMaps): - nameMap = data["maps"][i]["fileName"].replace(".tmx","") nameMapFree = nameMap.split("/")[-1] #count the number of "back" (cd ..) to locate the map on the computer nbRetour = nameMap.count("..")+1 #create the map absolute path - nameTMX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".tmx" nameJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" @@ -43,7 +41,6 @@ def convert_world(input, output, params, target): commandline = 'tiled --export-map json ' + nameTMX + ' ' + nameJSON print( "TILED COMMAND LINE FOR MAPS : ", commandline ) os.system( commandline ) - mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" print("Map ", i , " name : ", mapPath ) @@ -60,19 +57,54 @@ def convert_world(input, output, params, target): ymax = data["maps"][i]["y"] + data["maps"][i]["height"] print( "ymax = ", ymax ) - map = convert_map( mapPath, output, params, target, xmin, ymin, xmax, ymax) + map = get_tile_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax) print( "Map = ", map ) structWorld += fxconv.ptr( map ) structWorld += fxconv.u32(0) #generate ! + #the map data fxconv.elf(structWorld, output, "_" + params["name"], **target) + + +""" + structExtra = fxconv.Structure() + + for i in range(nbMaps): + + nameMap = data["maps"][i]["fileName"].replace(".tmx","") + nameMapFree = nameMap.split("/")[-1] + #count the number of "back" (cd ..) to locate the map on the computer + nbRetour = nameMap.count("..")+1 + #create the map absolute path + + mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" + print("Map ", i , " name : ", mapPath ) + + xmin = data["maps"][i]["x"] + print( "xmin = ", xmin ) + + ymin = data["maps"][i]["y"] + print( "ymin = ", ymin ) + + xmax = data["maps"][i]["x"] + data["maps"][i]["width"] + print( "xmax = ", xmax ) + + ymax = data["maps"][i]["y"] + data["maps"][i]["height"] + print( "ymax = ", ymax ) + + ext = get_extra_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax ) + print( "Data = ", ext ) + if (ext!=fxconv.u32(0)): structExtra += fxconv.ptr( ext ) + + structExtra += fxconv.u32(0) + #and all the extra data (PNJ, SGN, ...) + fxconv.elf(structExtra, output, "_" + params["name"]+"Extra", **target) +""" - - -def convert_map(input, output, params, target, xmin, ymin, xmax, ymax): +def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): print( "WE ARE COMPUTING THE MAP : ", input ) data = json.load(open(input, "r")) @@ -131,7 +163,7 @@ def convert_map(input, output, params, target, xmin, ymin, xmax, ymax): print( "Walkable Tile Data in layer : ", layer_walkable) break elif i==nbTilelayer: - printf( "ERROR : No Walkable layer data !!!" ) + print( "ERROR : No Walkable layer data !!!" ) walk_data = bytes() layer = data["layers"][layer_walkable] @@ -154,7 +186,7 @@ def convert_map(input, output, params, target, xmin, ymin, xmax, ymax): print( "Background Tile Data in layer : ", layer_background) break elif i==nbTilelayer: - printf( "ERROR : No Background layer data !!!" ) + print( "ERROR : No Background layer data !!!" ) layer_data = bytes() layer = data["layers"][layer_background] @@ -185,3 +217,42 @@ def convert_map(input, output, params, target, xmin, ymin, xmax, ymax): return structMap + + +def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): + 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 + print( "I found ", nblayer, " of extradata") + + #index of the various layers (may change from one map to another) + layer_extradata = 0 + + #import the foreground layer of the map + for i in range(nblayer+1): + datavalid = data["layers"][i] + if datavalid["name"]=="ExtraData": + layer_extradata = i + print( "Extra Data in layer : ", layer_extradata) + break + elif i==nblayer: + print( "ERROR : No ExtraData layer data !!!" ) + return fxconv.u32(0) + + #create the structure of the map + structData = fxconv.Structure() + + layer = data["layers"][layer_extradata] + for i in layer["objects"]: + x = i["x"] + xmin + y = i["y"] + ymin + st = i[ "type" ] + print( "OBJECT X= ", x, " Y= ", y, "STR= ", st ) + structData += fxconv.u16( x ) + structData += fxconv.u16( y ) + structData += fxconv.string( st ) + + + return structData diff --git a/assets/fxconv-metadata.txt b/assets/fxconv-metadata.txt index 77b9eb0..0176752 100644 --- a/assets/fxconv-metadata.txt +++ b/assets/fxconv-metadata.txt @@ -5,4 +5,5 @@ *.world: custom-type: world +# extra: extraRPG name: worldRPG diff --git a/assets/level0.tmx b/assets/level0.tmx index 2090f4e..9e150be 100644 --- a/assets/level0.tmx +++ b/assets/level0.tmx @@ -91,21 +91,24 @@ + + + - + - + - + diff --git a/src/game.h b/src/game.h index b8b8615..5dc51c5 100644 --- a/src/game.h +++ b/src/game.h @@ -32,6 +32,11 @@ typedef struct { } Player; +typedef struct { + uint16_t x, y; + char type[3]; +} ExtraData; + typedef struct { /* width, height and the number of layer of the map */ diff --git a/src/main.c b/src/main.c index 7a84413..eef0fec 100644 --- a/src/main.c +++ b/src/main.c @@ -108,13 +108,13 @@ int main(void) { dgray(DGRAY_ON); #endif -/* + showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0); if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true); else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true); else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true); -*/ + do{ /* clear screen */ diff --git a/src/map.c b/src/map.c index df771d0..94b43ff 100644 --- a/src/map.c +++ b/src/map.c @@ -5,6 +5,7 @@ #include extern Map *worldRPG[]; +//extern ExtraData *extraRPG[]; void render_map(Game *game) { From c5975889bc1da41b369eef51298b82611b758f39 Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Wed, 16 Aug 2023 17:34:45 +0200 Subject: [PATCH 06/10] Added importation of ExtraData from ObjectLayer in Tiled TMX files --- CMakeLists.txt | 2 +- assets/converters.py | 93 ++++++++++++++++++-------------------- assets/fxconv-metadata.txt | 6 ++- clean | 1 + src/game.c | 6 ++- src/game.h | 21 +++++++-- src/main.c | 15 ++++-- src/map.c | 2 +- 8 files changed, 84 insertions(+), 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a9e915..df83849 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ find_package(LibProf 2.4 REQUIRED) #set the color mode either to 1b or 2b set(COLORMODE_fx 2b) #set the color mode either to 1b, 2b or EGA64 -set(COLORMODE_cg 1b) +set(COLORMODE_cg 2b) fxconv_declare_converters(assets/converters.py) diff --git a/assets/converters.py b/assets/converters.py index a7ab5ae..cd3b933 100644 --- a/assets/converters.py +++ b/assets/converters.py @@ -27,7 +27,8 @@ def convert_world(input, output, params, target): print( "So let's go ... ") structWorld = fxconv.Structure() - + #structExtra = fxconv.Structure() + for i in range(nbMaps): nameMap = data["maps"][i]["fileName"].replace(".tmx","") nameMapFree = nameMap.split("/")[-1] @@ -61,47 +62,22 @@ def convert_world(input, output, params, target): print( "Map = ", map ) structWorld += fxconv.ptr( map ) + #ext = get_extra_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax ) + #print( "Data = ", ext ) + #if (ext!=fxconv.u32(0)): structExtra += fxconv.ptr( ext ) + structWorld += fxconv.u32(0) - #generate ! - #the map data - fxconv.elf(structWorld, output, "_" + params["name"], **target) - - -""" - structExtra = fxconv.Structure() - - for i in range(nbMaps): - - nameMap = data["maps"][i]["fileName"].replace(".tmx","") - nameMapFree = nameMap.split("/")[-1] - #count the number of "back" (cd ..) to locate the map on the computer - nbRetour = nameMap.count("..")+1 - #create the map absolute path - - mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" - print("Map ", i , " name : ", mapPath ) - - xmin = data["maps"][i]["x"] - print( "xmin = ", xmin ) - - ymin = data["maps"][i]["y"] - print( "ymin = ", ymin ) - - xmax = data["maps"][i]["x"] + data["maps"][i]["width"] - print( "xmax = ", xmax ) - - ymax = data["maps"][i]["y"] + data["maps"][i]["height"] - print( "ymax = ", ymax ) - - ext = get_extra_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax ) - print( "Data = ", ext ) - if (ext!=fxconv.u32(0)): structExtra += fxconv.ptr( ext ) - - structExtra += fxconv.u32(0) + #structExtra += fxconv.u32(0) + """ #and all the extra data (PNJ, SGN, ...) - fxconv.elf(structExtra, output, "_" + params["name"]+"Extra", **target) -""" + fxconv.elf_multi( + [("_" + params["varMapData"], structWorld), + ("_" + params["varExtraData"], structExtra)], + output, **target) + """ + #generate ! + fxconv.elf(structWorld, output, "_" + params["name"], **target) def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): @@ -174,6 +150,18 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): structMap += fxconv.ptr(walk_data) + nbextra = 0 + extradata = fxconv.Structure() + + nbextra, extradata = get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax) + + if (nbextra==0): + structMap += fxconv.u32( 0 ) + structMap += fxconv.u32( 0 ) + else: + structMap += fxconv.u32( int(nbextra) ) + structMap += fxconv.ptr( extradata ) + #extraction of the data contained in the layer "Background" and "Foreground" of the map @@ -212,8 +200,6 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): layer_data += fxconv.u16(tile-1) structMap += fxconv.ptr(layer_data) - #generate ! - #fxconv.elf(structMap, output, "_" + params["name"], **target) return structMap @@ -239,20 +225,29 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): break elif i==nblayer: print( "ERROR : No ExtraData layer data !!!" ) - return fxconv.u32(0) + return 0, fxconv.u32(0) #create the structure of the map structData = fxconv.Structure() + + nbExtraData = 0 layer = data["layers"][layer_extradata] for i in layer["objects"]: + nbExtraData = nbExtraData + 1 x = i["x"] + xmin y = i["y"] + ymin - st = i[ "type" ] - print( "OBJECT X= ", x, " Y= ", y, "STR= ", st ) - structData += fxconv.u16( x ) - structData += fxconv.u16( y ) - structData += fxconv.string( st ) + nme = i["name"] + tpe = i["type"] + for j in i["properties"]: + stg = j[ "value" ] + print( "OBJECT X= ", x, " Y= ", y, "STR= ", stg ) + print( " Type= ", tpe, " Name= ", nme ) + + structData += fxconv.u16( int(x) ) + structData += fxconv.u16( int(y) ) + structData += fxconv.string( nme ) + structData += fxconv.string( tpe ) + structData += fxconv.string( stg ) - - return structData + return nbExtraData, structData diff --git a/assets/fxconv-metadata.txt b/assets/fxconv-metadata.txt index 0176752..d38d6f6 100644 --- a/assets/fxconv-metadata.txt +++ b/assets/fxconv-metadata.txt @@ -3,7 +3,9 @@ # name_regex: (.*)\.json map_\1 -*.world: +WorldRPG.world: custom-type: world -# extra: extraRPG + #name: xxx #unused but mandatory (Do not touch) + #varMapData: worldRPG + #varExtraData: extraRPG name: worldRPG diff --git a/clean b/clean index 3e99971..db7550f 100755 --- a/clean +++ b/clean @@ -3,6 +3,7 @@ rm -f *.json rm -r __pycache__ cd .. rm -r build-cg +rm -r build-cg-push rm -r build-fx rm *.g1a rm *.g3a diff --git a/src/game.c b/src/game.c index 64d3765..284ce7c 100644 --- a/src/game.c +++ b/src/game.c @@ -7,8 +7,12 @@ #include #include + + void game_logic(Game *game) { - // to be done + + + } void draw(Game *game) { diff --git a/src/game.h b/src/game.h index 5dc51c5..af724b5 100644 --- a/src/game.h +++ b/src/game.h @@ -2,6 +2,7 @@ #define GAME_H #include +#include @@ -33,17 +34,23 @@ typedef struct { typedef struct { - uint16_t x, y; - char type[3]; + uint16_t x; + uint16_t y; + char *name; + char *type; + char *dialog; } ExtraData; typedef struct { /* width, height and the number of layer of the map */ - uint16_t w, h; + uint16_t w; + uint16_t h; uint16_t nblayers; uint16_t tileset_size; + /* world coordinates of the upper left and bootom right*/ + /* corners of the current map to be multiplied in game by PXSIZE */ uint16_t xmin; uint16_t ymin; uint16_t xmax; @@ -57,8 +64,13 @@ typedef struct { uint8_t *walkable; + uint32_t nbextradata; + ExtraData *extradata; + /* list of all the tiles */ uint16_t *layers[]; + + } Map; @@ -80,8 +92,9 @@ typedef struct { long int frame_duration; /* variables used for debuging */ - bool debug_player; bool debug_map; + bool debug_player; + bool debug_extra; } Game; /* (Mibi88) TODO: Describe what this function is doing. */ diff --git a/src/main.c b/src/main.c index eef0fec..07d98d8 100644 --- a/src/main.c +++ b/src/main.c @@ -26,8 +26,8 @@ extern bopti_image_t player_face_img; -extern Map *worldRPG[]; +extern Map *worldRPG[]; /* Game data (defined in "game.h")*/ Game game = { @@ -36,7 +36,7 @@ Game game = { false, false, false, 0 /* debug variables*/ - , false, false + , false, false, true }; /* screen capture management code */ @@ -108,13 +108,13 @@ int main(void) { dgray(DGRAY_ON); #endif - +/* showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0); if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true); else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true); else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true); - +*/ do{ /* clear screen */ @@ -139,6 +139,13 @@ int main(void) { drect( 5, 55,390, 75, C_WHITE ); dprint( 10, 60, C_BLUE, "X= %d - Y= %d / Wx= %d - Wy= %d", game.player.x, game.player.y, game.player.wx, game.player.wy ); } + if (game.debug_extra) + { + dfont( NULL ); + //drect( 155, 80, 390, 150, C_WHITE ); + for (int i=0; inbextradata; i++ ) + dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %s", game.map_level->extradata[i].x, game.map_level->extradata[i].y, game.map_level->extradata[i].dialog ); + } #endif /* start the logic of the game */ diff --git a/src/map.c b/src/map.c index 94b43ff..5670485 100644 --- a/src/map.c +++ b/src/map.c @@ -5,7 +5,7 @@ #include extern Map *worldRPG[]; -//extern ExtraData *extraRPG[]; +extern ExtraData *extraRPG[]; void render_map(Game *game) { From 47b8bfa25a9681a1dafc7723685fabbe33747c5e Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Wed, 16 Aug 2023 19:25:24 +0200 Subject: [PATCH 07/10] implementing the basis of player action --- CMakeLists.txt | 8 ++++++++ assets-cg/INFO_Icon.png | Bin 0 -> 4932 bytes assets-cg/NPC_Icon.png | Bin 0 -> 4809 bytes assets-cg/SGN_Icon.png | Bin 0 -> 4819 bytes assets-cg/SignAction.png | Bin 0 -> 5020 bytes assets-cg/fxconv-metadata.txt | 16 ++++++++++++++++ assets-fx/INFO_Icon.png | Bin 0 -> 4961 bytes assets-fx/NPC_Icon.png | Bin 0 -> 4923 bytes assets-fx/SGN_Icon.png | Bin 0 -> 4912 bytes assets-fx/SignAction.png | Bin 0 -> 4952 bytes assets-fx/fxconv-metadata.txt | 15 +++++++++++++++ src/game.c | 31 +++++++++++++++++++++++++++++++ src/game.h | 19 ++++++++++++++----- src/main.c | 5 ++--- src/player.c | 28 +++++++++++++++++++++++++++- 15 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 assets-cg/INFO_Icon.png create mode 100644 assets-cg/NPC_Icon.png create mode 100644 assets-cg/SGN_Icon.png create mode 100644 assets-cg/SignAction.png create mode 100644 assets-fx/INFO_Icon.png create mode 100644 assets-fx/NPC_Icon.png create mode 100644 assets-fx/SGN_Icon.png create mode 100644 assets-fx/SignAction.png diff --git a/CMakeLists.txt b/CMakeLists.txt index df83849..6a7f080 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,10 @@ set(ASSETS set(ASSETS_cg assets-cg/demo_player.png assets-cg/demo_PNJ.png + assets-cg/SignAction.png + assets-cg/NPC_Icon.png + assets-cg/SGN_Icon.png + assets-cg/INFO_Icon.png assets-cg/player_face.png assets-cg/font.png ) @@ -55,6 +59,10 @@ set(ASSETS_cg_EGA64 set(ASSETS_fx assets-fx/demo_player.png assets-fx/demo_PNJ.png + assets-fx/SignAction.png + assets-fx/NPC_Icon.png + assets-fx/SGN_Icon.png + assets-fx/INFO_Icon.png assets-fx/player_face.png assets-fx/font.png # ... diff --git a/assets-cg/INFO_Icon.png b/assets-cg/INFO_Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f07aa4e740ac876a67f86b1f04e5df0ec27c07c5 GIT binary patch literal 4932 zcmeHKc~n#95)X$%?*i=h2&!5z9EX%qCua^ zVpJNj3MzuuNENLjZipg2YZWceS}THeK`m9}eF>;|UjOl&*Z<5pcl&1MH#5JPZ%)1( zar}e<1RnwphZ`V_M6FIESEi#xY`zvHqDG}0 zhco`%wq=&7)!%j1-RXjVr3mpk_fwYaJ+yLsxN}^{_f-$VuxFe0W;0TjyG4z@!ra;Q z;sJgsaq>&gUHK)24a+_Cmu6mha&IEK89Os&zo%j79dm2*Y10v2}t3xDQ)_M3+if0bL+IGQGrh%^{-g- zw)N$$D&GYndM?f2%N4Ipcb0{De7mE0tkA>B^ecMx;)xpf4d(w~C9b(KcgNmw=1sQF zXs_V?(6IK0)#oN{xHhXx;r1Pwv^&UNNW5_=qL&w*o!tJZB?m=e9x zdT4y{x{Tk(<;^MF<}^GuXaoA4%R#Y&Nz3!Mb9z@nwQYdh7$Oz z@0PEabBXzr7BLlkk-Z$hexziU!;)Wbu&e}p%h%6BNyC=&s5waw%>@x&ic=AS#YK^a zj`VXU#g%EZ9UUXq^8>EJmtwLaAl#6nmpwWh9TM+5eaR)nZ!CXa=wtRS+ga+WUp8{f zu-H9g=m$?t?_26UleA%z$ud8{Yw)^Ljizl@G>|fC7SC#3 z_|n96p@`}NX1pxa2W+i~u>SIBg@dJV(S>0N15%;3cBa`PechORc=z1vY5Of1dD*Xv zE%Le)RywJgr;M!ZeKh(b+|{&2&my;vtO<*=~nXHXU>g^qKic73b#mxc;p6ZO z7ccYCr`2B!^*`oz{}pB5z|*lNas=b3*9cbLq$&8QRo;QgMGa$Wq#n_x#6^AY@<;DpN&J)Wm~i=RFvQtf zGkjoIZF6B)b?}u#c{K7+gKyp5A73myeX)6S(~{!T`6q%FMkfEptABLO7&fQ;>l4`e zY0qz)Qv=ps6hqTcc(x>E4q0o^Az$lKjU=Fv~WmmeV?E7NO7Mfc}>L<>`t8mF@%LVmvZvm6M#Gu-NA(96HEp=w z(Rn0$SjqN|2g9pz&&=YvaBb?3V1)Q6!Kg?U#X*QhMS*1+DM~S_w6;-#3k^4FVI&R3 zh*C6FspgUXsH!Frl`aww4>(*ps% zcq9deX(1}rU@%Y&Oo~RAN~LqTTq=!0WiZG8J{*>Va4KM=mD_MdJ4sHVRUeDy`iL zko}P+rj&mm>!a9g5_>wm0|DmmaX-?2m%CjVXo*A+UxQ@Y!V~g&B%6Oora_c4$o|S^ z$WS^nm_=rBxiT_~5gbJ3%D4x-_Dj1Ygse)5cs#cw97uX1gBE>=;i9w-#SP`eg zm>d}JNO4MartyP7qEw+t7;Iyc9>irZXlyo(OQSJa>|WMWQJo%iq79QyqcFQAwz5DV z89*#->r((=hXuJn(K-~yG&+e!lg=aALL%BM?d?qr?Ji2JQV%rd+d96d=abNk?yv4G zkgl|gh(vqaLNLedJu!nf~6?yV|2Ynju~Jb8kq_*1=)ZGvS&jaYo{{cV{L;1wedt_Fv&Cy znI0seb0HcVqHzLg42VV}QF{`m+IIE3j6xIJ43C z5B_>;@eg_c(4U=r62G76`b^g+G4M&spS$ZbU7y6jCn*|?Op|blcZR?+2?F%pVk%YoF-oL{iQzmvVaPXsH0sK zBhM9|%~@2EyGD_ipoc2t9m5!1qOlI^;bn=F>fy?{DU^NUQuV&R*Zo&ren@s?31sC8 zles>#E?-6ZD&z}U=*etza@*~}@r0IvrLIv8;o|XShfPl&+;kst!69qzmX%x6Z}ZP| zYR}Y9x3W7oFny1VDrn2WU+{j_Kqp)uFeMtROqrD4gnGL@iC7_LwO0?i{-(pi{b>h1 z>xSXYzkg=O)fis{{&hk4JUi=bNZDXk%j=V`W^)qmkCukuqwxD19qw*tO=fC`ZoA;{ zR}S73aXhxOF*e517dtfJikoG`fr35Rm4lyu{p5lBvTKp@1Dr8_PEGCKumip879$(` z&JS$4=V#7tO8?HEG=6D>Y3sE8Gp#yHMQGWfO3N_oeK*0YG)0~?EdZ1VClti<_eZ6y F_%9ykU&#Of literal 0 HcmV?d00001 diff --git a/assets-cg/NPC_Icon.png b/assets-cg/NPC_Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..60597e53d4f57bc5444b58ca036b7129be2bc573 GIT binary patch literal 4809 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 literal 0 HcmV?d00001 diff --git a/assets-cg/SignAction.png b/assets-cg/SignAction.png new file mode 100644 index 0000000000000000000000000000000000000000..891b8247502bf40d0638262ae5068bae019818fb GIT binary patch literal 5020 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 literal 0 HcmV?d00001 diff --git a/assets-fx/SignAction.png b/assets-fx/SignAction.png new file mode 100644 index 0000000000000000000000000000000000000000..ced6850a6fcd9b3086c6cf4db8b44cbc8d98eb5a GIT binary patch literal 4952 zcmeHKX;c$g7LK%ofTFe_D(D!)qKK7LDwU9w1jPV?8qJAOux-#vRV4(;ViHIMS8Q#t z1r-IA&81P4r3ZAx)*eIz1zf-dmv&T|abIvpWNf5g0xHh*AJ1w3nR6e7#lQaDK!eMT~wL^9c&_#9J zeKLJn^PtUs?eo3w3?0GTwj?7lSpQ~L+34{V!nTK(YSzVJSZ}YO;tLa|cV^`bSW!MU zYSs81GG)#4D;qi*XUv#nppW?4-c{{z+dFTc>8bOWH~;+hblv0plA;7*Q&WECoyJC9 zi|AJSGHq>SU$~&Qps4?hi^GH9wD`bej~zy1DAaFU>+ts zfB3-b139^>MO&Hw-E_;`$ZDx>=B7ifCige!+~-l+g_{{|n>rS@-H_H+? zp3OPfi(4m+efr`@-H;1Kj%d)s)z=G$mpSA6u* z`3*kRo=92>Y)5v})VQYQE>}@!e zsa5?v5`(!Vb>GlVy;N3apZ0dGTW?7ymYnQxTHcymtF}mPT zhL_l_ew|C!fkwTL&p*Pa6wa%14V!x*^YZ!9#>3J!;ma$<`MC*#J>sHyC+(yC_SOYQ z^REUt&fcHZd)-ZsehQk`tzp$_`q9LU%F~{&B5e;{LZxxAnm8b7xzr zrmf$oS~?0&xY$NC@{esd+n7a>lKlzh(FgB&^ayJfBlX#KP*kF-ImljDmwrCo2Z>_7v9_xhplhQx>x@4 zutb^b4ICNjrWr;ZHR z`u1;O3HNH`m$pRFXuaH3B9SCiBzkxHz?sX=SzkJ(O5(h_LRK2&-1~UIaO7u~;poPx zv+O3V8tN0CbKc{)e2^$jy7;T6z>&LG(qB6~cBp^ri}AM{ckAC-)12K|;d^%9Mi?4m z8g-`NSZhMnspj9QiyKWV<=i4OF zc#ZNH7-AhNFs#DG(=bA-X5yq)PBG1D9T;OYn%@Mo4ks2+M!K9*sx(5zlV2(rbQLLN zgmJ~NSSO;QR3Y(tYG(X&84AZLEM!=5F>r5LW-;hi z6XOCQBU~(@i?n)*jxtdu3!aK(JJxb~ zCIZ~w<9=lQu6C<2uo8>0KrIn#NiQ@|$gsr6NG+ivG3%{>=ZmtrBm&7Pm;<3)QV#J^ zln-$cfr2FDz9h=??Ew|4F&J?TL0O;xI8z01D2|+iayfhm;UX}E%H;|GL2x0qf~W9B z5d}e^+#V1!^eUiAJf>$>7AO)xp$dY{ms2Ff<*-o*C145?pg00ia+Hno@Hl;TJC0a1qFq6}TYiSDxiUGvp7M%hBs|TnB6X_}3sMX7~ z+880jk`mqGX_YtKud68`Dg&@sWKn##=4Vn1yPmp^K#a<|MW7a@5H6yn2j5-_X)ooB-&LaQu0Cu8$5HU~rgr$j%NWpKS~svqnB z+TLZ*W6}X?y4Ju11p}G&ej;~s2J-!!pKiH*&Jc9^mmr_S?-#nh(Dg|Se3J1Ob$y}h zlNk6U<1gy^%jk0W@J>f*z#lymcw^iDYU~8?wr3-sIysO=D@buiz>~c$WR8JG>+58> zdeJhohl0gE#!zukpSyMg2RaTW_T~)&OPtWa0GZuo^%-{mqwqkR%F518j`yRD*<)_+ yvytXa6pa;*%Z#EDs`b6RlJ*uK>~!n6;a@V#xsPX+Qw(sYg$7Lz{Atqs#6JMqeL%wi literal 0 HcmV?d00001 diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt index 0ca3da4..499f659 100644 --- a/assets-fx/fxconv-metadata.txt +++ b/assets-fx/fxconv-metadata.txt @@ -10,6 +10,21 @@ player_face.png: type: bopti-image name: player_face_img +SignAction.png: + type: bopti-image + name: SignAction_img + +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 font.png: name: fontRPG diff --git a/src/game.c b/src/game.c index 284ce7c..2a6439a 100644 --- a/src/game.c +++ b/src/game.c @@ -6,13 +6,40 @@ #include #include +#include +#include "stdlib.h" + +extern bopti_image_t SignAction_img; void game_logic(Game *game) { + for( int i=0; imap_level->nbextradata; i++ ) + { + if ( (abs((int) game->player.x - (int) game->map_level->extradata[i].x*PXSIZE) < 8*PXSIZE) + && (abs((int) game->player.y - (int) game->map_level->extradata[i].y*PXSIZE) < 8*PXSIZE)) + { + game->player.canDoSomething = true; + game->player.whichAction = i; + return; + } + } + + game->player.canDoSomething = false; + game->player.whichAction = -1; + return; +} +void render_indicator(Game *game) +{ + if (game->player.canDoSomething==false) + return; + + dimage(5, 5, &SignAction_img); + //dprint( 20, 20, C_RED, "X= %d - Y= %d / Xp= %d - Yp= %d", game->player.x, game->player.y, game->map_level->extradata[0].x*PXSIZE, game->map_level->extradata[0].y*PXSIZE ); + //dprint( 20, 40, C_RED, "ABS1= %d - ABS2= %d", abs((int) game->player.x - (int) game->map_level->extradata[0].x*PXSIZE), abs((int) game->player.y - (int) game->map_level->extradata[0].y*PXSIZE) ); } void draw(Game *game) { @@ -20,6 +47,7 @@ void draw(Game *game) { render_map_by_layer(game, BACKGROUND); player_draw(game); render_map_by_layer(game, FOREGROUND); + render_indicator( game ); } /* Key management */ @@ -51,6 +79,9 @@ void get_inputs(Game *game) { if(keydown(KEY_F2)) { game->debug_player = !game->debug_player; } + if(keydown(KEY_F3)) { + game->debug_extra = !game->debug_extra; + } #endif diff --git a/src/game.h b/src/game.h index af724b5..76c6a38 100644 --- a/src/game.h +++ b/src/game.h @@ -1,6 +1,7 @@ #ifndef GAME_H #define GAME_H + #include #include @@ -24,12 +25,16 @@ typedef enum { /* Struct that define player parameters */ typedef struct { - int x, y; /* The position of the player int the current map */ - unsigned int px, py; /* The position of the player on screen */ - int wx, wy; /* position of the player in the world */ - unsigned short int life; /* How many lives the player still has between 0 + int16_t x, y; /* The position of the player int the current map */ + uint16_t px, py; /* The position of the player on screen */ + int16_t wx, wy; /* position of the player in the world */ + int16_t life; /* How many lives the player still has between 0 * and 100. */ - char speed; /* The speed of the movement of the player. */ + int8_t speed; /* The speed of the movement of the player. */ + + bool canDoSomething; /* set to true if a action can be done in the current position of the map */ + int32_t whichAction; /* indicates which data are relevant to the current action in the extradata layer of the map */ + bool isDoingAction; } Player; @@ -103,6 +108,10 @@ void game_logic(Game *game); /* Draws everything on screen. */ void draw(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); + /* Handle key presses. */ void get_inputs(Game *game); diff --git a/src/main.c b/src/main.c index 07d98d8..f7893c9 100644 --- a/src/main.c +++ b/src/main.c @@ -32,11 +32,11 @@ extern Map *worldRPG[]; /* Game data (defined in "game.h")*/ Game game = { NULL, - {12*PXSIZE, 36*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED}, + {12*PXSIZE, 36*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED, false, 0, false}, false, false, false, 0 /* debug variables*/ - , false, false, true + , false, false, false }; /* screen capture management code */ @@ -142,7 +142,6 @@ int main(void) { if (game.debug_extra) { dfont( NULL ); - //drect( 155, 80, 390, 150, C_WHITE ); for (int i=0; inbextradata; i++ ) dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %s", game.map_level->extradata[i].x, game.map_level->extradata[i].y, game.map_level->extradata[i].dialog ); } diff --git a/src/player.c b/src/player.c index 3cb1efc..777a6b4 100644 --- a/src/player.c +++ b/src/player.c @@ -1,4 +1,5 @@ #include "player.h" +#include "dialogs.h" #include "map.h" #include "config.h" #include @@ -25,6 +26,9 @@ const char damage_taken_walkable[WALKABLE_TILE_MAX] = { }; 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_draw(Game *game) { @@ -77,8 +81,30 @@ void player_move(Game *game, Direction direction) { player->wy = game->map_level->ymin * PXSIZE + player->y; } + void player_action(Game *game) { - /* TODO */ + if( game->player.isDoingAction ) return; /* alreday doing something */ + + if( game->player.canDoSomething ) /* we can do something */ + { + game->player.isDoingAction = true; + + char *text = game->map_level->extradata[game->player.whichAction].dialog; + bopti_image_t *face; + + if (strcmp("PST", game->map_level->extradata[game->player.whichAction].type)==0) + face = &INFO_Icon_img; + else if (strcmp("NPC", game->map_level->extradata[game->player.whichAction].type)==0) + face = &NPC_Icon_img; + else if (strcmp("SGN", game->map_level->extradata[game->player.whichAction].type)==0) + face = &NPC_Icon_img; + else face = &demo_player_img; + + showtext_dialog( game, + face, + text, + true, true ); + } } bool player_collision(Game *game, Direction direction, From a5328d0be6d342568e7084b1bb059d3e0b455632 Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Wed, 16 Aug 2023 19:36:31 +0200 Subject: [PATCH 08/10] Added support for Player actions and interaction with the items within the map --- assets/level0.tmx | 2 +- src/player.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/level0.tmx b/assets/level0.tmx index 9e150be..d01c166 100644 --- a/assets/level0.tmx +++ b/assets/level0.tmx @@ -12,7 +12,7 @@ 301,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,301,2,386,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,49,9,10,134,135,52,393,394,395,396,337,338,2, 325,149,150,151,152,2,2,327,374,375,327,2,2,185,374,375,325,387,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,73,33,34,74,219,76,2,2,2,2,361,362,2, 257,2,2,385,2,2,385,2,265,266,2,2,208,209,352,353,257,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,26,27,27,97,98,99,98,99,100,26,26,27,28,131,2,2, -281,176,2,2,2,2,2,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,49,2,2,2,121,59,60,60,61,124,2,2,2,52,132,2,2, +281,176,2,2,2,2,176,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,49,2,2,2,121,59,60,60,61,124,2,2,2,52,132,2,2, 2,2,2,2,2,385,2,2,265,266,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,73,2,2,2,145,83,84,84,85,148,2,2,2,76,132,2,2, 2,2,2,2,326,2,385,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,190,2,2,2,2,2,2,385,2,49,404,405,2,169,107,108,108,109,172,2,402,403,76,132,2,2, 2,2,2,2,2,2,2,2,289,290,2,258,259,260,238,239,260,260,261,262,262,263,264,2,2,2,2,2,2,2,385,49,134,135,2,2,2,2,2,2,2,2,134,135,52,132,297,298, diff --git a/src/player.c b/src/player.c index 777a6b4..db0c28d 100644 --- a/src/player.c +++ b/src/player.c @@ -97,13 +97,15 @@ void player_action(Game *game) { else if (strcmp("NPC", game->map_level->extradata[game->player.whichAction].type)==0) face = &NPC_Icon_img; else if (strcmp("SGN", game->map_level->extradata[game->player.whichAction].type)==0) - face = &NPC_Icon_img; + face = &SGN_Icon_img; else face = &demo_player_img; showtext_dialog( game, face, text, true, true ); + + game->player.isDoingAction = false; } } From 9d8464e0d5a523f3b1cb0c7d29d77c739307e0e3 Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Wed, 16 Aug 2023 23:12:16 +0200 Subject: [PATCH 09/10] added items on all maps - one bug to be corrected with coodinates --- CMakeLists.txt | 4 ++-- TODO.txt | 8 ++++---- assets/level0.tmx | 16 ++++++++++++++-- assets/level1.tmx | 42 +++++++++++++++++++++++++----------------- assets/level2.tmx | 22 +++++++++++++++++++++- assets/level3.tmx | 36 ++++++++++++++++++++++++++++++++++-- src/game.c | 11 ++++++++--- src/game.h | 27 ++++++++++++++++++--------- src/player.c | 13 +++++++------ 9 files changed, 133 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a7f080..d8c8bba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,9 @@ find_package(Gint 2.9 REQUIRED) find_package(LibProf 2.4 REQUIRED) #set the color mode either to 1b or 2b -set(COLORMODE_fx 2b) +set(COLORMODE_fx 1b) #set the color mode either to 1b, 2b or EGA64 -set(COLORMODE_cg 2b) +set(COLORMODE_cg EGA64) fxconv_declare_converters(assets/converters.py) diff --git a/TODO.txt b/TODO.txt index e9f2bcf..46d445e 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,6 +1,6 @@ -- Jeu de tuile 1bit pour CG pour avoir la version 1bit vérifiable en fonctionnement dans l'émulateur de Heath -- corriger les tuiles 1bit pour les rivières (tiles 1 2 3 et 4) avec niveaux de diphering pour tiles 1 et 3 (gris 33% et 66%) -- ajouter face pour dialogue pour PNJ -- ajouter indicateur visuel pour action joueur quand on est proche d'un PNJ ou d'un panneau +[OK] - Jeu de tuile 1bit pour CG pour avoir la version 1bit vérifiable en fonctionnement dans l'émulateur de Heath +[OK] - corriger les tuiles 1bit pour les rivières (tiles 1 2 3 et 4) avec niveaux de diphering pour tiles 1 et 3 (gris 33% et 66%) +[OK] - ajouter face pour dialogue pour PNJ +[OK] - ajouter indicateur visuel pour action joueur quand on est proche d'un PNJ ou d'un panneau - faire des fonts lisibles avec le set `print` disponible intégralement \ No newline at end of file diff --git a/assets/level0.tmx b/assets/level0.tmx index d01c166..e6fd8eb 100644 --- a/assets/level0.tmx +++ b/assets/level0.tmx @@ -1,5 +1,5 @@ - + @@ -90,7 +90,19 @@ - + + + + + + + + + + + + + diff --git a/assets/level1.tmx b/assets/level1.tmx index 300ef70..20e3824 100644 --- a/assets/level1.tmx +++ b/assets/level1.tmx @@ -1,5 +1,5 @@ - + @@ -16,16 +16,16 @@ 2,293,1,1,1,1,1,1,1,1,1,1,1,1,272,2,2,2,2,270,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,267,268,269,1,1,1,1,1,1,1,1,1,1, 2,2,269,1,1,1,1,1,1,319,319,269,1,1,1,316,271,316,271,317,1,1,1,1,319,319,319,268,268,319,319,319,268,319,320,2,2,318,319,320,268,269,1,1,1,1,1,1, 2,2,2,269,1,1,1,1,320,2,2,2,269,1,1,1,1,1,1,1,1,1,267,2,2,2,2,2,2,2,2,2,2,2,2,2,2,219,2,2,2,318,319,320,269,1,1,1, -2,2,2,2,319,268,319,320,2,2,2,2,318,319,269,1,1,1,1,1,1,267,2,2,2,2,313,265,242,266,241,219,314,313,242,241,289,314,219,2,2,2,2,2,2,269,1,1, -27,26,27,26,27,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,290,313,266,297,298,299,300,2,2,318,319,320, +2,2,2,2,319,268,319,320,2,2,2,2,318,319,269,1,1,1,1,1,1,267,2,2,2,2,313,265,242,266,241,219,314,313,242,241,2,2,219,2,2,2,2,2,2,269,1,1, +27,26,27,26,27,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,2,2,2,297,298,299,300,2,2,318,319,320, 2,50,51,51,99,100,132,2,2,2,2,2,2,2,2,2,2,2,2,314,265,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,74,75,76,16,17,133,2,2,2,2,2,2,2,2,2,2,2,241,219,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 98,98,99,100,40,41,290,314,297,298,299,300,2,2,2,2,2,219,219,289,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2, -121,122,123,124,64,65,265,289,313,289,241,265,219,2,2,2,2,290,314,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -145,146,147,148,132,2,2,2,2,2,2,314,314,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2, +121,122,123,124,64,65,265,289,313,289,241,265,219,2,2,2,2,290,314,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,402,403,2,374,375,2,404,405,2,2,2,2,2,2, +145,146,147,148,132,2,2,2,2,2,2,314,314,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 169,170,171,172,133,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,345,346,347,348,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,369,370,371,372,297,298,299,300,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,369,370,371,372,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,393,394,395,396,2,2,2,2,2,297,298,299,300, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2 @@ -46,19 +46,19 @@ 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,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0, 275,276,0,0,0,0,0,0,201,202,203,204,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,0,273,274,275,276,201,202,203,204,0, 0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,225,226,227,228,0,201,202,203,204,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,249,250,251,252,0,0,0,0,0,0,0,0,0,249,250,251,252,0,225,226,227,228,0,0,0,0,0,201,202,203,204,0,0,0,0,249,250,251,252,0, -0,0,0,0,0,0,0,0,273,274,275,276,0,201,202,203,204,0,0,0,0,273,274,275,276,0,249,250,251,252,201,202,203,204,0,225,226,227,228,0,0,0,0,273,274,275,276,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,273,274,275,276,225,226,227,228,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,249,250,251,252,0,0,0,0,201,202,203,204,0,0,0,0,0,249,250,251,252,0,273,274,275,276,201,202,203,204,0,0,0,0,0, -0,0,0,0,0,0,0,201,202,203,204,0,0,273,274,275,276,0,0,0,0,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0,0,0,225,226,227,228,0,201,202,203,204, -0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,201,202,203,204,201,202,203,204,0,0,0,0,0,249,250,251,252,0,225,226,227,228, -204,0,0,201,202,203,204,249,250,251,252,201,202,203,204,0,0,0,0,0,0,273,274,275,276,0,225,226,227,228,225,226,227,228,0,0,0,0,0,273,274,275,276,0,249,250,251,252, +0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,249,250,251,252,0,225,226,227,228,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,273,274,275,276,0,201,202,203,204,0,0,0,0,273,274,275,276,0,249,250,251,252,201,202,203,204,354,355,0,0,0,0,356,357,0,273,274,275,276,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,273,274,275,276,225,226,227,228,378,379,0,350,351,0,380,381,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,201,202,203,204,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,201,202,203,204,0,0,273,274,275,276,0,0,0,0,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0,0,0,0,0,0,0,0,201,202,203,204, +0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,201,202,203,204,201,202,203,204,0,0,0,0,0,0,0,0,0,0,225,226,227,228, +204,0,0,201,202,203,204,249,250,251,252,201,202,203,204,0,0,0,0,0,0,273,274,275,276,0,225,226,227,228,225,226,227,228,0,0,0,0,0,0,0,0,0,0,249,250,251,252, 228,0,0,225,226,227,228,273,274,275,276,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,249,250,251,252,249,250,251,252,0,0,0,0,0,0,0,0,0,0,273,274,275,276, 252,0,0,249,250,251,252,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,0,0,273,274,275,276,273,274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 276,0,0,273,274,275,276,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -77,13 +77,21 @@ 0,0,0,0,410,410,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,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,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0, -410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -410,410,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0, +410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,0,410,410,0,410,410,0,0,0,0,0,0, +410,410,410,410,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,0,0,0, 410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,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,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,410,410,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,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,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,410,410,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,410,410,410,410,0,0,0,0,0,0,410,410,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,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + + + + + diff --git a/assets/level2.tmx b/assets/level2.tmx index 35d297c..6d1fb52 100644 --- a/assets/level2.tmx +++ b/assets/level2.tmx @@ -1,5 +1,5 @@ - + @@ -86,4 +86,24 @@ 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,0,0,0,0,0,0,0 + + + + + + + + + + + + + + + + + + + + diff --git a/assets/level3.tmx b/assets/level3.tmx index ea2adeb..d756a70 100644 --- a/assets/level3.tmx +++ b/assets/level3.tmx @@ -1,5 +1,5 @@ - + @@ -58,7 +58,7 @@ 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,0,0,0,0,0,0,0 - + 0,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,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,0,0,0,0,0,410,410,0,0,0,0,410,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410, @@ -86,4 +86,36 @@ 0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,0,0,0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/game.c b/src/game.c index 2a6439a..8052712 100644 --- a/src/game.c +++ b/src/game.c @@ -15,17 +15,21 @@ extern bopti_image_t SignAction_img; void game_logic(Game *game) { + /* we check if interactions are possible close to the player */ for( int i=0; imap_level->nbextradata; i++ ) { + /* simple distance check along X and Y axis */ if ( (abs((int) game->player.x - (int) game->map_level->extradata[i].x*PXSIZE) < 8*PXSIZE) && (abs((int) game->player.y - (int) game->map_level->extradata[i].y*PXSIZE) < 8*PXSIZE)) { + /* the player can do something */ game->player.canDoSomething = true; + /* we mark the action for futur treatment in player_action() */ game->player.whichAction = i; return; } } - + /* else nothing to be done here */ game->player.canDoSomething = false; game->player.whichAction = -1; return; @@ -34,14 +38,15 @@ void game_logic(Game *game) { void render_indicator(Game *game) { + /* nothing to do for the player so we quit */ if (game->player.canDoSomething==false) return; + /* else we draw a small indicator on the screen */ dimage(5, 5, &SignAction_img); - //dprint( 20, 20, C_RED, "X= %d - Y= %d / Xp= %d - Yp= %d", game->player.x, game->player.y, game->map_level->extradata[0].x*PXSIZE, game->map_level->extradata[0].y*PXSIZE ); - //dprint( 20, 40, C_RED, "ABS1= %d - ABS2= %d", abs((int) game->player.x - (int) game->map_level->extradata[0].x*PXSIZE), abs((int) game->player.y - (int) game->map_level->extradata[0].y*PXSIZE) ); } + void draw(Game *game) { /* Draw everything. */ render_map_by_layer(game, BACKGROUND); diff --git a/src/game.h b/src/game.h index 76c6a38..d6237e6 100644 --- a/src/game.h +++ b/src/game.h @@ -28,22 +28,31 @@ typedef struct { int16_t x, y; /* The position of the player int the current map */ uint16_t px, py; /* The position of the player on screen */ int16_t wx, wy; /* position of the player in the world */ - int16_t life; /* How many lives the player still has between 0 - * and 100. */ + int8_t life; /* How many lives the player still has between 0 and 100. */ int8_t speed; /* The speed of the movement of the player. */ - bool canDoSomething; /* set to true if a action can be done in the current position of the map */ - int32_t whichAction; /* indicates which data are relevant to the current action in the extradata layer of the map */ - bool isDoingAction; + + /* set to true if a action can be done in the current position of the map */ + bool canDoSomething; + /* indicates which data are relevant to the current action in the */ + /* extradata layer of the map */ + int32_t whichAction; + /* the player is doing something */ + bool isDoingAction; } Player; typedef struct { + /* position of the item */ uint16_t x; uint16_t y; + /* its name */ char *name; + /* its class (NPC, SGN, INFO, ... )*/ char *type; + /* data to be shown in the dialog*/ char *dialog; + /* ... this can be extended as per needs ... */ } ExtraData; @@ -66,16 +75,16 @@ typedef struct { /* contain the properties of the tiles */ /* this is given by the layer Walkable of the map in Tiled */ - uint8_t *walkable; + /* structure that contains all the items on the map to interract with */ + /* each portion of the map has its own list to avoid scrutinizing too much */ + /* data when lloking for proximity of items */ uint32_t nbextradata; ExtraData *extradata; - /* list of all the tiles */ + /* list of all the tiles to draw the background and the foreground layers */ uint16_t *layers[]; - - } Map; diff --git a/src/player.c b/src/player.c index db0c28d..ed7067f 100644 --- a/src/player.c +++ b/src/player.c @@ -87,12 +87,14 @@ void player_action(Game *game) { if( game->player.canDoSomething ) /* we can do something */ { + /* we indicate that the player is occupied */ game->player.isDoingAction = true; + /* we collect the information */ char *text = game->map_level->extradata[game->player.whichAction].dialog; + /* we use the correct image as per the class of the item */ bopti_image_t *face; - - if (strcmp("PST", game->map_level->extradata[game->player.whichAction].type)==0) + if (strcmp("INFO", game->map_level->extradata[game->player.whichAction].type)==0) face = &INFO_Icon_img; else if (strcmp("NPC", game->map_level->extradata[game->player.whichAction].type)==0) face = &NPC_Icon_img; @@ -100,11 +102,10 @@ void player_action(Game *game) { face = &SGN_Icon_img; else face = &demo_player_img; - showtext_dialog( game, - face, - text, - true, true ); + /* we treat the action - i.e. we show a dialog */ + showtext_dialog( game, face, text, true, true ); + /* when done we release the occupied status of the player */ game->player.isDoingAction = false; } } From ad525b869338da437b8ae3bcc449f31a336326ff Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Thu, 17 Aug 2023 07:11:52 +0200 Subject: [PATCH 10/10] Corrected bug regarding interactions with items in maps - used local coordinates instead of world coordinates :( --- src/game.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/game.c b/src/game.c index 8052712..e8e3c98 100644 --- a/src/game.c +++ b/src/game.c @@ -13,14 +13,22 @@ extern bopti_image_t SignAction_img; +#define MAX_INTERACTION_DISTANCE 16 + + void game_logic(Game *game) { /* we check if interactions are possible close to the player */ for( int i=0; imap_level->nbextradata; i++ ) { /* simple distance check along X and Y axis */ - if ( (abs((int) game->player.x - (int) game->map_level->extradata[i].x*PXSIZE) < 8*PXSIZE) - && (abs((int) game->player.y - (int) game->map_level->extradata[i].y*PXSIZE) < 8*PXSIZE)) + /* Be careful to use world coordinates, not local (i.e.map) ones */ + 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) ) { /* the player can do something */ game->player.canDoSomething = true;