Merge dev into new_converter

This commit is contained in:
mibi88 2024-07-30 18:19:49 +02:00
parent bc8382ac65
commit 2202ec6d38
77 changed files with 1003 additions and 811 deletions

12
.clang-format Normal file
View file

@ -0,0 +1,12 @@
BasedOnStyle: LLVM
IndentWidth: 4
PointerAlignment: Right
SpaceBeforeAssignmentOperators: true
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpaceBeforeParens: Never
IndentCaseBlocks: true
IncludeBlocks: Regroup
AllowShortBlocksOnASingleLine: Empty
ColumnLimit: 80

View file

@ -4,6 +4,16 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
project(MyAddin) project(MyAddin)
#set the color mode either to 1b or 2b
set(COLORMODE_fx 1b)
#set the color mode either to 1b, 2b or EGA64
set(COLORMODE_cg EGA64)
if(NOT "${COLORMODE_cg}" STREQUAL EGA64)
set(FXSDK_PLATFORM_LONG fx9860G_G3A)
set(FXSDK_PLATFORM fx)
endif()
include(GenerateG1A) include(GenerateG1A)
include(GenerateG3A) include(GenerateG3A)
@ -12,11 +22,6 @@ find_package(Gint 2.11 REQUIRED)
# Gint 2.11 is required, because we're using the new macros like GINT_RENDER_RGB # Gint 2.11 is required, because we're using the new macros like GINT_RENDER_RGB
find_package(LibProf 2.4 REQUIRED) 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 EGA64)
fxconv_declare_converters(assets/converters.py) fxconv_declare_converters(assets/converters.py)
set(SOURCES set(SOURCES
@ -38,8 +43,12 @@ set(ASSETS
) )
set(ASSETS_cg set(ASSETS_cg
assets-cg/demo_player.png assets-cg/player_male.png
assets-cg/player_female.png
assets-cg/npc/char/npc_male.png assets-cg/npc/char/npc_male.png
assets-cg/npc/char/npc_female.png
assets-cg/npc/char/npc_milkman.png
assets-cg/npc/char/npc_police.png
assets-cg/SignAction.png assets-cg/SignAction.png
assets-cg/npc/face/npc_male.png assets-cg/npc/face/npc_male.png
assets-cg/npc/face/npc_female.png assets-cg/npc/face/npc_female.png
@ -51,28 +60,15 @@ set(ASSETS_cg
assets-cg/font.png assets-cg/font.png
) )
set(ASSETS_cg_1b
assets-cg/1b/tileset/tileset1b_CG.png
)
set(ASSETS_cg_2b
assets-cg/2b/tileset/tileset2b_CG.png
)
set(ASSETS_cg_EGA64 set(ASSETS_cg_EGA64
assets-cg/ega64/tileset/tilesetEGA64_CG.png assets-cg/ega64/tileset/tilesetEGA64_CG.png
) )
set(ASSETS_fx set(ASSETS_fx
assets-fx/demo_player.png assets-fx/player_male.png
assets-fx/npc/char/npc_male.png assets-fx/player_female.png
assets-fx/SignAction.png assets-fx/SignAction.png
assets-fx/npc/face/npc_male.png
assets-fx/npc/face/npc_female.png
assets-fx/npc/face/npc_milkman.png
assets-fx/npc/face/npc_police.png
assets-fx/SGN_Icon.png assets-fx/SGN_Icon.png
assets-fx/INFO_Icon.png
assets-fx/player_face.png assets-fx/player_face.png
assets-fx/font.png assets-fx/font.png
# ... # ...
@ -80,11 +76,29 @@ set(ASSETS_fx
set(ASSETS_fx_1b set(ASSETS_fx_1b
assets-fx/1b/tileset/tileset1b.png assets-fx/1b/tileset/tileset1b.png
assets-fx/1b/npc/char/npc_male.png
assets-fx/1b/npc/char/npc_female.png
assets-fx/1b/npc/char/npc_milkman.png
assets-fx/1b/npc/char/npc_police.png
assets-fx/1b/npc/face/npc_male.png
assets-fx/1b/npc/face/npc_female.png
assets-fx/1b/npc/face/npc_milkman.png
assets-fx/1b/npc/face/npc_police.png
assets-fx/1b/INFO_Icon.png
# ... # ...
) )
set(ASSETS_fx_2b set(ASSETS_fx_2b
assets-fx/2b/tileset/tileset2b.png assets-fx/2b/tileset/tileset2b.png
assets-fx/2b/npc/char/npc_male.png
assets-fx/2b/npc/char/npc_female.png
assets-fx/2b/npc/char/npc_milkman.png
assets-fx/2b/npc/char/npc_police.png
assets-fx/2b/npc/face/npc_male.png
assets-fx/2b/npc/face/npc_female.png
assets-fx/2b/npc/face/npc_milkman.png
assets-fx/2b/npc/face/npc_police.png
assets-fx/1b/INFO_Icon.png
# ... # ...
) )
@ -126,26 +140,18 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
# cg colormode # cg colormode
if("${COLORMODE_cg}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR1BIT)
endif()
if("${COLORMODE_cg}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR2BIT)
endif()
if("${COLORMODE_cg}" STREQUAL EGA64) if("${COLORMODE_cg}" STREQUAL EGA64)
target_compile_options(myaddin PRIVATE -Wall -Wextra -O0 -g -DCOLOREGA) target_compile_options(myaddin PRIVATE -Wall -Wextra -O0 -g -DCOLOREGA)
endif() endif()
if("${COLORMODE_cg}" STREQUAL 1b) if("${COLORMODE_cg}" STREQUAL 1b)
generate_g3a(TARGET myaddin OUTPUT "RPG_1b.g3a" generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a"
NAME "RPG PC 1b" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png) NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
endif() endif()
if("${COLORMODE_cg}" STREQUAL 2b) if("${COLORMODE_cg}" STREQUAL 2b)
generate_g3a(TARGET myaddin OUTPUT "RPG_2b.g3a" generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a"
NAME "RPG PC 2b" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png) NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
endif() endif()
if("${COLORMODE_cg}" STREQUAL EGA64) if("${COLORMODE_cg}" STREQUAL EGA64)

View file

@ -2,32 +2,13 @@
(Mibi88) Fcalva, SlyVTT: What do you think of this? (Mibi88) Fcalva, SlyVTT: What do you think of this?
Wrap the code on 80 columns. Align the wrapped code with the last parantheses,
etc.
Use curly braces with if, else, while and for statements if they can't hold on a
single line.
Put the curly braces after if, else, while or for statements and declarations of
procedures on the same line.
No spaces around parantheses, one space after a comma.
Variables names in sneak_case. Variables names in sneak_case.
(Mibi88) SlyVTT, Fcalva, should be use a doc generation thing or do we describe Name your procedures as following: `filename_whatitdoes`.
the procedures as I did so far?
Document your procedures as following: The procedures are documented using sphinx.
```C We're using `clang-formatter` to keep the code readable. Please run it before
/* procedure_name() committing your code as following: `clang-format -i *` in the `src` folder.
*
* Describe what this procedure does.
* arg1: Describe this argument. If the text is too long, wrap it to the
* next line like this.
* long_name: Describe this argument, and so on.
*/
```
Have I forgotten something? Have I forgotten something?

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -1,11 +1,7 @@
*.png: *.png:
custom-type: custom-image custom-type: bopti-image
name_regex: (.*)\.png \1_img name_regex: (.*)\.png \1_img
profile: p8 profile: p8
scale: 2
demo_PNG.png:
scale: 1
font.png: font.png:
name: fontRPG name: fontRPG

View file

@ -1,3 +1,15 @@
npc_male.png: npc_male.png:
type: bopti-image type: bopti-image
name: demo_PNJ_img name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 B

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 1,000 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 246 B

BIN
assets-cg/player_female.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

BIN
assets-cg/player_male.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

BIN
assets-fx/1b/INFO_Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

View file

@ -0,0 +1,3 @@
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,3 @@
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

View file

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: npc_male
npc_female.png:
type: bopti-image
name: npc_female
npc_milkman.png:
type: bopti-image
name: npc_milkman
npc_police.png:
type: bopti-image
name: npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

View file

Before

Width:  |  Height:  |  Size: 306 B

After

Width:  |  Height:  |  Size: 306 B

View file

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 326 B

View file

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

View file

@ -1,6 +1,9 @@
demo_player.png: player_male.png:
type: bopti-image type: bopti-image
name: demo_player_img name: player_male_img
player_female.png:
type: bopti-image
name: player_female_img
player_face.png: player_face.png:
type: bopti-image type: bopti-image
@ -9,10 +12,6 @@ player_face.png:
SignAction.png: SignAction.png:
type: bopti-image type: bopti-image
name: SignAction_img name: SignAction_img
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img
SGN_Icon.png: SGN_Icon.png:
type: bopti-image type: bopti-image

View file

@ -1,3 +0,0 @@
npc_male.png:
type: bopti-image
name: demo_PNJ_img

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

BIN
assets-fx/player_female.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View file

Before

Width:  |  Height:  |  Size: 107 B

After

Width:  |  Height:  |  Size: 107 B

37
assets/DialogsLvl4.json Normal file
View file

@ -0,0 +1,37 @@
{
"dialogs": [
{
"ID": 0,
"dialog": "Pas sur que tu trouves grand chose ici, je suis le seul ici depuis cinquante ans.",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
},
{
"ID": 1,
"dialog": "L'eglise de Champdubouc",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
},
{
"ID": 2,
"dialog": "Passe moi ton fric !",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
}
]
}

View file

@ -27,6 +27,13 @@
"width": 384, "width": 384,
"x": 384, "x": 384,
"y": 192 "y": 192
},
{
"fileName": "level4.tmx",
"height": 192,
"width": 384,
"x": 384,
"y": 384
} }
], ],
"onlyShowAdjacentMaps": false, "onlyShowAdjacentMaps": false,

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="6"> <map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="6">
<properties> <properties>
<property name="dialogFile" type="file" value="DialogsLvl3.json"/> <property name="dialogFile" type="file" value="DialogsLvl3.json"/>
</properties> </properties>
@ -30,7 +30,7 @@
289,290,265,266,290,2,2,2,2,2,2,2,2,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,2,2,2,2,2,2,2,2,2,2,386,2,2,45,46,47,48,2,2, 289,290,265,266,290,2,2,2,2,2,2,2,2,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,2,2,2,2,2,2,2,2,2,2,386,2,2,45,46,47,48,2,2,
2,2,2,2,2,2,2,2,2,386,2,2,2,265,266,2,2,2,2,2,2,2,2,2,265,266,2,2,2,2,345,346,347,348,2,339,340,2,2,2,2,2,69,70,71,72,2,2, 2,2,2,2,2,2,2,2,2,386,2,2,2,265,266,2,2,2,2,2,2,2,2,2,265,266,2,2,2,2,345,346,347,348,2,339,340,2,2,2,2,2,69,70,71,72,2,2,
2,297,298,299,300,2,2,339,340,2,2,2,2,289,290,266,265,266,266,265,386,265,266,266,289,290,2,160,161,2,369,370,371,372,2,363,364,2,2,2,2,2,2,2,2,2,2,2, 2,297,298,299,300,2,2,339,340,2,2,2,2,289,290,266,265,266,266,265,386,265,266,266,289,290,2,160,161,2,369,370,371,372,2,363,364,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,386,2,2,363,364,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,393,394,395,396,2,2,2,2,2,2,2,387,2,2,2,386,2,2 2,2,2,2,386,2,2,363,364,2,2,2,2,2,2,2,2,2,2,2,265,265,2,2,2,2,2,2,385,2,393,394,395,396,2,2,2,2,2,2,2,387,2,2,2,386,2,2
</data> </data>
</layer> </layer>
<layer id="2" name="Foreground" width="48" height="24"> <layer id="2" name="Foreground" width="48" height="24">

124
assets/level4.tmx Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="6" nextobjectid="9">
<properties>
<property name="dialogFile" type="file" value="DialogsLvl4.json"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
<layer id="1" name="Background" width="48" height="24">
<data encoding="csv">
385,386,6,6,385,386,385,6,6,6,6,6,6,6,6,6,385,386,385,265,266,385,386,385,386,385,121,122,123,122,123,122,124,6,6,6,6,6,6,6,6,386,6,6,6,6,6,6,
385,386,385,386,385,386,385,386,6,6,218,219,385,386,385,386,385,386,385,289,241,385,386,385,386,385,145,146,147,147,146,147,148,385,386,385,385,386,6,6,6,217,218,219,385,6,6,386,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,313,314,25,26,27,26,27,145,146,146,146,147,146,148,26,27,28,385,386,385,386,385,217,218,219,385,386,385,386,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,387,265,266,49,50,51,176,2,169,170,170,170,171,170,172,2,176,52,385,386,385,386,385,217,218,219,363,364,385,386,
385,386,385,386,176,386,385,386,385,386,385,386,385,386,385,386,385,386,385,289,290,97,98,19,50,50,121,122,59,60,61,123,124,50,50,76,385,149,150,151,152,153,154,386,176,177,178,386,
385,385,386,218,385,386,386,219,218,219,385,176,385,386,217,218,219,386,385,313,314,121,122,73,50,50,145,146,83,84,85,147,148,50,50,52,385,386,385,386,385,386,385,386,385,386,385,386,
385,386,25,26,26,26,26,26,27,28,385,386,385,386,217,218,219,386,385,265,241,14,15,49,50,177,169,170,107,108,109,171,172,50,51,52,385,387,149,150,151,152,153,154,385,217,218,219,
385,386,73,74,74,74,74,74,75,76,385,386,385,386,25,26,27,28,385,289,290,38,39,73,74,75,50,2,2,2,2,176,2,74,177,76,385,386,385,386,385,386,385,386,385,217,218,219,
385,386,97,98,98,98,98,98,99,100,385,386,385,386,73,74,75,76,385,313,314,62,63,97,98,99,98,99,98,99,98,99,98,98,99,100,385,149,150,151,152,153,154,218,219,386,385,386,
385,386,162,163,163,163,163,163,164,165,385,386,385,386,97,98,99,100,385,265,266,2,2,197,198,199,200,197,198,199,200,197,198,199,200,197,385,386,385,386,385,386,217,361,362,386,385,386,
25,26,86,87,88,89,186,187,188,189,27,26,27,26,87,88,187,188,28,241,290,160,161,221,222,223,224,221,222,223,224,221,222,223,224,221,385,386,385,386,385,386,385,386,385,386,385,386,
49,50,110,111,112,113,210,211,212,213,177,50,11,12,111,112,211,212,52,313,314,2,2,245,246,247,248,245,246,247,248,245,246,247,248,245,385,386,385,386,385,386,385,386,385,386,385,386,
73,74,75,74,75,176,234,235,236,237,75,74,35,36,75,74,74,75,76,265,266,265,266,265,266,265,266,241,266,313,314,265,266,265,266,265,241,265,266,313,314,265,266,265,266,265,266,265,
97,98,99,98,99,98,99,98,99,98,99,98,99,98,99,98,98,99,100,289,290,289,313,241,290,289,290,289,290,289,290,289,313,241,290,289,290,289,290,289,290,289,290,313,314,313,290,289,
121,122,14,15,16,17,14,15,16,17,14,15,16,17,122,59,60,61,124,265,266,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
145,146,38,39,40,41,38,39,40,41,38,39,40,41,146,83,84,85,148,289,290,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
169,170,62,63,64,65,62,63,64,65,62,63,64,65,170,107,108,109,172,265,266,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,187,188,87,88,187,188,87,88,187,188,87,88,265,266,266,289,290,241,290,385,386,385,386,385,386,385,386,385,386,385,386,304,305,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,211,212,111,112,211,212,111,112,211,212,111,112,289,290,241,313,314,313,314,176,386,385,386,217,386,385,217,218,219,217,386,328,329,385,386,176,386,217,218,219,386,385,386,385,386,385,
385,386,289,241,265,266,289,290,241,266,289,290,265,266,241,290,385,386,385,385,386,45,46,47,48,217,386,385,217,218,219,217,386,385,386,385,386,385,386,217,218,219,386,385,386,385,386,385,
385,386,313,314,289,290,241,314,289,290,313,241,289,290,313,314,385,386,385,385,386,69,70,71,72,217,386,385,217,218,219,217,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,304,305,386,176,386,385,386,385,386,385,386,385,386,385,386,385,386,385,217,304,305,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,328,329,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,217,328,329,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385
</data>
</layer>
<layer id="2" name="Foreground" width="48" height="24">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,339,340,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,126,127,128,129,130,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,207,0,0,0,0,0,0,0,206,207,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,231,0,0,0,0,0,0,0,230,231,0,0,0,125,126,127,128,129,130,0,0,0,0,
0,0,0,0,0,0,0,214,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,0,0,0,0,0,0,0,254,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,238,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,126,127,128,129,130,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,337,338,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,22,23,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv">
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,410,410,410,410,410,410,410,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,412,0,0,412,412,412,412,412,410,0,0,0,0,0,410,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,412,0,0,410,410,410,410,410,410,0,0,0,0,0,410,410,410,410,412,412,412,412,412,412,412,412,410,410,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,0,0,410,0,0,0,0,410,0,0,0,0,0,410,0,0,410,412,412,412,412,412,412,412,412,410,410,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,410,0,0,0,0,410,0,410,410,410,0,410,0,0,410,412,410,410,410,410,410,410,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,410,410,0,0,0,410,0,410,0,410,0,410,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,412,412,0,0,0,0,0,410,410,410,410,410,0,410,410,410,410,410,410,412,410,410,410,410,410,410,410,412,412,412,412,
412,412,410,0,0,0,0,0,0,410,412,412,412,412,410,410,410,410,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,410,0,0,0,0,0,0,410,412,412,412,412,410,0,0,410,412,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,412,410,410,410,410,410,410,410,410,412,412,412,
412,412,410,0,0,0,410,410,410,410,412,412,412,412,410,410,410,410,412,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,410,410,412,412,412,
410,410,410,0,0,0,410,0,0,410,410,410,410,410,410,410,0,0,410,0,0,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
410,0,410,410,410,410,410,0,0,410,0,0,0,0,410,410,0,0,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,412,412,412,412,412,
410,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,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,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,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,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,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,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,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,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,412,0,0,410,410,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,0,0,410,410,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,410,410,410,410,412,412,412,412,412,412,412,412,410,410,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,412,412,412,412,412,410,410,410,410,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,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,410,410,410,410,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,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,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,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,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,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412
</data>
</layer>
<objectgroup id="4" name="ExtraData">
<object id="3" name="SGN1" type="SGN" x="176.852" y="88.7417">
<properties>
<property name="dialogID" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
</properties>
<point/>
</object>
<object id="6" name="NPC1" type="NPC" x="147.952" y="62.6849">
<properties>
<property name="dialogID" type="int" value="0"/>
<property name="face" value="MAN"/>
<property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="7" name="ENEMY1" type="NPC" x="182.215" y="181.047">
<properties>
<property name="dialogID" type="int" value="2"/>
<property name="face" value="MALE"/>
<property name="hasPath" type="int" value="0"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="0"/>
</properties>
<point/>
</object>
<object id="8" name="CHEMIN_FERMIER" x="147.952" y="63.0743">
<polyline points="0,0 13.6272,31.1478 50.6152,79.4269 13.6272,74.7547 -7.3976,102.009 -15.5739,71.6399 -17.91,116.804 47.8897,112.132 71.6399,87.2138 131.21,112.132 176.374,91.1073 218.424,89.9393 131.599,59.1808 74.3654,64.2423 50.2258,44.775 29.9798,42.4389 3.50413,3.50413"/>
</object>
</objectgroup>
</map>

View file

@ -1,7 +1,6 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
#define USB_FEATURE 0 #define USB_FEATURE 0
#define DEBUGMODE 1 #define DEBUGMODE 1
@ -9,48 +8,45 @@
/* Enable GrayMode on either FX and FX_G3A targets */ /* Enable GrayMode on either FX and FX_G3A targets */
#if GINT_RENDER_MONO && defined(COLOR2BIT) #if GINT_RENDER_MONO && defined(COLOR2BIT)
#define GRAYMODEOK 1 #define GRAYMODEOK 1
#endif #endif
#if GINT_RENDER_RGB #if GINT_RENDER_RGB
/* The tile size */ /* The tile size */
#define T_HEIGHT 16 #define T_HEIGHT 16
#define T_WIDTH 16 #define T_WIDTH 16
/* The size of a pixel */ /* The size of a pixel */
#define PXSIZE 2 #define PXSIZE 2
#define PATH_COLOR C_RED #define PATH_COLOR C_RED
/* The size of the player */ /* The size of the player */
#define P_WIDTH 16 #define P_WIDTH 16
#define P_HEIGHT 16 #define P_HEIGHT 16
#else #else
/* The tile size */ /* The tile size */
#define T_HEIGHT 8 #define T_HEIGHT 8
#define T_WIDTH 8 #define T_WIDTH 8
/* The pixel size */ /* The pixel size */
#define PXSIZE 1 #define PXSIZE 1
#define PATH_COLOR C_BLACK #define PATH_COLOR C_BLACK
/* The player size */ /* The player size */
#define P_WIDTH 8 #define P_WIDTH 8
#define P_HEIGHT 8 #define P_HEIGHT 8
#endif #endif
/* SPEED should NOT be 8 or bigger: it may cause bugs when handling /* SPEED should NOT be 8 or bigger: it may cause bugs when handling
* collisions! */ * collisions! */
#define SPEED (PXSIZE*2) #define SPEED (PXSIZE * 2)
/* The face size (in the dialogs) */ /* The face size (in the dialogs) */
#define F_WIDTH (32*PXSIZE) #define F_WIDTH (32 * PXSIZE)
#define F_HEIGHT (32*PXSIZE) #define F_HEIGHT (32 * PXSIZE)
/* the color of the text to go to the next dialog phase */ /* the color of the text to go to the next dialog phase */
/* it improves readability to have something lighter */ /* it improves readability to have something lighter */
#if GRAYMODEOK || (GINT_RENDER_RGB && !defined(COLOR1BIT)) #if GRAYMODEOK || (GINT_RENDER_RGB && !defined(COLOR1BIT))
#define NEXT_COLOR C_DARK #define NEXT_COLOR C_DARK
#else #else
#define NEXT_COLOR C_BLACK #define NEXT_COLOR C_BLACK
#endif #endif
#endif #endif

View file

@ -1,197 +1,209 @@
#include "dialogs.h" #include "dialogs.h"
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <string.h>
#include "config.h" #include "config.h"
#include "events.h"
#include "game.h" #include "game.h"
#include "npc.h" #include "npc.h"
#include "events.h"
#include <gint/cpu.h>
#include <gint/keyboard.h>
#include <string.h>
#define BOX_HEIGHT (F_HEIGHT/PXSIZE+8) #define BOX_HEIGHT (F_HEIGHT / PXSIZE + 8)
#define CHOICE_BOX_HEIGHT 10 #define CHOICE_BOX_HEIGHT 10
#define CHOICE_BOX_PADDING_TOP 3 #define CHOICE_BOX_PADDING_TOP 3
extern font_t fontRPG; extern font_t fontRPG;
#define FONT_USED fontRPG #define FONT_USED fontRPG
#if GRAYMODEOK #if GRAYMODEOK
#include <gint/gray.h> #include <gint/gray.h>
uint32_t *lightVRAMnext, *darkVRAMnext; uint32_t *lightVRAMnext, *darkVRAMnext;
uint32_t *lightVRAMcurrent, *darkVRAMcurrent; uint32_t *lightVRAMcurrent, *darkVRAMcurrent;
#endif //GRAYMODEOK #endif // GRAYMODEOK
void blit() { void blit() {
dupdate(); dupdate();
#if GRAYMODEOK && !GINT_HW_CG
dgray_getvram( &lightVRAMnext, &darkVRAMnext );
dgray_getscreen( &lightVRAMcurrent, &darkVRAMcurrent );
memcpy( lightVRAMnext, lightVRAMcurrent, 256*sizeof( uint32_t) );
memcpy( darkVRAMnext, darkVRAMcurrent, 256*sizeof( uint32_t) );
#endif
}
#if GRAYMODEOK && !GINT_HW_CG
dgray_getvram(&lightVRAMnext, &darkVRAMnext);
dgray_getscreen(&lightVRAMcurrent, &darkVRAMcurrent);
memcpy(lightVRAMnext, lightVRAMcurrent, 256 * sizeof(uint32_t));
memcpy(darkVRAMnext, darkVRAMcurrent, 256 * sizeof(uint32_t));
#endif
}
int dialogs_text_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) {
text = events_parse_string(&game->handler, text); text = events_parse_string(&game->handler, text);
dfont(&FONT_USED); dfont(&FONT_USED);
unsigned int i, n, y = PXSIZE, l = 0; unsigned int i, n, y = PXSIZE, l = 0;
int line_max_chars, return_int = 0; int line_max_chars, return_int = 0;
unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/ unsigned int max_lines_amount =
(FONT_USED.line_height+PXSIZE); (BOX_HEIGHT - 2) * PXSIZE / (FONT_USED.line_height + PXSIZE);
const char *c; const char *c;
if(start_anim){ if(start_anim) {
/* Run a little fancy animation. */ /* Run a little fancy animation. */
for(i=0;i<=BOX_HEIGHT;i++){ for(i = 0; i <= BOX_HEIGHT; i++) {
/* 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_npcs(game); update_npcs(game);
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);
/* Draw a thick black line on the bottom of the dialog. */ /* Draw a thick black line on the bottom of the dialog. */
drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); drect(0, i * PXSIZE, DWIDTH, (i + 1) * PXSIZE, C_BLACK);
/* Draw the part of the face of the player that can fit correctly in /* Draw the part of the face of the player that can fit correctly in
* the dialog drawn. */ * the dialog drawn. */
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, dsubimage(4 * PXSIZE, 2 * PXSIZE, face, 0, 0, F_WIDTH,
DIMAGE_NONE); (i - 8) * PXSIZE, DIMAGE_NONE);
blit(); blit();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
}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. */
game_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,
dimage(4*PXSIZE, 2*PXSIZE, face); C_BLACK);
dimage(4 * PXSIZE, 2 * PXSIZE, face);
if(update_screen){ if(update_screen) {
blit(); blit();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
/* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid
* drawing on the face. */ * drawing on the face. */
for(i=start_i;i<strlen(text);i++){ for(i = start_i; i < strlen(text); i++) {
if(!l && for_each_screen) for_each_screen(game, i); if(!l && for_each_screen)
for_each_screen(game, i);
/* Get how many chars we can draw on screen with a padding on the left /* Get how many chars we can draw on screen with a padding on the left
* of BOX_HEIGHT px and on the right of 1 px. */ * of BOX_HEIGHT px and on the right of 1 px. */
c = drsize(text+i, &FONT_USED, DWIDTH-(BOX_HEIGHT*PXSIZE+PXSIZE), NULL); c = drsize(text + i, &FONT_USED,
DWIDTH - (BOX_HEIGHT * PXSIZE + PXSIZE), NULL);
/* c is a pointer to the last char that can be drawn. So: */ /* c is a pointer to the last char that can be drawn. So: */
line_max_chars = c-(text+i); line_max_chars = c - (text + i);
/* TODO: Handle lines that are longer than what I can draw and '\n'. */ /* TODO: Handle lines that are longer than what I can draw and '\n'. */
/* Loop from the end to the start for word wrap. */ /* Loop from the end to the start for word wrap. */
if(*c){ if(*c) {
/* If we are not drawing the end of the text. */ /* If we are not drawing the end of the text. */
for(n=line_max_chars; n>0; n--) { for(n = line_max_chars; n > 0; n--) {
/* If we found a space, we can draw this line and do the same /* If we found a space, we can draw this line and do the same
* for the next line. */ * for the next line. */
if(text[i+n] == ' '){ if(text[i + n] == ' ') {
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE,
DTEXT_TOP, text+i, n); /* Draw everything. */ DTEXT_LEFT, DTEXT_TOP, text + i,
n); /* Draw everything. */
/* Increment y by the line height. */ /* Increment y by the line height. */
y += FONT_USED.line_height+PXSIZE; y += FONT_USED.line_height + PXSIZE;
i += n; /* We drew everything to i+n */ i += n; /* We drew everything to i+n */
l++; /* We drew one more line. */ l++; /* We drew one more line. */
break; break;
} }
} }
}else{ } else {
/* If it is the last line of the text. */ /* If it is the last line of the text. */
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT,
DTEXT_TOP, text+i, line_max_chars); DTEXT_TOP, text + i, line_max_chars);
y += FONT_USED.line_height+PXSIZE; y += FONT_USED.line_height + PXSIZE;
i += line_max_chars; i += line_max_chars;
l++; l++;
} }
if(l>=max_lines_amount-1){ if(l >= max_lines_amount - 1) {
/* We drew one entire screen, reset everything to draw the next one. /* We drew one entire screen, reset everything to draw the next one.
*/ */
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
while(game->frame_duration < line_duration) sleep(); blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
/* Ask the user to press SHIFT to continue. */ /* Ask the user to press SHIFT to continue. */
dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite..."); dtext(BOX_HEIGHT * PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite...");
} }
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
if(l>=max_lines_amount-1){ blit();
if(l >= max_lines_amount - 1) {
/* If we drew one entire screen. */ /* If we drew one entire screen. */
/* Wait that the SHIFT key is pressed if we should. */ /* Wait that the SHIFT key is pressed if we should. */
if(wait_continue){ if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){ ~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep(); sleep();
} }
} }
/* Clear the text area. */ /* Clear the text area. */
drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2, drect(BOX_HEIGHT * PXSIZE, 0, DWIDTH, (BOX_HEIGHT - 1) * PXSIZE - 2,
C_WHITE); C_WHITE);
/* Reset y and l. */ /* Reset y and l. */
y = PXSIZE; y = PXSIZE;
l = 0; l = 0;
} } else {
else{
/* Else, wait a bit for the animation. */ /* Else, wait a bit for the animation. */
while(game->frame_duration < line_duration) sleep(); while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
if(l<max_lines_amount-1){ if(l < max_lines_amount - 1) {
/* If we have not filled everthing with text at the end. */ /* If we have not filled everthing with text at the end. */
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
while(game->frame_duration < line_duration) sleep(); blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
/* Ask the user to press SHIFT to continue. */ /* Ask the user to press SHIFT to continue. */
dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite..."); dtext(BOX_HEIGHT * PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite...");
/* Update the screen and wait for SHIFT being pressed, if needed. */ /* Update the screen and wait for SHIFT being pressed, if needed. */
if(update_screen) blit(); if(update_screen)
if(wait_continue){ blit();
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){ ~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep(); sleep();
} }
} }
} }
if(call_before_end) return_int = call_before_end(game, i); if(call_before_end)
if(end_anim){ return_int = call_before_end(game, i);
if(end_anim) {
/* Run another little fancy animation if we should. */ /* Run another little fancy animation if we should. */
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_npcs(game); update_npcs(game);
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,
DIMAGE_NONE); (i - 8) * PXSIZE, DIMAGE_NONE);
dupdate(); dupdate();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
@ -202,11 +214,10 @@ 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. */
dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL,
true, 0, true); 100, true, 0, true);
} }
/* Some variables and pointers used to get some arguments passed in /* Some variables and pointers used to get some arguments passed in
* showtext_dialog_ask in _choice_call_before_end. */ * showtext_dialog_ask in _choice_call_before_end. */
char *_choices, *_text; char *_choices, *_text;
@ -216,31 +227,33 @@ unsigned int _i;
/* Get where I started drawing a dialog page, to be able to redraw the last page /* Get where I started drawing a dialog page, to be able to redraw the last page
* for the end animation in _choice_call_before_end. */ * for the end animation in _choice_call_before_end. */
void _choice_screen_call( [[maybe_unused]] Game *game, unsigned int i) { void _choice_screen_call([[maybe_unused]] Game *game, unsigned int i) {
_i = i; _i = i;
} }
int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) { int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
int i, key; int i, key;
/* Make a little animation because we looove little animations ;) */ /* Make a little animation because we looove little animations ;) */
for(i=0;i<DWIDTH/8+1;i++){ for(i = 0; i < DWIDTH / 8 + 1; i++) {
/* Fill the interaction box with white */ /* Fill the interaction box with white */
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);
/* Draw a thick border on the right of the box. */ /* Draw a thick border on the right of the box. */
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); i * (DWIDTH / 8) + PXSIZE - 1,
(BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
/* Draw a thick border on the bottom of the box. */ /* Draw a thick border on the bottom of the box. */
drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), drect(0, (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, i * (DWIDTH / 8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); (BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
/* Show everyting on screen. */ /* Show everyting on screen. */
blit(); blit();
/* Wait some ms so that the animation isn't too fast. */ /* Wait some ms so that the animation isn't too fast. */
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
/* Calculate the maximal size of a choice. */ /* Calculate the maximal size of a choice. */
const int choice_size = DWIDTH/_choices_amount; const int choice_size = DWIDTH / _choices_amount;
/* arrow_width: The space taken by the arrow that shows the selected item. /* arrow_width: The space taken by the arrow that shows the selected item.
* arrow_height: The height of the arrow used to show which item is choosen. * arrow_height: The height of the arrow used to show which item is choosen.
* Used to calculate the size of the rectangle used to remove * Used to calculate the size of the rectangle used to remove
@ -256,65 +269,70 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
dsize(">", &FONT_USED, &arrow_width, &arrow_height); dsize(">", &FONT_USED, &arrow_width, &arrow_height);
/* Add the character spacing of the font to it. */ /* Add the character spacing of the font to it. */
arrow_width += FONT_USED.char_spacing; arrow_width += FONT_USED.char_spacing;
for(i=0;i<_choices_amount;i++){ for(i = 0; i < _choices_amount; i++) {
dtext(i*choice_size+arrow_width+PXSIZE, dtext(i * choice_size + arrow_width + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
_choices+pos); _choices + pos);
pos += strlen(_choices+pos)+1; pos += strlen(_choices + pos) + 1;
} }
do{ do {
/* Display the diffrent choices. */ /* Display the diffrent choices. */
for(i=0;i<_choices_amount;i++){ for(i = 0; i < _choices_amount; i++) {
if(i == selected) dtext(i*choice_size+PXSIZE, if(i == selected)
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, dtext(i * choice_size + PXSIZE,
C_BLACK, ">"); (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
">");
} }
blit(); blit();
key = getkey_opt( GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key; key = getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA,
NULL)
.key;
/* If the player pressed the left arrow key and has not already selected /* If the player pressed the left arrow key and has not already selected
* the first possible choice. */ * the first possible choice. */
if(key == KEY_LEFT && selected > 0){ if(key == KEY_LEFT && selected > 0) {
/* Remove the old arrow. */ /* Remove the old arrow. */
drect(selected*choice_size+PXSIZE, drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected*choice_size+PXSIZE+arrow_width, selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE); C_WHITE);
/* Move the selection arrow and update the selected item. */ /* Move the selection arrow and update the selected item. */
selected--; selected--;
} }
/* If the player pressed the right arrow key and has not already /* If the player pressed the right arrow key and has not already
* selected the last possible choice. */ * selected the last possible choice. */
else if(key == KEY_RIGHT && selected < _choices_amount-1){ else if(key == KEY_RIGHT && selected < _choices_amount - 1) {
/* Remove the old arrow. */ /* Remove the old arrow. */
drect(selected*choice_size+PXSIZE, drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected*choice_size+PXSIZE+arrow_width, selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE); C_WHITE);
/* Move the selection arrow and update the selected item. */ /* Move the selection arrow and update the selected item. */
selected++; selected++;
} }
/* If the user has not validated his choice by pressing SHIFT, we loop one /* If the user has not validated his choice by pressing SHIFT, we loop
* more time. */ * one more time. */
}while(key != KEY_SHIFT); } while(key != KEY_SHIFT);
/* Make a little animation because we looove little animations ;) */ /* Make a little animation because we looove little animations ;) */
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_npcs(game); update_npcs(game);
game_draw(game); game_draw(game);
dialogs_text_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);
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); i * (DWIDTH / 8) + PXSIZE - 1,
drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, i * (DWIDTH / 8),
(BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
dupdate(); dupdate();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
/* Return the selected item because he'll also be returned by showtext_opt. /* Return the selected item because he'll also be returned by showtext_opt.
@ -338,42 +356,41 @@ int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
end, _choice_screen_call, 100, true, 0, true); end, _choice_screen_call, 100, true, 0, true);
} }
void dialogs_initiate_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 */
char *text = currentDiag->dialog; char *text = currentDiag->dialog;
char *choices = currentDiag->choices ; char *choices = currentDiag->choices;
char *conclusion1 = currentDiag->conclusion1; char *conclusion1 = currentDiag->conclusion1;
int next1 = currentDiag->next1; int next1 = currentDiag->next1;
char *conclusion2 = currentDiag->conclusion2; char *conclusion2 = currentDiag->conclusion2;
int next2 = currentDiag->next2; int next2 = currentDiag->next2;
int nextOther = currentDiag->nextOther; int nextOther = currentDiag->nextOther;
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){ if(isQuestion == 1) {
/* we have to manage a question */ /* we have to manage a question */
int answer = dialogs_ask(game, face, text, true, true, int answer = dialogs_ask(game, face, text, true, true, choices, 2, 0);
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); dialogs_text(game, face, conclusion1, true, true);
if (next1!=-1) dialogs_initiate_sequence(game, face, next1); if(next1 != -1)
}else{ dialogs_initiate_sequence(game, face, next1);
dialogs_text(game, face, conclusion2, true, true); } else {
if (next2!=-1) dialogs_initiate_sequence(game, face, next2); dialogs_text(game, face, conclusion2, true, true);
} if(next2 != -1)
}else{ dialogs_initiate_sequence(game, face, next2);
dialogs_text(game, face, text, true, true); }
if (nextOther!=-1) dialogs_initiate_sequence(game, face, nextOther); } else {
} dialogs_text(game, face, text, true, true);
if(nextOther != -1)
dialogs_initiate_sequence(game, face, nextOther);
}
} }

