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)
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(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
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)
set(SOURCES
@ -38,8 +43,12 @@ set(ASSETS
)
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_female.png
assets-cg/npc/char/npc_milkman.png
assets-cg/npc/char/npc_police.png
assets-cg/SignAction.png
assets-cg/npc/face/npc_male.png
assets-cg/npc/face/npc_female.png
@ -51,28 +60,15 @@ set(ASSETS_cg
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
assets-cg/ega64/tileset/tilesetEGA64_CG.png
)
set(ASSETS_fx
assets-fx/demo_player.png
assets-fx/npc/char/npc_male.png
assets-fx/player_male.png
assets-fx/player_female.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/INFO_Icon.png
assets-fx/player_face.png
assets-fx/font.png
# ...
@ -80,11 +76,29 @@ set(ASSETS_fx
set(ASSETS_fx_1b
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
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)
# 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)
target_compile_options(myaddin PRIVATE -Wall -Wextra -O0 -g -DCOLOREGA)
endif()
if("${COLORMODE_cg}" STREQUAL 1b)
generate_g3a(TARGET myaddin OUTPUT "RPG_1b.g3a"
NAME "RPG PC 1b" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a"
NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
endif()
if("${COLORMODE_cg}" STREQUAL 2b)
generate_g3a(TARGET myaddin OUTPUT "RPG_2b.g3a"
NAME "RPG PC 2b" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a"
NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
endif()
if("${COLORMODE_cg}" STREQUAL EGA64)

View file

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

View file

@ -1,3 +1,15 @@
npc_male.png:
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
name: demo_player_img
name: player_male_img
player_female.png:
type: bopti-image
name: player_female_img
player_face.png:
type: bopti-image
@ -9,10 +12,6 @@ player_face.png:
SignAction.png:
type: bopti-image
name: SignAction_img
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img
SGN_Icon.png:
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,
"x": 384,
"y": 192
},
{
"fileName": "level4.tmx",
"height": 192,
"width": 384,
"x": 384,
"y": 384
}
],
"onlyShowAdjacentMaps": false,

View file

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

View file

@ -1,197 +1,209 @@
#include "dialogs.h"
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <string.h>
#include "config.h"
#include "events.h"
#include "game.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_PADDING_TOP 3
extern font_t fontRPG;
#define FONT_USED fontRPG
#if GRAYMODEOK
#include <gint/gray.h>
uint32_t *lightVRAMnext, *darkVRAMnext;
uint32_t *lightVRAMcurrent, *darkVRAMcurrent;
#endif //GRAYMODEOK
#include <gint/gray.h>
uint32_t *lightVRAMnext, *darkVRAMnext;
uint32_t *lightVRAMcurrent, *darkVRAMcurrent;
#endif // GRAYMODEOK
void blit() {
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
}
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
}
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i),
bool start_anim,
bool end_anim,
bool start_anim, bool end_anim,
void for_each_screen(Game *game, unsigned int i),
int line_duration, bool update_screen, unsigned int start_i,
bool wait_continue) {
int line_duration, bool update_screen,
unsigned int start_i, bool wait_continue) {
text = events_parse_string(&game->handler, text);
dfont(&FONT_USED);
unsigned int i, n, y = PXSIZE, l = 0;
int line_max_chars, return_int = 0;
unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/
(FONT_USED.line_height+PXSIZE);
unsigned int max_lines_amount =
(BOX_HEIGHT - 2) * PXSIZE / (FONT_USED.line_height + PXSIZE);
const char *c;
if(start_anim){
if(start_anim) {
/* 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
displayed before. */
update_npcs(game);
game_draw(game);
/* 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. */
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
* the dialog drawn. */
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE,
DIMAGE_NONE);
dsubimage(4 * PXSIZE, 2 * PXSIZE, face, 0, 0, F_WIDTH,
(i - 8) * PXSIZE, DIMAGE_NONE);
blit();
while(game->frame_duration < 20) sleep();
while(game->frame_duration < 20)
sleep();
game->frame_duration = 0;
}
}else{
} else {
/* Here I'm drawing the same as if start_anim is true, but whitout
* making an animation. */
game_draw(game);
drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE);
drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK);
dimage(4*PXSIZE, 2*PXSIZE, face);
drect(0, 0, DWIDTH, BOX_HEIGHT * PXSIZE, C_WHITE);
drect(0, BOX_HEIGHT * PXSIZE, DWIDTH, (BOX_HEIGHT + 1) * PXSIZE,
C_BLACK);
dimage(4 * PXSIZE, 2 * PXSIZE, face);
if(update_screen){
if(update_screen) {
blit();
while(game->frame_duration < 20) sleep();
while(game->frame_duration < 20)
sleep();
game->frame_duration = 0;
}
}
/* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid
* drawing on the face. */
for(i=start_i;i<strlen(text);i++){
if(!l && for_each_screen) for_each_screen(game, i);
for(i = start_i; i < strlen(text); 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
* 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: */
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'. */
/* Loop from the end to the start for word wrap. */
if(*c){
if(*c) {
/* 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
* for the next line. */
if(text[i+n] == ' '){
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT,
DTEXT_TOP, text+i, n); /* Draw everything. */
* for the next line. */
if(text[i + n] == ' ') {
dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE,
DTEXT_LEFT, DTEXT_TOP, text + i,
n); /* Draw everything. */
/* 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 */
l++; /* We drew one more line. */
l++; /* We drew one more line. */
break;
}
}
}else{
} else {
/* If it is the last line of the text. */
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT,
DTEXT_TOP, text+i, line_max_chars);
y += FONT_USED.line_height+PXSIZE;
dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT,
DTEXT_TOP, text + i, line_max_chars);
y += FONT_USED.line_height + PXSIZE;
i += line_max_chars;
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.
*/
/* Make a little animation :). */
if(update_screen) blit();
while(game->frame_duration < line_duration) sleep();
if(update_screen)
blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0;
/* 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 :). */
if(update_screen) blit();
if(l>=max_lines_amount-1){
if(update_screen)
blit();
if(l >= max_lines_amount - 1) {
/* If we drew one entire screen. */
/* Wait that the SHIFT key is pressed if we should. */
if(wait_continue){
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
/* 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);
/* Reset y and l. */
y = PXSIZE;
l = 0;
}
else{
} else {
/* 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;
}
}
if(l<max_lines_amount-1){
if(l < max_lines_amount - 1) {
/* If we have not filled everthing with text at the end. */
/* Make a little animation :). */
if(update_screen) blit();
while(game->frame_duration < line_duration) sleep();
if(update_screen)
blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0;
/* 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. */
if(update_screen) blit();
if(wait_continue){
if(update_screen)
blit();
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT){
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
}
if(call_before_end) return_int = call_before_end(game, i);
if(end_anim){
if(call_before_end)
return_int = call_before_end(game, i);
if(end_anim) {
/* 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. */
update_npcs(game);
game_draw(game);
drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE);
drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK);
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE,
DIMAGE_NONE);
drect(0, 0, DWIDTH, i * PXSIZE, C_WHITE);
drect(0, i * PXSIZE, DWIDTH, (i + 1) * PXSIZE, C_BLACK);
dsubimage(4 * PXSIZE, 2 * PXSIZE, face, 0, 0, F_WIDTH,
(i - 8) * PXSIZE, DIMAGE_NONE);
dupdate();
while(game->frame_duration < 20) sleep();
while(game->frame_duration < 20)
sleep();
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) {
/* Run showtext_opt with some default values. It makes it easier to use in
* simple dialogs. */
dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100,
true, 0, true);
dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL,
100, true, 0, true);
}
/* Some variables and pointers used to get some arguments passed in
* showtext_dialog_ask in _choice_call_before_end. */
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
* 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;
}
int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
int i, key;
/* 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 */
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE);
drect(0, (BOX_HEIGHT + 1) * PXSIZE + 1, i * (DWIDTH / 8),
(BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, C_WHITE);
/* Draw a thick border on the right of the box. */
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1,
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK);
drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
i * (DWIDTH / 8) + PXSIZE - 1,
(BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
/* Draw a thick border on the bottom of the box. */
drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8),
(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);
/* Show everyting on screen. */
blit();
/* 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;
}
/* 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_height: The height of the arrow used to show which item is choosen.
* 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);
/* Add the character spacing of the font to it. */
arrow_width += FONT_USED.char_spacing;
for(i=0;i<_choices_amount;i++){
dtext(i*choice_size+arrow_width+PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK,
_choices+pos);
pos += strlen(_choices+pos)+1;
for(i = 0; i < _choices_amount; i++) {
dtext(i * choice_size + arrow_width + PXSIZE,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
_choices + pos);
pos += strlen(_choices + pos) + 1;
}
do{
do {
/* Display the diffrent choices. */
for(i=0;i<_choices_amount;i++){
if(i == selected) dtext(i*choice_size+PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE,
C_BLACK, ">");
for(i = 0; i < _choices_amount; i++) {
if(i == selected)
dtext(i * choice_size + PXSIZE,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
">");
}
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
* the first possible choice. */
if(key == KEY_LEFT && selected > 0){
if(key == KEY_LEFT && selected > 0) {
/* Remove the old arrow. */
drect(selected*choice_size+PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE,
selected*choice_size+PXSIZE+arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height,
drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE);
/* Move the selection arrow and update the selected item. */
selected--;
}
/* If the player pressed the right arrow key and has not already
* 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. */
drect(selected*choice_size+PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE,
selected*choice_size+PXSIZE+arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height,
drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE);
/* Move the selection arrow and update the selected item. */
selected++;
}
/* If the user has not validated his choice by pressing SHIFT, we loop one
* more time. */
}while(key != KEY_SHIFT);
/* If the user has not validated his choice by pressing SHIFT, we loop
* one more time. */
} while(key != KEY_SHIFT);
/* 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 */
update_npcs(game);
game_draw(game);
dialogs_text_opt(game, _face, _text, NULL, false, false, NULL, 0, false,
_i, false);
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE);
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1,
(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);
drect(0, (BOX_HEIGHT + 1) * PXSIZE + 1, i * (DWIDTH / 8),
(BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, C_WHITE);
drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
i * (DWIDTH / 8) + PXSIZE - 1,
(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();
while(game->frame_duration < 20) sleep();
while(game->frame_duration < 20)
sleep();
game->frame_duration = 0;
}
/* 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);
}
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber) {
Dialog *currentDiag = &game->map_level->dialogs[dialogNumber];
uint32_t dialogNumber) {
Dialog *currentDiag = &game->map_level->dialogs[dialogNumber];
/* we collect the information */
char *text = currentDiag->dialog;
/* we collect the information */
char *text = currentDiag->dialog;
char *choices = currentDiag->choices ;
char *conclusion1 = currentDiag->conclusion1;
int next1 = currentDiag->next1;
char *conclusion2 = currentDiag->conclusion2;
int next2 = currentDiag->next2;
int nextOther = currentDiag->nextOther;
int isQuestion = currentDiag->isQuestion;
char *choices = currentDiag->choices;
char *conclusion1 = currentDiag->conclusion1;
int next1 = currentDiag->next1;
char *conclusion2 = currentDiag->conclusion2;
int next2 = currentDiag->next2;
int nextOther = currentDiag->nextOther;
int isQuestion = currentDiag->isQuestion;
/* we treat the action - i.e. we show a dialog */
if (isQuestion == 1){
/* we have to manage a question */
int answer = dialogs_ask(game, face, text, true, true,
choices, 2, 0);
/* we treat the action - i.e. we show a dialog */
if(isQuestion == 1) {
/* we have to manage a question */
int answer = dialogs_ask(game, face, text, true, true, choices, 2, 0);
/* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */
/* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */
if(answer==0){
dialogs_text(game, face, conclusion1, true, true);
if (next1!=-1) dialogs_initiate_sequence(game, face, next1);
}else{
dialogs_text(game, face, conclusion2, true, true);
if (next2!=-1) dialogs_initiate_sequence(game, face, next2);
}
}else{
dialogs_text(game, face, text, true, true);
if (nextOther!=-1) dialogs_initiate_sequence(game, face, nextOther);
}
if(answer == 0) {
dialogs_text(game, face, conclusion1, true, true);
if(next1 != -1)
dialogs_initiate_sequence(game, face, next1);
} else {
dialogs_text(game, face, conclusion2, true, true);
if(next2 != -1)
dialogs_initiate_sequence(game, face, next2);
}
} 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
#define DIALOG_H
#include <gint/display.h>
#include <string.h>
#include "config.h"
#include "game.h"
#include "map.h"
#include "config.h"
#include <gint/display.h>
#include <string.h>
/* dialogs_text_opt()
*
@ -37,8 +38,7 @@
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i),
bool start_anim,
bool end_anim,
bool start_anim, bool end_anim,
void for_each_screen(Game *game, unsigned int i),
int line_duration, bool update_screen,
unsigned int start_i, bool wait_continue);

View file

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

View file

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

View file

@ -1,17 +1,14 @@
#include "game.h"
#include "map.h"
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <gint/display.h>
#include "map.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;
@ -87,13 +84,13 @@ void game_logic(Game *game) {
void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */
if(game->player.canDoSomething==false) return;
if(game->player.canDoSomething == false)
return;
/* else we draw a small indicator on the screen */
dimage(5, 5, &SignAction_img);
}
void game_draw(Game *game) {
/* Draw everything. */
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 */
if(keydown(KEY_LEFT)) player_move(game, D_LEFT);
if(keydown(KEY_RIGHT)) player_move(game, D_RIGHT);
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_LEFT))
player_move(game, D_LEFT);
if(keydown(KEY_RIGHT))
player_move(game, D_RIGHT);
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 */
#if DEBUGMODE
@ -138,12 +149,13 @@ void game_get_inputs(Game *game) {
}
#endif
/* if USB is enabled - keybinding for screencapture */
#if USB_FEATURE
if(keydown(KEY_7)) game->screenshot = true;
if(keydown(KEY_8)) game->record = !game->record;
if(keydown(KEY_7))
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
#define GAME_H
#include "events.h"
#include <gint/display.h>
#include <stdint.h>
#include "events.h"
/* The direction where the player is going to. */
typedef enum {
D_UP,
D_DOWN,
D_LEFT,
D_RIGHT
} Direction;
typedef enum { D_UP, D_DOWN, D_LEFT, D_RIGHT } Direction;
typedef enum {
P_LEFTUP = -1,
@ -32,25 +24,24 @@ typedef struct
/* Struct that define player parameters */
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 */
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. */
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 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 */
bool canDoSomething;
/* indicates which data are relevant to the current action in the */
/* extradata layer of the map */
int32_t whichAction;
int32_t whichAction;
/* the player is doing something */
bool isDoingAction;
/* the player is interacting with a NPC */
bool isInteractingWithNPC;
bool is_male;
} Player;
typedef struct {
uint32_t ID;
/* data to be shown in the dialog*/
@ -68,8 +59,8 @@ typedef struct {
int32_t nextOther;
} Dialog;
typedef struct
{
typedef struct {
/* position of the item */
uint32_t x;
uint32_t y;
/*id of it's icon*/
@ -82,7 +73,6 @@ typedef struct
uint32_t dialogID;
/*if the dialog is interactive or not*/
uint32_t needAction;
} Sign;
typedef struct
@ -93,7 +83,7 @@ typedef struct
/* initial coordinates of the NPC (needed to get absolute coordinates of path) */
uint32_t x;
uint32_t y;
/* id of it's face*/
/* id of it's face */
uint16_t face;
uint8_t paused;
@ -120,17 +110,14 @@ typedef struct
uint8_t hostile_to_group;
uint16_t __padding;
} NPC;
typedef struct{
Collider collider;
/*if the portal tps to an interior or exterior map*/
uint16_t tp_interior;
/*Id of the interior/exterior map to transport the player to*/
uint16_t tp_to;
} Portal;
typedef struct {
@ -172,14 +159,12 @@ typedef struct {
} Map;
/* 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
* the world. */
typedef struct {
Map *map_level; /* The level that the player is currently playing */
Player player; /* The player data. */
Map *map_level; /* The level that the player is currently playing */
Player player; /* The player data. */
EventHandler handler; /* The event handler (see events.h). */
/* Some global variables */
/* Set to true when asked for exit */
@ -210,7 +195,7 @@ void game_logic(Game *game);
void game_draw(Game *game);
/* game_render_indicator()
*
*
* This render a small sign on the upper left corner of the screen
* if the player can do an action
* game: The game struct.
@ -218,11 +203,10 @@ void game_draw(Game *game);
void game_render_indicator(Game *game);
/* game_get_inputs()
*
*
* Handle key presses.
* game: The game struct.
*/
void game_get_inputs(Game *game);
#endif

View file

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

165
src/map.c
View file

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

View file

@ -1,33 +1,29 @@
#ifndef MAP_H
#define MAP_H
#define BACKGROUND 0
#define FOREGROUND 1
#define MAP_OUTSIDE -2 /* Returned by get_tile_at_pos if the point is outside of
* the map. */
#define MAP_OUTSIDE \
-2 /* Returned by get_tile_at_pos if the point is outside of \
* the map. */
#include "game.h"
#include "player.h"
/* Structure 'Map' has been moved to game.h */
/* to avoid circular references between map.h, game.h and player.h */
/* only methods propotypes are now in dedicated header files */
/* map_render()
*
*
* Draws the map map on the entire screen to be viewed by the player player.
* game: The game struct.
*/
void map_render(Game *game);
/* map_render_by_layer()
*
*
* Draws the map layer on the entire screen to be viewed by the player player.
* game: The game struct.
* layer: The layer to render.
@ -35,7 +31,7 @@ void map_render(Game *game);
void map_render_by_layer(Game *game, int layer);
/* map_get_tile()
*
*
* Get the tile at (x, y) of the map map. If the tile is located outside of the
* screen, MAP_OUTSIDE is returned.
* game: The game struct.
@ -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);
/* map_get_walkable()
*
*
* Returns what is in the walkable layer at (x, y).
* game: The game struct.
* 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);
/* map_get_for_coordinates()
*
*
* return the pointer to the map containing the given position.
* game: The game struct.
* x: The coordinates to look at.
* y: The coordinates to look at.
*/
Map* map_get_for_coordinates(Game *game, int x, int y );
Map *map_get_for_coordinates(Game *game, int x, int y);
#endif

View file

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

View file

@ -2,11 +2,10 @@
bool memory_is_in(short int *array, short int array_length, short int item) {
short int i;
for(i=0;i<array_length;i++){
if(array[i] == item){
for(i = 0; i < array_length; i++) {
if(array[i] == item) {
return true;
}
}
return false;
}

View file

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

282
src/npc.c
View file

@ -1,29 +1,27 @@
#include "npc.h"
#include "config.h"
#include "dialogs.h"
#include "game.h"
#include "map.h"
#include "config.h"
#include <gint/display.h>
#include <gint/keyboard.h> /*debug*/
#include <math.h>
#include <stdint.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;
//uint32_t nbNPC = 0;
float length( float x, float y )
{
return sqrtf( x*x+y*y );
}
float length(float x, float y) { return sqrtf(x * x + y * y); }
int npc_clear_path(NPC *npc)
{
int npc_clear_path(NPC *npc) {
npc->currentPoint = 0;
npc->hasPath = 0;
npc->path_length = 0;
@ -31,47 +29,46 @@ int npc_clear_path(NPC *npc)
free(npc->ypath);
npc->xpath = 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;
}
int npc_append_path(uint16_t x, uint16_t y, NPC *npc)
{
npc->xpath = realloc(npc->xpath, npc->path_length*2+2);
npc->ypath = realloc(npc->ypath, npc->path_length*2+2);
if(npc->xpath == NULL || npc->ypath == NULL) return 1;
int npc_append_path(uint16_t x, uint16_t y, NPC *npc) {
npc->xpath = realloc(npc->xpath, npc->path_length * 2 + 2);
npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
if(npc->xpath == NULL || npc->ypath == NULL)
return 1;
npc->path_length++;
npc->xpath[npc->path_length-1] = x - npc->x;
npc->ypath[npc->path_length-1] = y - npc->y;
npc->xpath[npc->path_length - 1] = x - npc->x;
npc->ypath[npc->path_length - 1] = y - npc->y;
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(gscore);
free(fscore);
}
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
int16_t dest, NPC *npc)
{
if(npc_clear_path(npc)) goto as_recons_fail;
int16_t dest, NPC *npc) {
if(npc_clear_path(npc))
goto as_recons_fail;
int16_t next = came_from[dest];
unsigned int i;
for(i = 0; i < 64; i++)
{
if(npc_append_path((next%w)*T_WIDTH,(next/h)*T_HEIGHT, npc))
{
for(i = 0; i < 64; i++) {
if(npc_append_path((next % w) * T_WIDTH, (next / h) * T_HEIGHT, npc)) {
goto as_recons_fail;
}
next = came_from[next];
if(next == spos){
if(npc_append_path((spos%w)*T_WIDTH,(spos/h)*T_HEIGHT, npc))
if(next == spos) {
if(npc_append_path((spos % w) * T_WIDTH, (spos / h) * T_HEIGHT,
npc))
goto as_recons_fail;
break;
}
@ -79,16 +76,15 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
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];
ty = npc->ypath[i];
npc->xpath[i] = npc->xpath[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] = ty;
npc->xpath[i] = npc->xpath[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] = ty;
}
free(came_from);
@ -97,95 +93,103 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
return 0;
as_recons_fail:
as_recons_fail:
free(came_from);
return 1;
}
//Returns non zero error code on failure
//Custom a* implemetation
//Unoptimized, may become an issue
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc)
{
// Returns non zero error code on failure
// Custom a* implemetation
// Unoptimized, may become an issue
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
int32_t i, j;
int32_t w = full_map->w;
int32_t h = full_map->h;
int32_t x = floor(npc->curx)/T_WIDTH;
int32_t y = floor(npc->cury)/T_HEIGHT;
int32_t x = floor(npc->curx) / T_WIDTH;
int32_t y = floor(npc->cury) / T_HEIGHT;
dest_x /= T_WIDTH;
dest_y /= T_HEIGHT;
int32_t spos = y*w+x;
int32_t spos = y * w + x;
uint8_t *map = full_map->walkable;
if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h) return 2;
if(map[spos]) return 2;
if(map[dest_y*w+dest_x]) return 2;
if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h)
return 2;
if(map[spos])
return 2;
if(map[dest_y * w + dest_x])
return 2;
npc_clear_path(npc);
uint8_t *visited = malloc(w*h);
for(i=0; i<w*h; i++) visited[i] = 1;
uint8_t *visited = malloc(w * h);
for(i = 0; i < w * h; i++)
visited[i] = 1;
visited[spos] = 0;
int16_t *came_from = malloc(w*h*2);
for(i=0; i<w*h; i++) came_from[i] = -1;
int16_t *came_from = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
came_from[i] = -1;
uint8_t *gscore = malloc(w*h*2);
for(i=0; i<w*h; i++) gscore[i] = 255;
uint8_t *gscore = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
gscore[i] = 255;
gscore[spos] = 0;
uint8_t *fscore = malloc(w*h*2);
for(i=0; i<w*h; i++) fscore[i] = 255;
fscore[spos] = length(dest_x-x, dest_y-y);
uint8_t *fscore = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
fscore[i] = 255;
fscore[spos] = length(dest_x - x, dest_y - y);
uint8_t bscore;
int32_t bx = x;
int32_t by = y;
for(int iter=0; iter < 64; iter++)
{
for(int iter = 0; iter < 64; iter++) {
bscore = 255;
//Cheapest known tile
for(i = 0; i <= w*h; i++)
{
if(visited[i]) continue;
if(map[i] == 1) continue;
if(fscore[i] > bscore) continue;
bx = i%w;
by = i/w;
// Cheapest known tile
for(i = 0; i <= w * h; i++) {
if(visited[i])
continue;
if(map[i] == 1)
continue;
if(fscore[i] > bscore)
continue;
bx = i % w;
by = i / w;
bscore = fscore[i];
}
if(bx == dest_x && by == dest_y)
{
if(bx == dest_x && by == dest_y) {
as_clean(visited, gscore, fscore);
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;
for(i = bx-1; i < bx+2; i++)
{
if(i > w) break;
for(j = by-1; j < by+2; j++)
{
if(j > h) break;
if(map[j*w+i] == 1) continue;
if(i == bx && j == by) continue;
att_score = gscore[by*w+bx] + round(length(bx-i,by-j));
if(att_score < gscore[j*w+i])
{
came_from[j*w+i] = by*w+bx;
gscore[j*w+i] = att_score;
fscore[j*w+i] = att_score + round(
length(dest_x-i, dest_y-j));
if(visited[j*w+i]) visited[j*w+i] = 0;
for(i = bx - 1; i < bx + 2; i++) {
if(i > w)
break;
for(j = by - 1; j < by + 2; j++) {
if(j > h)
break;
if(map[j * w + i] == 1)
continue;
if(i == bx && j == by)
continue;
att_score = gscore[by * w + bx] + round(length(bx - i, by - j));
if(att_score < gscore[j * w + i]) {
came_from[j * w + i] = by * w + bx;
gscore[j * w + i] = att_score;
fscore[j * w + i] =
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;
}
/*The following functions need to be redone*/
/*
NPC *npc_create()
{
//Use temp pointer to avoid breaking the whole npcRPG on failure
void *temp = realloc(npcRPG, (nbNPC+1)*sizeof(NPC));
if(temp == NULL) return NULL;
/*NPC *npc_create() {
// Use temp pointer to avoid breaking the whole npcRPG on failure
void *temp = realloc(npcRPG, (nbNPC + 1) * sizeof(NPC));
if(temp == NULL)
return NULL;
npcRPG = temp;
nbNPC++;
NPC *npc = &npcRPG[nbNPC-1];
NPC *npc = &npcRPG[nbNPC - 1];
npc->xpath = malloc(2);
npc->ypath = malloc(2);
return npc;
}
}*/
void npc_remove(NPC *npc)
{
uint32_t pos = ((uint32_t)npc - (uint32_t)npcRPG)/sizeof(NPC);
if(pos > nbNPC-1) return;
if(pos == nbNPC-1)
{
/*void npc_remove(NPC *npc) {
uint32_t pos = ((uint32_t)npc - (uint32_t)npcRPG) / sizeof(NPC);
if(pos > nbNPC - 1)
return;
if(pos == nbNPC - 1) {
nbNPC--;
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
@ -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 (!npc->hasPath || npc->paused==true) return;
if(!npc->hasPath || npc->paused == true)
return;
float vecX = (float) (npc->xpath[ npc->currentPoint ] +
npc->x) - npc->curx;
float vecY = (float) (npc->ypath[ npc->currentPoint ] +
npc->y) - npc->cury;
float vecX = (float)(npc->xpath[npc->currentPoint] + npc->x) - npc->curx;
float vecY = (float)(npc->ypath[npc->currentPoint] + npc->y) - npc->cury;
float vecN = length(vecX, vecY);
if (vecN>0.5f)
{
vecX /= vecN*2.0;
vecY /= vecN*2.0;
}
else
{
if(vecN > 0.5f) {
vecX /= vecN * 2.0;
vecY /= vecN * 2.0;
} else {
npc->currentPoint++;
npc->currentPoint = npc->currentPoint % npc->path_length;
}
npc->curx += vecX;
npc->cury += vecY;
}
/*void reload_npc(Game *game)
{
if (npcRPG!=NULL)
{
/*void reload_npc(Game *game) {
if(npcRPG != NULL) {
free(npcRPG);
npcRPG = NULL;
}
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];
if (strcmp(Data->type, "NPC")==0) //the current data is a NPC
if(strcmp(Data->type, "NPC") == 0)
{
nbNPC++;
}
}
npcRPG = (NPC*) malloc( nbNPC * sizeof(NPC) );
if(npcRPG == NULL) return;
int currentNPC=0;
npcRPG = (NPC *)malloc(nbNPC * sizeof(NPC));
if(npcRPG == NULL)
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];
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].cury = (float) Data->y;
npcRPG[currentNPC].curx = (float)Data->x;
npcRPG[currentNPC].cury = (float)Data->y;
npcRPG[currentNPC].x = Data->x;
npcRPG[currentNPC].y = Data->y;
npcRPG[currentNPC].dialogID = Data->dialogID;
npcRPG[currentNPC].currentPoint = 1;
npcRPG[currentNPC].currentPoint = 1;
npcRPG[currentNPC].hasPath = Data->hasPath;
npcRPG[currentNPC].path_length = Data->path_length;
npcRPG[currentNPC].xpath = Data->xpath;
@ -311,6 +301,13 @@ void update_npc(NPC *npc)
void npc_draw(Game *game) {
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++)
{
@ -341,8 +338,9 @@ void npc_draw(Game *game) {
}
#endif // DEBUGMODE
int16_t delX=((int16_t) (Data->curx * PXSIZE))-(int16_t) pl->wx;
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);
int16_t delX = ((int16_t)(Data->curx * PXSIZE)) - (int16_t)pl->wx;
int16_t delY = ((int16_t)(Data->cury * PXSIZE)) - (int16_t)pl->wy;
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
#define NPC_H
#include <stdbool.h>
#include <stdint.h>
#include "game.h"
#include "memory.h"
enum
{
#include <stdbool.h>
#include <stdint.h>
enum {
NPC_NONE = 0,
NPC_FRIENDLY = 1, //The player's team
NPC_HOSTILE = 2, //to the player
NPC_FRIENDLY = 1, // The player's team
NPC_HOSTILE = 2, // to the player
NPC_ALL = 3
};
//Frees then malloc()s a new path to npc
//Useful if you want to safely edit a path
// Frees then malloc()s a new path to npc
// Useful if you want to safely edit a path
int npc_clear_path(NPC *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
// 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
int npc_append_path(uint16_t x, uint16_t y, NPC *npc);
//Clears the NPCs path and creates a new one going to dest,
//avoiding non-walkable tiles
//Returns non-zero on failure
// Clears the NPCs path and creates a new one going to dest,
// avoiding non-walkable tiles
// Returns non-zero on failure
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
//Returns NULL on failure
// realloc()s npcRPG to adequate size and returns a pointer to the new element
// Returns NULL on failure
NPC *npc_create();
//Pops the NPC from npcRPG
void npc_remove(NPC *npc);*/
// Pops the NPC from npcRPG
void npc_remove(NPC *npc);
/* Draws the player player. This function should be called after drawing the
* map! */
@ -50,4 +47,3 @@ void update_npc(NPC *npc);
void reload_npc(Game *game);
#endif

View file

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

View file

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