View file

@ -1,11 +1,12 @@
#ifndef DIALOG_H #ifndef DIALOG_H
#define DIALOG_H #define DIALOG_H
#include <gint/display.h> #include "config.h"
#include <string.h>
#include "game.h" #include "game.h"
#include "map.h" #include "map.h"
#include "config.h"
#include <gint/display.h>
#include <string.h>
/* dialogs_text_opt() /* dialogs_text_opt()
* *
@ -37,8 +38,7 @@
int dialogs_text_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, int line_duration, bool update_screen,
unsigned int start_i, bool wait_continue); unsigned int start_i, bool wait_continue);

View file

@ -1,62 +1,46 @@
#include <stdlib.h>
#include <string.h>
#include "events.h" #include "events.h"
void events_init_handler(EventHandler *handler) { #include <stdlib.h>
handler->vars = 0; #include <string.h>
}
void events_init_handler(EventHandler *handler) { handler->vars = 0; }
int events_bind_variable(EventHandler *handler, int *var, char *name) { int events_bind_variable(EventHandler *handler, int *var, char *name) {
if(handler->vars < MAX_VARIABLES){ if(handler->vars < MAX_VARIABLES) {
handler->variables[handler->vars] = var; handler->variables[handler->vars] = var;
handler->var_names[handler->vars++] = name; handler->var_names[handler->vars++] = name;
}else{ } else {
return 1; return 1;
} }
return 0; return 0;
} }
char op_chars[OP_AMOUNT+1] = " =+-/*%"; char op_chars[OP_AMOUNT + 1] = " =+-/*%";
int _op_null(int a, int b) { int _op_null(int a, int b) { return 0; }
return 0;
}
int _op_set(int a, int b) { int _op_set(int a, int b) { return b; }
return b;
}
int _op_add(int a, int b) { int _op_add(int a, int b) { return a + b; }
return a+b;
}
int _op_sub(int a, int b) { int _op_sub(int a, int b) { return a - b; }
return a-b;
}
int _op_div(int a, int b) { int _op_div(int a, int b) {
if(b == 0) return 0; if(b == 0)
return a/b; return 0;
return a / b;
} }
int _op_mul(int a, int b) { int _op_mul(int a, int b) { return a * b; }
return a*b;
}
int _op_mod(int a, int b) { int _op_mod(int a, int b) {
if(b == 0) return 0; if(b == 0)
return a%b; return 0;
return a % b;
} }
int (*_operations[OP_AMOUNT])(int, int) = { int (*_operations[OP_AMOUNT])(int, int) = {_op_null, _op_set, _op_add, _op_sub,
_op_null, _op_div, _op_mul, _op_mod};
_op_set,
_op_add,
_op_sub,
_op_div,
_op_mul,
_op_mod
};
#define MIN(a, b) a < b ? a : b #define MIN(a, b) a < b ? a : b
@ -73,19 +57,19 @@ char *events_parse_string(EventHandler *handler, char *message) {
char c; char c;
size_t i, n; size_t i, n;
int *var; int *var;
for(i=0;i<strlen(message);i++){ for(i = 0; i < strlen(message); i++) {
c = message[i]; c = message[i];
if(c == '`'){ if(c == '`') {
in_token = !in_token; in_token = !in_token;
if(!in_token){ if(!in_token) {
if(tok_type == T_VAR_EDIT){ if(tok_type == T_VAR_EDIT) {
/* Do the calculation */ /* Do the calculation */
var_name[MIN(name_pos, TOKEN_MAX_SZ)] = '\0'; var_name[MIN(name_pos, TOKEN_MAX_SZ)] = '\0';
num[MIN(num_pos, TOKEN_MAX_SZ)] = '\0'; num[MIN(num_pos, TOKEN_MAX_SZ)] = '\0';
for(n=0;n<handler->vars;n++){ for(n = 0; n < handler->vars; n++) {
if(!strcmp(var_name, handler->var_names[n])){ if(!strcmp(var_name, handler->var_names[n])) {
var = handler->variables[n]; var = handler->variables[n];
if(var_op){ if(var_op) {
*var = _operations[var_op](*var, atoi(num)); *var = _operations[var_op](*var, atoi(num));
} }
break; break;
@ -98,22 +82,25 @@ char *events_parse_string(EventHandler *handler, char *message) {
var_op = OP_NULL; var_op = OP_NULL;
num_pos = 0; num_pos = 0;
} }
}else if(!in_token){ } else if(!in_token) {
if(message_pos < TOKEN_MAX_SZ) _message_buffer[message_pos++] = c; if(message_pos < TOKEN_MAX_SZ)
_message_buffer[message_pos++] = c;
} }
if(in_token && c != ' '){ if(in_token && c != ' ') {
if(tok_type == T_VAR_EDIT){ if(tok_type == T_VAR_EDIT) {
if(var_op != OP_NULL){ if(var_op != OP_NULL) {
if(num_pos < TOKEN_MAX_SZ) num[num_pos++] = c; if(num_pos < TOKEN_MAX_SZ)
num[num_pos++] = c;
} }
if(strchr(op_chars, c)){ if(strchr(op_chars, c)) {
var_op = (Operation)(strchr(op_chars, c)-op_chars); var_op = (Operation)(strchr(op_chars, c) - op_chars);
} }
if(var_op == OP_NULL){ if(var_op == OP_NULL) {
if(name_pos < TOKEN_MAX_SZ) var_name[name_pos++] = c; if(name_pos < TOKEN_MAX_SZ)
var_name[name_pos++] = c;
} }
} }
if(c == '$'){ if(c == '$') {
tok_type = T_VAR_EDIT; tok_type = T_VAR_EDIT;
} }
} }

View file

@ -15,11 +15,7 @@ typedef struct {
unsigned int vars; unsigned int vars;
} EventHandler; } EventHandler;
typedef enum { typedef enum { T_NULL, T_VAR_EDIT, T_AMOUNT } Token;
T_NULL,
T_VAR_EDIT,
T_AMOUNT
} Token;
typedef enum { typedef enum {
OP_NULL, OP_NULL,
@ -39,7 +35,7 @@ typedef enum {
*/ */
void events_init_handler(EventHandler *handler); void events_init_handler(EventHandler *handler);
/* events_bind_variable() /* events_bind_variable()
* *
* Bind a variable. Binding a variable allows it to be modified by messages * Bind a variable. Binding a variable allows it to be modified by messages
* passed to the event handler using tags written as following: * passed to the event handler using tags written as following:
* `variable+number` (The backticks delimit the tag). Available operators: * `variable+number` (The backticks delimit the tag). Available operators:

View file

@ -1,17 +1,14 @@
#include "game.h" #include "game.h"
#include "map.h"
#include "config.h" #include "config.h"
#include "map.h"
#include <stdlib.h>
#include <string.h>
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <gint/display.h>
#include "npc.h" #include "npc.h"
#include <gint/cpu.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdlib.h>
#include <string.h>
extern bopti_image_t SignAction_img; extern bopti_image_t SignAction_img;
@ -87,13 +84,13 @@ void game_logic(Game *game) {
void game_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) return; if(game->player.canDoSomething == false)
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 game_draw(Game *game) { void game_draw(Game *game) {
/* Draw everything. */ /* Draw everything. */
dclear(C_WHITE); dclear(C_WHITE);
@ -116,14 +113,28 @@ void game_get_inputs(Game *game) {
/*************************************/ /*************************************/
if(keydown(KEY_EXIT)) game->exittoOS = true; if(keydown(KEY_EXIT))
game->exittoOS = true;
/* Player actions - Prototypes in player.h and implementation in player.c */ /* Player actions - Prototypes in player.h and implementation in player.c */
if(keydown(KEY_LEFT)) player_move(game, D_LEFT); if(keydown(KEY_LEFT))
if(keydown(KEY_RIGHT)) player_move(game, D_RIGHT); player_move(game, D_LEFT);
if(keydown(KEY_UP)) player_move(game, D_UP); if(keydown(KEY_RIGHT))
if(keydown(KEY_DOWN)) player_move(game, D_DOWN); player_move(game, D_RIGHT);
if(keydown(KEY_SHIFT)) player_action(game); if(keydown(KEY_UP))
player_move(game, D_UP);
if(keydown(KEY_DOWN))
player_move(game, D_DOWN);
if(keydown(KEY_SHIFT))
player_action(game);
if(keydown(KEY_OPTN)) {
game->player.is_male = !game->player.is_male;
/* TODO: Make something cleaner */
while(keydown(KEY_OPTN)) {
clearevents();
sleep();
}
}
/* Display Debug Information on screen */ /* Display Debug Information on screen */
#if DEBUGMODE #if DEBUGMODE
@ -138,12 +149,13 @@ void game_get_inputs(Game *game) {
} }
#endif #endif
/* if USB is enabled - keybinding for screencapture */ /* if USB is enabled - keybinding for screencapture */
#if USB_FEATURE #if USB_FEATURE
if(keydown(KEY_7)) game->screenshot = true; if(keydown(KEY_7))
if(keydown(KEY_8)) game->record = !game->record; game->screenshot = true;
if(keydown(KEY_8))
game->record = !game->record;
#endif //USB_FEATURE #endif // USB_FEATURE
} }

View file

@ -1,21 +1,13 @@
#ifndef GAME_H #ifndef GAME_H
#define GAME_H #define GAME_H
#include "events.h"
#include <gint/display.h> #include <gint/display.h>
#include <stdint.h> #include <stdint.h>
#include "events.h"
/* The direction where the player is going to. */ /* The direction where the player is going to. */
typedef enum { typedef enum { D_UP, D_DOWN, D_LEFT, D_RIGHT } Direction;
D_UP,
D_DOWN,
D_LEFT,
D_RIGHT
} Direction;
typedef enum { typedef enum {
P_LEFTUP = -1, P_LEFTUP = -1,
@ -32,25 +24,24 @@ typedef struct
/* Struct that define player parameters */ /* Struct that define player parameters */
typedef struct { typedef struct {
int16_t x, y; /* The position of the player int the current map */ int16_t x, y; /* The position of the player int the current map */
uint16_t px, py; /* The position of the player on screen */ uint16_t px, py; /* The position of the player on screen */
int16_t wx, wy; /* position of the player in the world */ int16_t wx, wy; /* position of the player in the world */
int8_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. */ int8_t speed; /* The speed of the movement of the player. */
/* set to true if a action can be done in the current position of the map */ /* set to true if a action can be done in the current position of the map */
bool canDoSomething; bool canDoSomething;
/* indicates which data are relevant to the current action in the */ /* indicates which data are relevant to the current action in the */
/* extradata layer of the map */ /* extradata layer of the map */
int32_t whichAction; int32_t whichAction;
/* the player is doing something */ /* the player is doing something */
bool isDoingAction; bool isDoingAction;
/* the player is interacting with a NPC */ /* the player is interacting with a NPC */
bool isInteractingWithNPC; bool isInteractingWithNPC;
bool is_male;
} Player; } Player;
typedef struct { typedef struct {
uint32_t ID; uint32_t ID;
/* data to be shown in the dialog*/ /* data to be shown in the dialog*/
@ -68,8 +59,8 @@ typedef struct {
int32_t nextOther; int32_t nextOther;
} Dialog; } Dialog;
typedef struct typedef struct {
{ /* position of the item */
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
/*id of it's icon*/ /*id of it's icon*/
@ -82,7 +73,6 @@ typedef struct
uint32_t dialogID; uint32_t dialogID;
/*if the dialog is interactive or not*/ /*if the dialog is interactive or not*/
uint32_t needAction; uint32_t needAction;
} Sign; } Sign;
typedef struct typedef struct
@ -93,7 +83,7 @@ typedef struct
/* initial coordinates of the NPC (needed to get absolute coordinates of path) */ /* initial coordinates of the NPC (needed to get absolute coordinates of path) */
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
/* id of it's face*/ /* id of it's face */
uint16_t face; uint16_t face;
uint8_t paused; uint8_t paused;
@ -120,17 +110,14 @@ typedef struct
uint8_t hostile_to_group; uint8_t hostile_to_group;
uint16_t __padding; uint16_t __padding;
} NPC; } NPC;
typedef struct{ typedef struct{
Collider collider; Collider collider;
/*if the portal tps to an interior or exterior map*/ /*if the portal tps to an interior or exterior map*/
uint16_t tp_interior; uint16_t tp_interior;
/*Id of the interior/exterior map to transport the player to*/ /*Id of the interior/exterior map to transport the player to*/
uint16_t tp_to; uint16_t tp_to;
} Portal; } Portal;
typedef struct { typedef struct {
@ -172,14 +159,12 @@ typedef struct {
} Map; } Map;
/* This struct will contain all the data of the game. It will make it possible /* This struct will contain all the data of the game. It will make it possible
* to pass it to the NPCs to let them interact with the player and the rest of * to pass it to the NPCs to let them interact with the player and the rest of
* the world. */ * the world. */
typedef struct { typedef struct {
Map *map_level; /* The level that the player is currently playing */ Map *map_level; /* The level that the player is currently playing */
Player player; /* The player data. */ Player player; /* The player data. */
EventHandler handler; /* The event handler (see events.h). */ EventHandler handler; /* The event handler (see events.h). */
/* Some global variables */ /* Some global variables */
/* Set to true when asked for exit */ /* Set to true when asked for exit */
@ -210,7 +195,7 @@ void game_logic(Game *game);
void game_draw(Game *game); void game_draw(Game *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.
@ -218,11 +203,10 @@ void game_draw(Game *game);
void game_render_indicator(Game *game); void game_render_indicator(Game *game);
/* game_get_inputs() /* game_get_inputs()
* *
* Handle key presses. * Handle key presses.
* game: The game struct. * game: The game struct.
*/ */
void game_get_inputs(Game *game); void game_get_inputs(Game *game);
#endif #endif

View file

@ -3,17 +3,13 @@
#include <gint/timer.h> #include <gint/timer.h>
#include <gint/cpu.h> #include <gint/cpu.h>
#include <fxlibc/printf.h>
#include "config.h" #include "config.h"
#include "npc.h"
#include "events.h"
#if USB_FEATURE #if USB_FEATURE
#include <gint/usb-ff-bulk.h> #include <gint/usb-ff-bulk.h>
#include <gint/usb.h> #include <gint/usb.h>
#endif //USB_FEATURE #endif // USB_FEATURE
#if GRAYMODEOK #if GRAYMODEOK
#include <gint/gray.h> #include <gint/gray.h>
@ -23,66 +19,70 @@
#include <gint/gdb.h> #include <gint/gdb.h>
#endif /*DEBUGMODE*/ #endif /*DEBUGMODE*/
#include <stdint.h> #include "dialogs.h"
#include <stdbool.h>
#include "game.h" #include "game.h"
#include "mapdata.h" #include "mapdata.h"
#include "dialogs.h" #include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
extern bopti_image_t player_face_img; extern bopti_image_t player_face_img;
extern Map *worldRPG[]; extern Map *worldRPG[];
/* Game data (defined in "game.h")*/ /* Game data (defined in "game.h")*/
Game game = { Game game = {NULL,
NULL, {12 * PXSIZE, 36 * PXSIZE, 0, 0, 12 * PXSIZE, 36 * PXSIZE, 100,
{12*PXSIZE, 36*PXSIZE, 0, 0, 12*PXSIZE, 36*PXSIZE, 100, SPEED, false, 0, false, false}, SPEED, false, 0, false, false, true, true},
{{}, {}, 0}, {{}, {}, 0},
false, false, false, 0 false,
false,
false,
0
/* debug variables*/ /* debug variables*/
, false, false, false, 100 ,
}; false,
false,
false,
100};
/* screen capture management code. TODO: Clean this up! */ /* screen capture management code. TODO: Clean this up! */
#if USB_FEATURE #if USB_FEATURE
void USB_feature( void ) void USB_feature(void) {
{ if(game.screenshot && usb_is_open()) {
if (game.screenshot && usb_is_open()) {
#if GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then #if GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then
// we make the code accessible // we make the code accessible
if (dgray_enabled()) if(dgray_enabled())
usb_fxlink_screenshot_gray(false); usb_fxlink_screenshot_gray(false);
else else
#endif #endif
// else we just let the usual screeshot function // else we just let the usual screeshot function
usb_fxlink_screenshot(false); usb_fxlink_screenshot(false);
game.screenshot = false; game.screenshot = false;
} }
if(game.record && usb_is_open()) {
if (game.record && usb_is_open()) { #if GRAYMODEOK
#if GRAYMODEOK
if (dgray_enabled()) if(dgray_enabled())
usb_fxlink_videocapture_gray(false); usb_fxlink_videocapture_gray(false);
else else
#endif #endif
usb_fxlink_videocapture(false); usb_fxlink_videocapture(false);
}
} }
}
#endif #endif
@ -99,18 +99,18 @@ int main(void) {
gdb_start_on_exception(); gdb_start_on_exception();
#endif /*DEBUGMODE*/ #endif /*DEBUGMODE*/
__printf_enable_fp(); //__printf_enable_fp();
int timer; int timer;
timer = timer_configure(TIMER_TMU, 1000, GINT_CALL(update_time)); timer = timer_configure(TIMER_TMU, 1000, GINT_CALL(update_time));
if(timer < 0){ if(timer < 0) {
return -1; return -1;
} }
timer_start(timer); timer_start(timer);
game.map_level = worldRPG[0]; game.map_level = worldRPG[0];
events_init_handler(&game.handler); events_init_handler(&game.handler);
events_bind_variable(&game.handler, (int*)&game.player.life, "life"); events_bind_variable(&game.handler, (int *)&game.player.life, "life");
events_bind_variable(&game.handler, &game.mana, "mana"); events_bind_variable(&game.handler, &game.mana, "mana");
//reload_npc(&game); //reload_npc(&game);
@ -129,7 +129,7 @@ int main(void) {
dupdate(); dupdate();
getkey(); getkey();
do{ do {
/* clear screen */ /* clear screen */
dclear(C_WHITE); dclear(C_WHITE);
@ -181,33 +181,30 @@ int main(void) {
/* Screen blit */ /* Screen blit */
dupdate(); dupdate();
/* Screen capture feature if enabled */ /* Screen capture feature if enabled */
#if USB_FEATURE #if USB_FEATURE
USB_feature(); USB_feature();
#endif #endif
/* Management of the inputs */ /* Management of the inputs */
game_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 */
game.frame_duration = 0; game.frame_duration = 0;
}while(!game.exittoOS); // want to exit ? } while(!game.exittoOS); // want to exit ?
/* shutdown grayengine*/
#if GRAYMODEOK
dgray(DGRAY_OFF);
#endif
/* close USB */
/* shutdown grayengine*/ #if USB_FEATURE
#if GRAYMODEOK usb_close();
dgray(DGRAY_OFF); #endif
#endif
/* close USB */
#if USB_FEATURE
usb_close();
#endif
timer_stop(timer); timer_stop(timer);
return 1; return 1;
} }

165
src/map.c
View file

@ -1,4 +1,5 @@
#include "map.h" #include "map.h"
#include "config.h" #include "config.h"
#include "game.h" #include "game.h"
@ -6,8 +7,7 @@
#include <gint/keyboard.h> #include <gint/keyboard.h>
extern Map *worldRPG[]; extern Map *worldRPG[];
//extern ExtraData *extraRPG[]; // extern ExtraData *extraRPG[];
void map_render(Game *game) { void map_render(Game *game) {
@ -26,9 +26,10 @@ void map_render(Game *game) {
unsigned char mx, my; unsigned char mx, my;
/* dw and dh contain the amount of tiles that will be drawn on x and on /* dw and dh contain the amount of tiles that will be drawn on x and on
* y. */ * y. */
unsigned char dw = DWIDTH/T_WIDTH+2, dh = DHEIGHT/T_HEIGHT+1; unsigned char dw = DWIDTH / T_WIDTH + 2, dh = DHEIGHT / T_HEIGHT + 1;
/* mw and mh will contain the height and the width of the map. */ /* mw and mh will contain the height and the width of the map. */
unsigned short int mw = map_level->w*T_WIDTH, mh = map_level->h*T_HEIGHT; unsigned short int mw = map_level->w * T_WIDTH,
mh = map_level->h * T_HEIGHT;
/* tile contains the tile to draw. */ /* tile contains the tile to draw. */
short int tile; short int tile;
/* The position where I start drawing */ /* The position where I start drawing */
@ -40,62 +41,62 @@ void map_render(Game *game) {
/* The index of the current tile we're drawing in the layer. */ /* The index of the current tile we're drawing in the layer. */
int current_index; int current_index;
/* Fix sx. */ /* Fix sx. */
if(player->x<DWIDTH/2){ if(player->x < DWIDTH / 2) {
/* If I can't center the player because I'm near the left border of /* If I can't center the player because I'm near the left border of
* the map. */ * the map. */
player->px = player->x; player->px = player->x;
sx = 0; sx = 0;
}else if(player->x+DWIDTH/2>mw){ } else if(player->x + DWIDTH / 2 > mw) {
/* If I can't center the player because I'm near the right border of /* If I can't center the player because I'm near the right border of
* the map. */ * the map. */
sx = mw-DWIDTH; sx = mw - DWIDTH;
player->px = player->x-sx; player->px = player->x - sx;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->px = DWIDTH/2; player->px = DWIDTH / 2;
sx = player->x-player->px; sx = player->x - player->px;
} }
/* Fix sy. */ /* Fix sy. */
if(player->y<DHEIGHT/2){ if(player->y < DHEIGHT / 2) {
/* If I can't center the player because I'm near the top border of /* If I can't center the player because I'm near the top border of
* the map. */ * the map. */
player->py = player->y; player->py = player->y;
sy = 0; sy = 0;
}else if(player->y+DHEIGHT/2>mh){ } else if(player->y + DHEIGHT / 2 > mh) {
/* If I can't center the player because I'm near the bottom border /* If I can't center the player because I'm near the bottom border
* of the map. */ * of the map. */
sy = mh-DHEIGHT; sy = mh - DHEIGHT;
player->py = player->y-sy; player->py = player->y - sy;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->py = DHEIGHT/2; player->py = DHEIGHT / 2;
sy = player->y-player->py; sy = player->y - player->py;
} }
tx = sx/T_WIDTH; tx = sx / T_WIDTH;
ty = sy/T_HEIGHT; ty = sy / T_HEIGHT;
mx = sx-tx*T_WIDTH; mx = sx - tx * T_WIDTH;
my = sy-ty*T_HEIGHT; my = sy - ty * T_HEIGHT;
for (l = 0; l < map_level->nblayers-1; l++){ for(l = 0; l < map_level->nblayers - 1; l++) {
/* Draw a layer of the map on screen. */ /* Draw a layer of the map on screen. */
for(y=0;y<dh;y++){ for(y = 0; y < dh; y++) {
for(x=0;x<dw;x++){ for(x = 0; x < dw; x++) {
/* I get the tile number if his position is inside the map. Then /* I get the tile number if his position is inside the map. Then
* I draw it. */ * I draw it. */
if(tx+x>=0 && tx+x < map_level->w && if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
ty+y>=0 && ty+y < map_level->h){ ty + y < map_level->h) {
/* index of the current tile */ /* index of the current tile */
current_index = (y+ty) * map_level->w + tx+x; current_index = (y + ty) * map_level->w + tx + x;
/* we get the ID of the tile in the current drawable layers /* we get the ID of the tile in the current drawable layers
*/ */
tile = map_level->layers[l][current_index]; tile = map_level->layers[l][current_index];
/* tile == -1 means nothing to be drawn */ /* tile == -1 means nothing to be drawn */
if(tile >= 0){ if(tile >= 0) {
/* get x and y position in the tileset image */ /* get x and y position in the tileset image */
xtile = (tile % map_level->tileset_size) * T_WIDTH; xtile = (tile % map_level->tileset_size) * T_WIDTH;
ytile = (tile / map_level->tileset_size) * T_HEIGHT; ytile = (tile / map_level->tileset_size) * T_HEIGHT;
/* render */ /* render */
dsubimage(x*T_WIDTH-mx, y*T_HEIGHT-my, dsubimage(x * T_WIDTH - mx, y * T_HEIGHT - my,
map_level->tileset, xtile, ytile, T_WIDTH, map_level->tileset, xtile, ytile, T_WIDTH,
T_HEIGHT, DIMAGE_NONE); T_HEIGHT, DIMAGE_NONE);
} }
@ -106,7 +107,7 @@ void map_render(Game *game) {
} }
void map_render_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;
@ -122,9 +123,10 @@ void map_render_by_layer(Game *game, int layer) {
unsigned char mx, my; unsigned char mx, my;
/* dw and dh contain the amount of tiles that will be drawn on x and on /* dw and dh contain the amount of tiles that will be drawn on x and on
* y. */ * y. */
unsigned char dw = DWIDTH/T_WIDTH+2, dh = DHEIGHT/T_HEIGHT+1; unsigned char dw = DWIDTH / T_WIDTH + 2, dh = DHEIGHT / T_HEIGHT + 1;
/* mw and mh will contain the height and the width of the map. */ /* mw and mh will contain the height and the width of the map. */
unsigned short int mw = map_level->w*T_WIDTH, mh = map_level->h*T_HEIGHT; unsigned short int mw = map_level->w * T_WIDTH,
mh = map_level->h * T_HEIGHT;
/* tile contains the tile to draw. */ /* tile contains the tile to draw. */
short int tile; short int tile;
/* The position where I start drawing */ /* The position where I start drawing */
@ -132,63 +134,63 @@ void map_render_by_layer(Game *game, int layer) {
/* The position of the tile in the tileset. */ /* The position of the tile in the tileset. */
unsigned short int xtile, ytile; unsigned short int xtile, ytile;
/* Fix sx. */ /* Fix sx. */
if(player->x<DWIDTH/2){ if(player->x < DWIDTH / 2) {
/* If I can't center the player because I'm near the left border of /* If I can't center the player because I'm near the left border of
* the map. */ * the map. */
player->px = player->x; player->px = player->x;
sx = 0; sx = 0;
}else if(player->x+DWIDTH/2>mw){ } else if(player->x + DWIDTH / 2 > mw) {
/* If I can't center the player because I'm near the right border of /* If I can't center the player because I'm near the right border of
* the map. */ * the map. */
sx = mw-DWIDTH; sx = mw - DWIDTH;
player->px = player->x-sx; player->px = player->x - sx;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->px = DWIDTH/2; player->px = DWIDTH / 2;
sx = player->x-player->px; sx = player->x - player->px;
} }
/* Fix sy. */ /* Fix sy. */
if(player->y<DHEIGHT/2){ if(player->y < DHEIGHT / 2) {
/* If I can't center the player because I'm near the top border of /* If I can't center the player because I'm near the top border of
* the map. */ * the map. */
player->py = player->y; player->py = player->y;
sy = 0; sy = 0;
}else if(player->y+DHEIGHT/2>mh){ } else if(player->y + DHEIGHT / 2 > mh) {
/* If I can't center the player because I'm near the bottom border /* If I can't center the player because I'm near the bottom border
* of the map. */ * of the map. */
sy = mh-DHEIGHT; sy = mh - DHEIGHT;
player->py = player->y-sy; player->py = player->y - sy;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->py = DHEIGHT/2; player->py = DHEIGHT / 2;
sy = player->y-player->py; sy = player->y - player->py;
} }
tx = sx/T_WIDTH; tx = sx / T_WIDTH;
ty = sy/T_HEIGHT; ty = sy / T_HEIGHT;
mx = sx-tx*T_WIDTH; mx = sx - tx * T_WIDTH;
my = sy-ty*T_HEIGHT; my = sy - ty * T_HEIGHT;
/* Draw a layer of the map on screen. */ /* Draw a layer of the map on screen. */
for(y=0;y<dh;y++){ for(y = 0; y < dh; y++) {
for(x=0;x<dw;x++){ for(x = 0; x < dw; x++) {
/* I get the tile number if his position is inside the map. Then /* I get the tile number if his position is inside the map. Then
* I draw it. */ * I draw it. */
if(tx+x>=0 && tx+x < map_level->w && if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
ty+y>=0 && ty+y < map_level->h){ ty + y < map_level->h) {
/* index of the current tile */ /* index of the current tile */
int currentIndex = (y+ty) * map_level->w + tx+x; int currentIndex = (y + ty) * map_level->w + tx + x;
/* we get the ID of the tile in the current drawable layers /* we get the ID of the tile in the current drawable layers
*/ */
tile = map_level->layers[layer][currentIndex]; //DEBUG : Unaligned read here tile = map_level->layers[layer][currentIndex];
/* tile == -1 means nothing to be drawn */ /* tile == -1 means nothing to be drawn */
if(tile >= 0){ if(tile >= 0) {
/* get x and y position in the tileset image */ /* get x and y position in the tileset image */
xtile = (tile % map_level->tileset_size) * T_WIDTH; xtile = (tile % map_level->tileset_size) * T_WIDTH;
ytile = (tile / map_level->tileset_size) * T_HEIGHT; ytile = (tile / map_level->tileset_size) * T_HEIGHT;
/* render */ /* render */
dsubimage(x*T_WIDTH-mx, y*T_HEIGHT-my, dsubimage(x * T_WIDTH - mx, y * T_HEIGHT - my,
map_level->tileset, xtile, ytile, T_WIDTH, map_level->tileset, xtile, ytile, T_WIDTH,
T_HEIGHT, DIMAGE_NONE); T_HEIGHT, DIMAGE_NONE);
} }
} }
} }
@ -196,44 +198,45 @@ void map_render_by_layer(Game *game, int layer) {
} }
short int map_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;
/* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if
* it's not found. */ * it's not found. */
return (x>=0 && x < (int) map_level->w && y>=0 && y < (int) map_level->h) ? return (x >= 0 && x < (int)map_level->w && y >= 0 && y < (int)map_level->h)
map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; ? map_level->layers[l][y * map_level->w + x]
: MAP_OUTSIDE;
} }
short int map_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
* found. */ * found. */
return (x>=0 && x < (int) map_level->w && y>=0 && y < (int) map_level->h) ? return (x >= 0 && x < (int)map_level->w && y >= 0 && y < (int)map_level->h)
map_level->walkable[y * map_level->w + x] : MAP_OUTSIDE; ? map_level->walkable[y * map_level->w + x]
: MAP_OUTSIDE;
} }
/* return the pointer to the map containing the given position */ /* return the pointer to the map containing the given position */
Map *map_get_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 &&
y>= (int)game->map_level->ymin && y< (int)game->map_level->ymax){ y >= (int)game->map_level->ymin && y < (int)game->map_level->ymax) {
return game->map_level; return game->map_level;
} }
/* else we check in worldRPG if there is a mal containing that point */ /* else we check in worldRPG if there is a mal containing that point */
int i = 0; int i = 0;
Map *current = worldRPG[i]; Map *current = worldRPG[i];
do{ do {
if (x>= (int)current->xmin && x< (int)current->xmax && if(x >= (int)current->xmin && x < (int)current->xmax &&
y>= (int)current->ymin && y< (int)current->ymax) y >= (int)current->ymin && y < (int)current->ymax)
return current; return current;
i++; i++;
current = worldRPG[i]; current = worldRPG[i];
}while (current!=NULL); } while(current != NULL);
/* else we return NULL cause the point is a not within a map */ /* else we return NULL cause the point is a not within a map */
return NULL; return NULL;
} }

View file

@ -1,33 +1,29 @@
#ifndef MAP_H #ifndef MAP_H
#define MAP_H #define MAP_H
#define BACKGROUND 0 #define BACKGROUND 0
#define FOREGROUND 1 #define FOREGROUND 1
#define MAP_OUTSIDE -2 /* Returned by get_tile_at_pos if the point is outside of #define MAP_OUTSIDE \
* the map. */ -2 /* Returned by get_tile_at_pos if the point is outside of \
* the map. */
#include "game.h" #include "game.h"
#include "player.h" #include "player.h"
/* Structure 'Map' has been moved to game.h */ /* Structure 'Map' has been moved to game.h */
/* to avoid circular references between map.h, game.h and player.h */ /* to avoid circular references between map.h, game.h and player.h */
/* only methods propotypes are now in dedicated header files */ /* only methods propotypes are now in dedicated header files */
/* map_render() /* 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 map_render(Game *game); void map_render(Game *game);
/* map_render_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.
@ -35,7 +31,7 @@ void map_render(Game *game);
void map_render_by_layer(Game *game, int layer); void map_render_by_layer(Game *game, int layer);
/* map_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.
* game: The game struct. * game: The game struct.
@ -46,7 +42,7 @@ void map_render_by_layer(Game *game, int layer);
short int map_get_tile(Game *game, int x, int y, int l); short int map_get_tile(Game *game, int x, int y, int l);
/* map_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.
@ -55,12 +51,12 @@ short int map_get_tile(Game *game, int x, int y, int l);
short int map_get_walkable(Game *game, int x, int y); short int map_get_walkable(Game *game, int x, int y);
/* map_get_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* map_get_for_coordinates(Game *game, int x, int y ); Map *map_get_for_coordinates(Game *game, int x, int y);
#endif #endif

View file

@ -1,10 +1,10 @@
#ifndef MAPDATA_H #ifndef MAPDATA_H
#define MAPDATA_H #define MAPDATA_H
#include <stdint.h>
#include "game.h" #include "game.h"
#include <stdint.h>
extern Map *worldRPG[]; extern Map *worldRPG[];
#endif #endif

View file

@ -2,11 +2,10 @@
bool memory_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) {
return true; return true;
} }
} }
return false; return false;
} }

View file

@ -3,7 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
/* memory_is_in() /* memory_is_in()
* *
* returns true if item is in array. * returns true if item is in array.
* array: The array to search in. * array: The array to search in.
* array_length: The length of the array. * array_length: The length of the array.
@ -12,4 +12,3 @@
bool memory_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);
#endif #endif

282
src/npc.c
View file

@ -1,29 +1,27 @@
#include "npc.h" #include "npc.h"
#include "config.h"
#include "dialogs.h" #include "dialogs.h"
#include "game.h" #include "game.h"
#include "map.h" #include "map.h"
#include "config.h"
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h> /*debug*/ #include <gint/keyboard.h> /*debug*/
#include <math.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
extern bopti_image_t demo_PNJ_img;
extern bopti_image_t tiny_npc_male;
extern bopti_image_t tiny_npc_female;
extern bopti_image_t tiny_npc_milkman;
extern bopti_image_t tiny_npc_police;
//NPC *npcRPG; //NPC *npcRPG;
//uint32_t nbNPC = 0; //uint32_t nbNPC = 0;
float length( float x, float y ) float length(float x, float y) { return sqrtf(x * x + y * y); }
{
return sqrtf( x*x+y*y );
}
int npc_clear_path(NPC *npc) int npc_clear_path(NPC *npc) {
{
npc->currentPoint = 0; npc->currentPoint = 0;
npc->hasPath = 0; npc->hasPath = 0;
npc->path_length = 0; npc->path_length = 0;
@ -31,47 +29,46 @@ int npc_clear_path(NPC *npc)
free(npc->ypath); free(npc->ypath);
npc->xpath = malloc(4); npc->xpath = malloc(4);
npc->ypath = malloc(4); npc->ypath = malloc(4);
if(npc->xpath == NULL || npc->ypath == NULL) return 1; if(npc->xpath == NULL || npc->ypath == NULL)
return 1;
return 0; return 0;
} }
int npc_append_path(uint16_t x, uint16_t y, NPC *npc) int npc_append_path(uint16_t x, uint16_t y, NPC *npc) {
{ npc->xpath = realloc(npc->xpath, npc->path_length * 2 + 2);
npc->xpath = realloc(npc->xpath, npc->path_length*2+2); npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
npc->ypath = realloc(npc->ypath, npc->path_length*2+2); if(npc->xpath == NULL || npc->ypath == NULL)
if(npc->xpath == NULL || npc->ypath == NULL) return 1; return 1;
npc->path_length++; npc->path_length++;
npc->xpath[npc->path_length-1] = x - npc->x; npc->xpath[npc->path_length - 1] = x - npc->x;
npc->ypath[npc->path_length-1] = y - npc->y; npc->ypath[npc->path_length - 1] = y - npc->y;
return 0; return 0;
} }
void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
{
free(visited); free(visited);
free(gscore); free(gscore);
free(fscore); free(fscore);
} }
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos, int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
int16_t dest, NPC *npc) int16_t dest, NPC *npc) {
{ if(npc_clear_path(npc))
if(npc_clear_path(npc)) goto as_recons_fail; goto as_recons_fail;
int16_t next = came_from[dest]; int16_t next = came_from[dest];
unsigned int i; unsigned int i;
for(i = 0; i < 64; i++) for(i = 0; i < 64; i++) {
{ if(npc_append_path((next % w) * T_WIDTH, (next / h) * T_HEIGHT, npc)) {
if(npc_append_path((next%w)*T_WIDTH,(next/h)*T_HEIGHT, npc))
{
goto as_recons_fail; goto as_recons_fail;
} }
next = came_from[next]; next = came_from[next];
if(next == spos){ if(next == spos) {
if(npc_append_path((spos%w)*T_WIDTH,(spos/h)*T_HEIGHT, npc)) if(npc_append_path((spos % w) * T_WIDTH, (spos / h) * T_HEIGHT,
npc))
goto as_recons_fail; goto as_recons_fail;
break; break;
} }
@ -79,16 +76,15 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
uint16_t tx, ty; uint16_t tx, ty;
//Flip the path because it started from the end // Flip the path because it started from the end
for(i = 0; i < npc->path_length/2; i++) for(i = 0; i < npc->path_length / 2; i++) {
{
tx = npc->xpath[i]; tx = npc->xpath[i];
ty = npc->ypath[i]; ty = npc->ypath[i];
npc->xpath[i] = npc->xpath[npc->path_length-i-1]; npc->xpath[i] = npc->xpath[npc->path_length - i - 1];
npc->ypath[i] = npc->ypath[npc->path_length-i-1]; npc->ypath[i] = npc->ypath[npc->path_length - i - 1];
npc->ypath[npc->path_length-i-1] = tx; npc->ypath[npc->path_length - i - 1] = tx;
npc->ypath[npc->path_length-i-1] = ty; npc->ypath[npc->path_length - i - 1] = ty;
} }
free(came_from); free(came_from);
@ -97,95 +93,103 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
return 0; return 0;
as_recons_fail: as_recons_fail:
free(came_from); free(came_from);
return 1; return 1;
} }
//Returns non zero error code on failure // Returns non zero error code on failure
//Custom a* implemetation // Custom a* implemetation
//Unoptimized, may become an issue // Unoptimized, may become an issue
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
{
int32_t i, j; int32_t i, j;
int32_t w = full_map->w; int32_t w = full_map->w;
int32_t h = full_map->h; int32_t h = full_map->h;
int32_t x = floor(npc->curx)/T_WIDTH; int32_t x = floor(npc->curx) / T_WIDTH;
int32_t y = floor(npc->cury)/T_HEIGHT; int32_t y = floor(npc->cury) / T_HEIGHT;
dest_x /= T_WIDTH; dest_x /= T_WIDTH;
dest_y /= T_HEIGHT; dest_y /= T_HEIGHT;
int32_t spos = y*w+x; int32_t spos = y * w + x;
uint8_t *map = full_map->walkable; uint8_t *map = full_map->walkable;
if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h) return 2; if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h)
if(map[spos]) return 2; return 2;
if(map[dest_y*w+dest_x]) return 2; if(map[spos])
return 2;
if(map[dest_y * w + dest_x])
return 2;
npc_clear_path(npc); npc_clear_path(npc);
uint8_t *visited = malloc(w*h); uint8_t *visited = malloc(w * h);
for(i=0; i<w*h; i++) visited[i] = 1; for(i = 0; i < w * h; i++)
visited[i] = 1;
visited[spos] = 0; visited[spos] = 0;
int16_t *came_from = malloc(w*h*2); int16_t *came_from = malloc(w * h * 2);
for(i=0; i<w*h; i++) came_from[i] = -1; for(i = 0; i < w * h; i++)
came_from[i] = -1;
uint8_t *gscore = malloc(w*h*2); uint8_t *gscore = malloc(w * h * 2);
for(i=0; i<w*h; i++) gscore[i] = 255; for(i = 0; i < w * h; i++)
gscore[i] = 255;
gscore[spos] = 0; gscore[spos] = 0;
uint8_t *fscore = malloc(w*h*2); uint8_t *fscore = malloc(w * h * 2);
for(i=0; i<w*h; i++) fscore[i] = 255; for(i = 0; i < w * h; i++)
fscore[spos] = length(dest_x-x, dest_y-y); fscore[i] = 255;
fscore[spos] = length(dest_x - x, dest_y - y);
uint8_t bscore; uint8_t bscore;
int32_t bx = x; int32_t bx = x;
int32_t by = y; int32_t by = y;
for(int iter=0; iter < 64; iter++) for(int iter = 0; iter < 64; iter++) {
{
bscore = 255; bscore = 255;
//Cheapest known tile // Cheapest known tile
for(i = 0; i <= w*h; i++) for(i = 0; i <= w * h; i++) {
{ if(visited[i])
if(visited[i]) continue; continue;
if(map[i] == 1) continue; if(map[i] == 1)
if(fscore[i] > bscore) continue; continue;
bx = i%w; if(fscore[i] > bscore)
by = i/w; continue;
bx = i % w;
by = i / w;
bscore = fscore[i]; bscore = fscore[i];
} }
if(bx == dest_x && by == dest_y) if(bx == dest_x && by == dest_y) {
{
as_clean(visited, gscore, fscore); as_clean(visited, gscore, fscore);
return as_reconstruct_path(came_from, w, h, spos, return as_reconstruct_path(came_from, w, h, spos,
dest_y*w+dest_x, npc); dest_y * w + dest_x, npc);
} }
visited[by*w+bx] = 1; visited[by * w + bx] = 1;
int att_score; int att_score;
for(i = bx-1; i < bx+2; i++) for(i = bx - 1; i < bx + 2; i++) {
{ if(i > w)
if(i > w) break; break;
for(j = by-1; j < by+2; j++) for(j = by - 1; j < by + 2; j++) {
{ if(j > h)
if(j > h) break; break;
if(map[j*w+i] == 1) continue; if(map[j * w + i] == 1)
if(i == bx && j == by) continue; continue;
att_score = gscore[by*w+bx] + round(length(bx-i,by-j)); if(i == bx && j == by)
if(att_score < gscore[j*w+i]) continue;
{ att_score = gscore[by * w + bx] + round(length(bx - i, by - j));
came_from[j*w+i] = by*w+bx; if(att_score < gscore[j * w + i]) {
gscore[j*w+i] = att_score; came_from[j * w + i] = by * w + bx;
fscore[j*w+i] = att_score + round( gscore[j * w + i] = att_score;
length(dest_x-i, dest_y-j)); fscore[j * w + i] =
if(visited[j*w+i]) visited[j*w+i] = 0; att_score + round(length(dest_x - i, dest_y - j));
if(visited[j * w + i])
visited[j * w + i] = 0;
} }
} }
} }
@ -197,31 +201,28 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc)
return 3; return 3;
} }
/*The following functions need to be redone*/ /*NPC *npc_create() {
/* // Use temp pointer to avoid breaking the whole npcRPG on failure
NPC *npc_create() void *temp = realloc(npcRPG, (nbNPC + 1) * sizeof(NPC));
{ if(temp == NULL)
//Use temp pointer to avoid breaking the whole npcRPG on failure return NULL;
void *temp = realloc(npcRPG, (nbNPC+1)*sizeof(NPC));
if(temp == NULL) return NULL;
npcRPG = temp; npcRPG = temp;
nbNPC++; nbNPC++;
NPC *npc = &npcRPG[nbNPC-1]; NPC *npc = &npcRPG[nbNPC - 1];
npc->xpath = malloc(2); npc->xpath = malloc(2);
npc->ypath = malloc(2); npc->ypath = malloc(2);
return npc; return npc;
} }*/
void npc_remove(NPC *npc) /*void npc_remove(NPC *npc) {
{ uint32_t pos = ((uint32_t)npc - (uint32_t)npcRPG) / sizeof(NPC);
uint32_t pos = ((uint32_t)npc - (uint32_t)npcRPG)/sizeof(NPC); if(pos > nbNPC - 1)
if(pos > nbNPC-1) return; return;
if(pos == nbNPC-1) if(pos == nbNPC - 1) {
{
nbNPC--; nbNPC--;
return; return;
} }
memmove(npc, &npc[1], (nbNPC-pos-1)*sizeof(NPC)); memmove(npc, &npc[1], (nbNPC - pos - 1) * sizeof(NPC));
}*/ }*/
//Refactoring to make adding complexity cleaner //Refactoring to make adding complexity cleaner
@ -233,71 +234,60 @@ void update_npcs([[maybe_unused]] Game *game)
} }
} }
void update_npc(NPC *npc) void update_npc(NPC *npc) {
{
/* if the NPC has no path or is paused, skip it */ /* if the NPC has no path or is paused, skip it */
if (!npc->hasPath || npc->paused==true) return; if(!npc->hasPath || npc->paused == true)
return;
float vecX = (float) (npc->xpath[ npc->currentPoint ] + float vecX = (float)(npc->xpath[npc->currentPoint] + npc->x) - npc->curx;
npc->x) - npc->curx; float vecY = (float)(npc->ypath[npc->currentPoint] + npc->y) - npc->cury;
float vecY = (float) (npc->ypath[ npc->currentPoint ] +
npc->y) - npc->cury;
float vecN = length(vecX, vecY); float vecN = length(vecX, vecY);
if (vecN>0.5f) if(vecN > 0.5f) {
{ vecX /= vecN * 2.0;
vecX /= vecN*2.0; vecY /= vecN * 2.0;
vecY /= vecN*2.0; } else {
}
else
{
npc->currentPoint++; npc->currentPoint++;
npc->currentPoint = npc->currentPoint % npc->path_length; npc->currentPoint = npc->currentPoint % npc->path_length;
} }
npc->curx += vecX; npc->curx += vecX;
npc->cury += vecY; npc->cury += vecY;
} }
/*void reload_npc(Game *game) /*void reload_npc(Game *game) {
{ if(npcRPG != NULL) {
if (npcRPG!=NULL)
{
free(npcRPG); free(npcRPG);
npcRPG = NULL; npcRPG = NULL;
} }
nbNPC = 0; nbNPC = 0;
for(uint32_t u = 0; u < game->map_level->nbextradata; u++) {
for (uint32_t u=0; u<game->map_level->nbextradata; u++)
{
ExtraData *Data = &game->map_level->extradata[u]; ExtraData *Data = &game->map_level->extradata[u];
if (strcmp(Data->type, "NPC")==0) //the current data is a NPC if(strcmp(Data->type, "NPC") == 0)
{ {
nbNPC++; nbNPC++;
} }
} }
npcRPG = (NPC*) malloc( nbNPC * sizeof(NPC) ); npcRPG = (NPC *)malloc(nbNPC * sizeof(NPC));
if(npcRPG == NULL) return; if(npcRPG == NULL)
int currentNPC=0; return;
int currentNPC = 0;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) for(uint32_t u = 0; u < game->map_level->nbextradata; u++) {
{
ExtraData *Data = &game->map_level->extradata[u]; ExtraData *Data = &game->map_level->extradata[u];
if (strcmp(Data->type, "NPC")==0) //the current data is a NPC if(strcmp(Data->type, "NPC") == 0)
{ {
npcRPG[currentNPC].curx = (float) Data->x; npcRPG[currentNPC].curx = (float)Data->x;
npcRPG[currentNPC].cury = (float) Data->y; npcRPG[currentNPC].cury = (float)Data->y;
npcRPG[currentNPC].x = Data->x; npcRPG[currentNPC].x = Data->x;
npcRPG[currentNPC].y = Data->y; npcRPG[currentNPC].y = Data->y;
npcRPG[currentNPC].dialogID = Data->dialogID; npcRPG[currentNPC].dialogID = Data->dialogID;
npcRPG[currentNPC].currentPoint = 1; npcRPG[currentNPC].currentPoint = 1;
npcRPG[currentNPC].hasPath = Data->hasPath; npcRPG[currentNPC].hasPath = Data->hasPath;
npcRPG[currentNPC].path_length = Data->path_length; npcRPG[currentNPC].path_length = Data->path_length;
npcRPG[currentNPC].xpath = Data->xpath; npcRPG[currentNPC].xpath = Data->xpath;
@ -311,6 +301,13 @@ void update_npc(NPC *npc)
void npc_draw(Game *game) { void npc_draw(Game *game) {
Player *pl = &game->player; Player *pl = &game->player;
size_t i;
const bopti_image_t *npc_sprites[FACES] = {
&tiny_npc_male,
&tiny_npc_female,
&tiny_npc_milkman,
&tiny_npc_police
};
for (uint32_t u=0; u<game->map_level->nbNPC; u++) for (uint32_t u=0; u<game->map_level->nbNPC; u++)
{ {
@ -341,8 +338,9 @@ void npc_draw(Game *game) {
} }
#endif // DEBUGMODE #endif // DEBUGMODE
int16_t delX=((int16_t) (Data->curx * PXSIZE))-(int16_t) pl->wx; int16_t delX = ((int16_t)(Data->curx * PXSIZE)) - (int16_t)pl->wx;
int16_t delY=((int16_t) (Data->cury * PXSIZE))-(int16_t) pl->wy; int16_t delY = ((int16_t)(Data->cury * PXSIZE)) - (int16_t)pl->wy;
dimage( pl->px-P_WIDTH/2+delX, pl->py-P_HEIGHT/2+delY, &demo_PNJ_img); bopti_image_t *face = npc_sprites[Data->face];
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face);
} }
} }

View file

@ -1,43 +1,40 @@
#ifndef NPC_H #ifndef NPC_H
#define NPC_H #define NPC_H
#include <stdbool.h>
#include <stdint.h>
#include "game.h" #include "game.h"
#include "memory.h" #include "memory.h"
enum #include <stdbool.h>
{ #include <stdint.h>
enum {
NPC_NONE = 0, NPC_NONE = 0,
NPC_FRIENDLY = 1, //The player's team NPC_FRIENDLY = 1, // The player's team
NPC_HOSTILE = 2, //to the player NPC_HOSTILE = 2, // to the player
NPC_ALL = 3 NPC_ALL = 3
}; };
//Frees then malloc()s a new path to npc // Frees then malloc()s a new path to npc
//Useful if you want to safely edit a path // Useful if you want to safely edit a path
int npc_clear_path(NPC *npc); int npc_clear_path(NPC *npc);
//Adds point x,y to the path of npc // Adds point x,y to the path of npc
//Won't work on static NPCs, use npc_clear_path before or make them on the heap // Won't work on static NPCs, use npc_clear_path before or make them on the heap
int npc_append_path(uint16_t x, uint16_t y, NPC *npc); int npc_append_path(uint16_t x, uint16_t y, NPC *npc);
//Clears the NPCs path and creates a new one going to dest, // Clears the NPCs path and creates a new one going to dest,
//avoiding non-walkable tiles // avoiding non-walkable tiles
//Returns non-zero on failure // Returns non-zero on failure
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc); int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc);
/* // realloc()s npcRPG to adequate size and returns a pointer to the new element
//realloc()s npcRPG to adequate size and returns a pointer to the new element // Returns NULL on failure
//Returns NULL on failure
NPC *npc_create(); NPC *npc_create();
//Pops the NPC from npcRPG // Pops the NPC from npcRPG
void npc_remove(NPC *npc);*/ void npc_remove(NPC *npc);
/* Draws the player player. This function should be called after drawing the /* Draws the player player. This function should be called after drawing the
* map! */ * map! */
@ -50,4 +47,3 @@ void update_npc(NPC *npc);
void reload_npc(Game *game); void reload_npc(Game *game);
#endif #endif

View file

@ -1,19 +1,15 @@
#include "player.h" #include "player.h"
#include "config.h"
#include "dialogs.h" #include "dialogs.h"
#include "game.h" #include "game.h"
#include "map.h" #include "map.h"
#include "config.h"
#include "npc.h" #include "npc.h"
#include <gint/display.h> #include <gint/display.h>
#define FACES 4 extern bopti_image_t player_male_img;
extern bopti_image_t player_female_img;
struct Face {
const char *name;
bopti_image_t *face;
};
extern bopti_image_t demo_player_img;
extern bopti_image_t npc_male; extern bopti_image_t npc_male;
extern bopti_image_t npc_female; extern bopti_image_t npc_female;
extern bopti_image_t npc_milkman; extern bopti_image_t npc_milkman;
@ -21,82 +17,76 @@ extern bopti_image_t npc_police;
extern bopti_image_t SGN_Icon_img; extern bopti_image_t SGN_Icon_img;
extern bopti_image_t INFO_Icon_img; extern bopti_image_t INFO_Icon_img;
const struct Face faces[FACES] = { const bopti_image_t *faces[FACES] = {
{"MALE", &npc_male}, &npc_male,
{"FEMALE", &npc_female}, &npc_female,
{"MILKMAN", &npc_milkman}, &npc_milkman,
{"POLICE", &npc_police} &npc_police
}; };
const char one_px_mov[8] = { const char one_px_mov[8] = {
0, -1, /* Up */ 0, -1, /* Up */
0, 1, /* Down */ 0, 1, /* Down */
-1, 0, /* Left */ -1, 0, /* Left */
1, 0 /* Right */ 1, 0 /* Right */
}; };
/* TODO: Search for all hard tiles in the tileset. hard_tiles is a list of their /* TODO: Search for all hard tiles in the tileset. hard_tiles is a list of their
* IDs */ * IDs */
/* The speed of the player on the diffrent tiles in the walkable layer. */ /* The speed of the player on the diffrent tiles in the walkable layer. */
#define WALKABLE_TILE_MAX 4 #define WALKABLE_TILE_MAX 4
const short int walkable_speed[WALKABLE_TILE_MAX] = { const short int walkable_speed[WALKABLE_TILE_MAX] = {SPEED, 0, PXSIZE, PXSIZE};
SPEED, 0, PXSIZE, PXSIZE
};
/* How much damage the player takes on the diffrent tiles in the walkable /* How much damage the player takes on the diffrent tiles in the walkable
* layer. */ * layer. */
const char damage_taken_walkable[WALKABLE_TILE_MAX] = { const char damage_taken_walkable[WALKABLE_TILE_MAX] = {0, 0, 5, 0};
0, 0, 5, 0
};
extern bopti_image_t demo_player_img; extern bopti_image_t demo_player_img;
//extern NPC *npcRPG; extern NPC *npcRPG;
//extern uint32_t nbNPC; extern uint32_t nbNPC;
void player_draw(Game *game) { void player_draw(Game *game) {
Player *player = &game->player; Player *player = &game->player;
dimage(player->px-P_WIDTH/2, player->py-P_HEIGHT/2, &demo_player_img); dimage(player->px - P_WIDTH / 2, player->py - P_HEIGHT / 2,
player->is_male ? &player_male_img : &player_female_img);
} }
void player_move(Game *game, Direction direction) { void player_move(Game *game, Direction direction) {
Player *player = &game->player; Player *player = &game->player;
/* How this player movement will modify the player x and y. */ /* How this player movement will modify the player x and y. */
char dx, dy; char dx, dy;
/* If the player will collide with a hard tile or if the will go outside of /* If the player will collide with a hard tile or if the will go outside of
* the map. */ * the map. */
if(player_collision(game, direction, P_CENTER)){ if(player_collision(game, direction, P_CENTER)) {
/* If the will collide with the center of the player. */ /* If the will collide with the center of the player. */
dx = one_px_mov[direction*2]*player->speed; dx = one_px_mov[direction * 2] * player->speed;
dy = one_px_mov[direction*2+1]*player->speed; dy = one_px_mov[direction * 2 + 1] * player->speed;
player_fix_position(game, dx, dy); player_fix_position(game, dx, dy);
} } else {
else{
if(player_collision(game, direction, P_RIGHTDOWN) || if(player_collision(game, direction, P_RIGHTDOWN) ||
player_collision(game, direction, P_LEFTUP)){ player_collision(game, direction, P_LEFTUP)) {
/* If the will collide with the edges of the player. */ /* If the will collide with the edges of the player. */
/* I fix his position so he won't be partially in the tile. */ /* 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. */ /* I invert dx and dy to fix the axis where he is not moving on. */
/* Do not replace dx==0 with !dx or dy==0 with !dy, it won't work! /* Do not replace dx==0 with !dx or dy==0 with !dy, it won't work!
*/ */
dx = one_px_mov[direction*2]*player->speed; dx = one_px_mov[direction * 2] * player->speed;
dy = one_px_mov[direction*2+1]*player->speed; dy = one_px_mov[direction * 2 + 1] * player->speed;
player_fix_position(game, dx==0, dy==0); player_fix_position(game, dx == 0, dy == 0);
} }
/* If he won't collide with the center, so I just move him normally */ /* If he won't collide with the center, so I just move him normally */
dx = one_px_mov[direction*2]*player->speed; dx = one_px_mov[direction * 2] * player->speed;
dy = one_px_mov[direction*2+1]*player->speed; dy = one_px_mov[direction * 2 + 1] * player->speed;
player->x += dx; player->x += dx;
player->y += dy; player->y += dy;
} }
@ -106,6 +96,7 @@ void player_move(Game *game, Direction direction) {
} }
void player_action(Game *game) { void player_action(Game *game) {
size_t i;
/* already doing something, or can't do anything*/ /* already doing something, or can't do anything*/
if(game->player.isDoingAction || !game->player.canDoSomething) return; if(game->player.isDoingAction || !game->player.canDoSomething) return;
@ -141,10 +132,11 @@ void player_action(Game *game) {
NPC *currentNPC = &game->map_level->npcs[game->player.whichAction]; NPC *currentNPC = &game->map_level->npcs[game->player.whichAction];
/* we use the correct image as per the class of the item */ /* we use the correct image as per the class of the item */
/*TODO*/
bopti_image_t *face = &npc_male; bopti_image_t *face = &npc_male;
/* It's a NPC */
face = faces[currentNPC->face];
uint32_t dialogStart = currentNPC->dialogID; uint32_t dialogStart = currentNPC->dialogID;
/* we set this NPC to paused to avoid changing its position while /* we set this NPC to paused to avoid changing its position while
@ -158,43 +150,40 @@ void player_action(Game *game) {
currentNPC->paused = false; currentNPC->paused = false;
} }
} }
bool player_collision(Game *game, Direction direction, bool player_collision(Game *game, Direction direction,
Checkpos nomov_axis_check) { Checkpos nomov_axis_check) {
Player *player = &game->player; Player *player = &game->player;
/* Where is the tile where he will go to from his position. */ /* Where is the tile where he will go to from his position. */
char dx = one_px_mov[direction*2]; char dx = one_px_mov[direction * 2];
char dy = one_px_mov[direction*2+1]; char dy = one_px_mov[direction * 2 + 1];
if(!dx){ if(!dx) {
dx += nomov_axis_check; dx += nomov_axis_check;
}else if(!dy){ } else if(!dy) {
dy += nomov_axis_check; dy += nomov_axis_check;
} }
dx = dx*(P_WIDTH/2+1); dx = dx * (P_WIDTH / 2 + 1);
dy = dy*(P_HEIGHT/2+1); dy = dy * (P_HEIGHT / 2 + 1);
/* The tile he will go to. */ /* The tile he will go to. */
int player_tile_x = player->x+dx; int player_tile_x = player->x + dx;
int player_tile_y = player->y+dy; int player_tile_y = player->y + dy;
/* 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 (map_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 = map_get_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;
@ -206,8 +195,8 @@ bool player_collision(Game *game, Direction direction,
player->wx = worldX * PXSIZE; player->wx = worldX * PXSIZE;
player->wy = worldY * PXSIZE; player->wy = worldY * PXSIZE;
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 = map_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);
@ -218,7 +207,7 @@ bool player_collision(Game *game, Direction direction,
/* if he's on a hard tile and we need to revert the changes as */ /* 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 */ /* tile on the next side of the border is not walkable */
if(!speed){ if(!speed) {
game->map_level = backupmap; game->map_level = backupmap;
player->x = backupx; player->x = backupx;
player->y = backupy; player->y = backupy;
@ -235,45 +224,50 @@ bool player_collision(Game *game, Direction direction,
} }
} }
/* Handle a negative position differently than a positive one. */ /* Handle a negative position differently than a positive one. */
if(player_tile_x < 0) player_tile_x = player_tile_x/T_WIDTH-1; if(player_tile_x < 0)
else player_tile_x = player_tile_x/T_WIDTH; player_tile_x = player_tile_x / T_WIDTH - 1;
else
if(player_tile_y < 0) player_tile_y = player_tile_y/T_HEIGHT-1; player_tile_x = player_tile_x / T_WIDTH;
else player_tile_y = player_tile_y/T_HEIGHT;
if(player_tile_y < 0)
player_tile_y = player_tile_y / T_HEIGHT - 1;
else
player_tile_y = player_tile_y / T_HEIGHT;
int on_walkable = map_get_walkable(game, player_tile_x, player_tile_y); int on_walkable = 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;
/* if he's on a hard tile */ /* if he's on a hard tile */
if(!speed){ if(!speed) {
return true; /* He will collide with it. */ return true; /* He will collide with it. */
} }
player->speed = speed; player->speed = speed;
return false; /* He won't collide with a hard tile. */ return false; /* He won't collide with a hard tile. */
} }
void player_fix_position(Game *game, bool fix_x, bool fix_y) { void player_fix_position(Game *game, bool fix_x, bool fix_y) {
Player *player = &game->player; 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 /* 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. */ * the hard tile that he collided with. */
if(fix_x) player->x = player->x/T_WIDTH*T_WIDTH+P_WIDTH/2; 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;
if(fix_y)
player->y = player->y / T_HEIGHT * T_HEIGHT + P_HEIGHT / 2;
} }
void player_damage(Game *game, int amount) { void player_damage(Game *game, int amount) {
Player *player = &game->player; Player *player = &game->player;
player->life-=amount; player->life -= amount;
/* TODO: Let the player dye if life < 1. */ /* TODO: Let the player dye if life < 1. */
}; };

View file

@ -1,18 +1,25 @@
#ifndef PLAYER_H #ifndef PLAYER_H
#define PLAYER_H #define PLAYER_H
#include <stdbool.h>
#include "config.h" #include "config.h"
#include "game.h" #include "game.h"
#include "memory.h" #include "memory.h"
#include <stdbool.h>
typedef struct {
const char *name;
bopti_image_t *face;
} Face;
#define FACES 4
/* Structure 'Player' has been moved to game.h */ /* Structure 'Player' has been moved to game.h */
/* to avoid circular references between map.h, game.h and player.h */ /* to avoid circular references between map.h, game.h and player.h */
/* only methods propotypes are now in dedicated header files */ /* only methods propotypes are now in dedicated header files */
/* player_draw() /* player_draw()
* *
* Draws the player. This function should be called after drawing the * Draws the player. This function should be called after drawing the
* map! * map!
* game: The game struct which contains the player struct used. * game: The game struct which contains the player struct used.
@ -20,7 +27,7 @@
void player_draw(Game *game); void player_draw(Game *game);
/* player_move() /* player_move()
* *
* Move the player in a direction. * Move the player in a direction.
* game: The game struct. * game: The game struct.
* direction: The direction to move the player in. * direction: The direction to move the player in.
@ -31,7 +38,7 @@ void player_move(Game *game, Direction direction);
void player_action(Game *game); void player_action(Game *game);
/* player_collision() /* player_collision()
* *
* Check if the player is in collision with the map or a NPC. Checkpos is used * 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. * to check the axis where the player is not moving.
* game: The game struct. * game: The game struct.
@ -42,7 +49,7 @@ bool player_collision(Game *game, Direction direction,
Checkpos nomov_axis_check); Checkpos nomov_axis_check);
/* player_fix_position() /* player_fix_position()
* *
* Fix the position of the player so that he's not a bit inside of a hard block * Fix the position of the player so that he's not a bit inside of a hard block
* after a collision. * after a collision.
* game: The game struct. * game: The game struct.
@ -51,9 +58,8 @@ bool player_collision(Game *game, Direction direction,
*/ */
void player_fix_position(Game *game, bool fix_x, bool fix_y); void player_fix_position(Game *game, bool fix_x, bool fix_y);
/* player_damage() /* player_damage()
* *
* Apply damage to player * Apply damage to player
* game: The game struct. * game: The game struct.
* amount: The amount of damage to apply. * amount: The amount of damage to apply.
@ -61,4 +67,3 @@ void player_fix_position(Game *game, bool fix_x, bool fix_y);
void player_damage(Game *game, int amount); void player_damage(Game *game, int amount);
#endif #endif