Merge remote-tracking branch 'origin/dev'

This commit is contained in:
mibi88 2024-08-01 11:02:17 +02:00
commit b5759bd95d
102 changed files with 2392 additions and 1516 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

2
.gitignore vendored
View file

@ -2,6 +2,7 @@
/build-fx
/build-cg
/build-cg-push
/build-fxg3a
/*.g1a
/*.g3a
@ -13,5 +14,4 @@ __pycache__/
*.sublime-workspace
.vscode
level*.json
tilesetnpp.json

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "assets/tinytiled"]
path = assets/tinytiled
url = https://git.planet-casio.com/mibi88/tinytiled
[submodule "assets/--force"]
path = assets/--force
url = https://git.planet-casio.com/mibi88/tinytiled

View file

@ -4,18 +4,24 @@
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)
include(Fxconv)
find_package(Gint 2.9 REQUIRED)
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
@ -26,44 +32,53 @@ set(SOURCES
src/game.c
src/dialogs.c
src/npc.c
src/events.c
# ...
)
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
set(ASSETS
assets/WorldRPG.world
assets/level0_dialogs.json
assets/level1_dialogs.json
assets/level2_dialogs.json
assets/level3_dialogs.json
assets/level4_dialogs.json
assets/level0.tmx
assets/level1.tmx
assets/level2.tmx
assets/level3.tmx
assets/level4.tmx
assets/interior1_0_dialogs.json
assets/interior1_0.tmx
# ...
)
set(ASSETS_cg
assets-cg/demo_player.png
assets-cg/demo_PNJ.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_Icon.png
assets-cg/npc/face/npc_male.png
assets-cg/npc/face/npc_female.png
assets-cg/npc/face/npc_milkman.png
assets-cg/npc/face/npc_police.png
assets-cg/SGN_Icon.png
assets-cg/INFO_Icon.png
assets-cg/player_face.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
assets-cg/ega64/tileset/tilesetEGA64_CG.png
)
set(ASSETS_fx
assets-fx/demo_player.png
assets-fx/demo_PNJ.png
assets-fx/player_male.png
assets-fx/player_female.png
assets-fx/SignAction.png
assets-fx/NPC_Icon.png
assets-fx/SGN_Icon.png
assets-fx/INFO_Icon.png
assets-fx/player_face.png
assets-fx/font.png
# ...
@ -71,11 +86,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
# ...
)
@ -85,29 +118,8 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} )
endif()
# fx colormode
if("${COLORMODE_fx}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT)
endif()
# cg colormode
if("${COLORMODE_cg}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT)
endif()
if("${COLORMODE_cg}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT)
endif()
if("${COLORMODE_cg}" STREQUAL EGA64)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOREGA)
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
endif()
target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage)
@ -115,6 +127,14 @@ target_link_libraries(myaddin LibProf::LibProf Gint::Gint)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
# fx colormode
if("${COLORMODE_fx}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR1BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR2BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 1b)
generate_g1a(TARGET myaddin OUTPUT "RPG_1b.g1a"
@ -127,16 +147,21 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
endif()
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
# cg colormode
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)
@ -144,4 +169,19 @@ elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
NAME "RPG PC EGA" ICONS assets-cg/ega64/icon-uns-ega64.png assets-cg/ega64/icon-sel-ega64.png)
endif()
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
if("${COLORMODE_fx}" STREQUAL 1b)
generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a"
NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a"
NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
endif()
endif()

26
PROJECT_STRUCTURE.md Normal file
View file

@ -0,0 +1,26 @@
# Project structure
* `assets` contains the tiled maps, and the tiled map converters.
* `assets-cg` contains the assets for cg calculators like the cg-50.
* `assets-fx` contains the assets for monochrome calculators.
* `captures` contains screenshots.
* `src` This folder contains the source code.
* `config.h` This header file contains defines for the size of various
things on screen, like the size of a tile in the tilemap, the size of the
dialog box, etc.
* `dialogs.c` and `dialogs.h` contain various functions to display dialogs
and also let the user respond.
* `events.c` and `events.h` parse tags in the messages that are displayed
using the dialogs procedures to modify variables (and soon, call
procedures).
* `game.c` and `game.h` handles the rendering, the input, etc.
* `main.c` handles the USB connection and the gint gray rendering, for 2bpp
rendering on monochrome calculators. Contains the mainloop. Also contains
code to display debug informations.
* `map.c` and `map.h` contain code to render, get a tile in the map, see if
the tile is walkable, etc.
* `mapdata.h` contains the available maps.
* `memory.c` and `memory.h` procedures to handle arrays (currently: search
in an array of short ints).
* `npc.c` and `npc.h` npc rendering and movement (and soon pathfinding).
* `player.c` and `player.h` handle the player movement, collision, etc.

View file

@ -2,7 +2,12 @@
Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html)
## Avencement du projet
## Contribuer!
Style du code [STYLE.md](STYLE.md).
Structure du projet [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md).
## Avancement du projet
A ce stade, on a déjà implémenté :
@ -13,12 +18,13 @@ A ce stade, on a déjà implémenté :
- [x] Multiple cartes avec importation automatique des fichiers `world` issus de Tiled
- [x] Carte Multilayer (Background, Foreground + accessibilité / Dommages) avec transparence du calque Foreground
- [x] Personnage
- [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés)
- [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés + limite d'un kibibyte)
- [x] Fontes de caractères
- [x] Interaction
- [ ] NPC
- [x] Changement de map durant le jeu
- [ ] Système d'événements
- [ ] Pathfinding
## Crédits

44
README_en.md Normal file
View file

@ -0,0 +1,44 @@
# Planet Casio Collaborative Project
(maybe I should've used google translate)
More informations can be found here (in french):
[Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html)
## Contribute!
Style guidelines [STYLE.md](STYLE.md).
Project structure [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md).
## Current state
What we've implemented so far:
- [x] Screenshots via USB
- [x] Displaying the current map at the players position
- [x] Handling keyboard inputs
- [x] Handling collisions.
- [x] Multiple maps with automatic `world` files import (made with Tiled)
- [x] Multilayer map (Background, Foreground + accessibility / damage) with
foreground layer transparency.
- [x] Player character.
- [x] Dialogs from external `json` files (line jumps and words bigger than the
screen are unsupported + 1 kibibyte per message limit)
- [x] Font
- [x] Interaction
- [ ] NPC
- [x] Changing map in game.
- [ ] Event system
- [ ] Pathfinding
## Credits
The tiles are from Game Boy Top-down RPG Fantasy Tileset (FREE)
"Background Assets by Gumpy Function (gumpyfunction.itch.io)"
[Tiles Background Assets by Gumpy Function](https://gumpyfunction.itch.io/game-boy-rpg-fantasy-tileset-free)
Converted to greyscale with gimp.
1-bit (black and white) version by Shadow15510
CG (palette EGA64) color version by Fcalva

14
STYLE.md Normal file
View file

@ -0,0 +1,14 @@
# Style guidelines in Collab RPG
(Mibi88) Fcalva, SlyVTT: What do you think of this?
Variables names in sneak_case.
Name your procedures as following: `filename_whatitdoes`.
The procedures are documented using sphinx.
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: 7.1 KiB

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.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

BIN
assets-cg/ega64/tileset/tilesetEGA64_CG.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

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

@ -0,0 +1,15 @@
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: 221 B

Binary file not shown.

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

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: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Binary file not shown.

After

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

Binary file not shown.

Binary file not shown.

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

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: 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

Binary file not shown.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
assets-fx/2bpp_palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

View file

@ -1,10 +1,9 @@
demo_player.png:
player_male.png:
type: bopti-image
name: demo_player_img
demo_PNJ.png:
name: player_male_img
player_female.png:
type: bopti-image
name: demo_PNJ_img
name: player_female_img
player_face.png:
type: bopti-image
@ -13,14 +12,6 @@ player_face.png:
SignAction.png:
type: bopti-image
name: SignAction_img
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img
NPC_Icon.png:
type: bopti-image
name: NPC_Icon_img
SGN_Icon.png:
type: bopti-image
@ -34,4 +25,4 @@ font.png:
grid.padding: 1
grid.border: 0
proportional: true
height: 5
height: 5

BIN
assets-fx/player_female.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

BIN
assets-fx/player_male.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

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,405 +1,392 @@
from random import randint
from PIL import Image
import fxconv
"""
This is the main converter script. It uses the tiled.py script to handle the
tiled maps.
We're trying to follow the PEP, so please read PEP 8 (if you haven't already):
https://peps.python.org/pep-0008/, so please write variable names in sneak_case
and class names in PascalCase.
To improve the lisibility of this code, please document your methods, add
comments (yes, it's hard to add the right amount of comments), and add type
hints, to avoid bugs and make it easy to understand how to use them.
To document your methods, you should read PEP 257:
https://peps.python.org/pep-0257/.
Thanks,
Mibi88
"""
import xml.etree.ElementTree as ET
import json
import pathlib
import csv
import os
def convert(input, output, params, target):
if params["custom-type"] == "map":
print("ERROR : Asset ", params["name"], " has legacy type map")
return 1
elif params["custom-type"] == "world":
convert_world(input, output, params, target)
return 0
elif params["custom-type"] == "custom-image":
convert_custom_image(input, output, params, target)
return 0
elif params["custom-type"] == "font":
convert_font(input, output, params, target)
return 0
elif params["custom-type"] == "dialogs":
print("ERROR : Asset ", params["name"], " has legacy type dialog")
#convert_dialogs(input, output, params, target)
return 0
else:
return 1
def convert_world(input, output, params, target):
print( "WE ARE COMPUTING THE WORLD", input )
data = json.load(open(input, "r"))
nbMaps = ["fileName" in i for i in data["maps"]].count(True)
print( "We have to treat ", nbMaps, " maps")
print( "So let's go ... ")
structWorld = fxconv.Structure()
#structExtra = fxconv.Structure()
for i in range(nbMaps):
nameMap = data["maps"][i]["fileName"].replace(".tmx","")
nameMapFree = nameMap.split("/")[-1]
#count the number of "back" (cd ..) to locate the map on the computer
nbRetour = nameMap.count("..")+1
#create the map absolute path
nameTMX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".tmx"
nameJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json"
commandline = 'tiled --export-map json ' + nameTMX + ' ' + nameJSON
print( "TILED COMMAND LINE FOR MAPS : ", commandline )
os.system( commandline )
mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json"
print("Map ", i , " name : ", mapPath )
xmin = data["maps"][i]["x"]
print( "xmin = ", xmin )
ymin = data["maps"][i]["y"]
print( "ymin = ", ymin )
xmax = data["maps"][i]["x"] + data["maps"][i]["width"]
print( "xmax = ", xmax )
ymax = data["maps"][i]["y"] + data["maps"][i]["height"]
print( "ymax = ", ymax )
map = get_tile_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax)
print( "Map = ", map )
structWorld += fxconv.ptr( map )
structWorld += fxconv.u32(0)
#generate !
fxconv.elf(structWorld, output, "_" + params["name"], **target)
def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
print( "WE ARE COMPUTING THE MAP : ", input )
data = json.load(open(input, "r"))
#find the tileset in use. it's a relative path (like ../tileset.tsx)
nameTileset = data["tilesets"][0]["source"].replace(".tsx","")
print(nameTileset)
#the name of the tileset without the .something
nameTilesetFree = nameTileset.split("/")[-1]
#count the number of "back" (cd ..) to locate the tileset on the computer
nbRetour = nameTileset.count("..")+1
#create the tileset absolute path
tilesetTSX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".tsx"
tilesetJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".json"
commandline = 'tiled --export-tileset json ' + tilesetTSX + ' ' + tilesetJSON
print( "TILED COMMAND LINE FOR TILESET : ", commandline )
os.system( commandline )
tileset = open(tilesetJSON, "r")
data_tileset = json.load(tileset)
tileset_size = data_tileset.get("columns")
tileset.close()
#find the ID of the first tile in the walkable tileset ()
indexWalkable = data["tilesets"][1]["firstgid"]
print(indexWalkable)
#Extract from the json the width, height
w, h = data["width"], data["height"]
#nbTileLayer is the number of "true" layers (without ObjectsLayer)
nbTilelayer = ["data" in i for i in data["layers"]].count(True) - 1
print( nbTilelayer)
#index of the various layers (may change from one map to another)
layer_walkable = 0
layer_foreground = 0
layer_background = 0
#create the structure of the map
structMap = fxconv.Structure()
structMap += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(nbTilelayer)
structMap += fxconv.u32(tileset_size)
structMap += fxconv.u32(xmin) + fxconv.u32(ymin) + fxconv.u32(xmax) + fxconv.u32(ymax)
structMap += fxconv.ref(f"img_{nameTilesetFree}")
#extraction of the data contained in the layer "Walkable" of the map
for i in range(nbTilelayer+1):
datavalid = data["layers"][i]
if datavalid["name"]=="Walkable":
layer_walkable = i
print( "Walkable Tile Data in layer : ", layer_walkable)
break
elif i==nbTilelayer:
print( "ERROR : No Walkable layer data !!!" )
walk_data = bytes()
layer = data["layers"][layer_walkable]
for tile in layer["data"]:
#print( tile )
if tile == 0: walk_data += fxconv.u8(tile) #if walkable_data = 0 then it is a blanck cell so nothing to change
else : walk_data += fxconv.u8(tile-indexWalkable) #if !=0 than we need to shift the tile number by considering the first tileID (given by indexwalkable)
structMap += fxconv.ptr(walk_data)
nbextra = 0
extradata = fxconv.Structure()
nbextra, extradata = get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax)
if (nbextra==0):
structMap += fxconv.u32( 0 )
structMap += fxconv.u32( 0 )
else:
structMap += fxconv.u32( int(nbextra) )
structMap += fxconv.ptr( extradata )
nameDialog = data["properties"][0]["value"]
dialogfile = "/".join(input.split("/")[:-nbRetour]) + "/" + nameDialog
print( "THE DIALOGS ARE CONTAINED IN THE FILE : ", dialogfile )
nbdiag = 0
diagdata = fxconv.Structure()
nbdiag, diagdata = convert_dialogs(dialogfile, output, params, target)
if (nbdiag==0):
structMap += fxconv.u32( 0 )
structMap += fxconv.u32( 0 )
else:
structMap += fxconv.u32( int(nbdiag) )
structMap += fxconv.ptr( diagdata )
#extraction of the data contained in the layer "Background" and "Foreground" of the map
#import the Background layer of the map
for i in range(nbTilelayer+1):
datavalid = data["layers"][i]
if datavalid["name"]=="Background":
layer_background = i
print( "Background Tile Data in layer : ", layer_background)
break
elif i==nbTilelayer:
print( "ERROR : No Background layer data !!!" )
layer_data = bytes()
layer = data["layers"][layer_background]
for tile in layer["data"]:
layer_data += fxconv.u16(tile-1)
structMap += fxconv.ptr(layer_data)
#import the foreground layer of the map
for i in range(nbTilelayer+1):
datavalid = data["layers"][i]
if datavalid["name"]=="Foreground":
layer_foreground = i
print( "Foreground Tile Data in layer : ", layer_foreground)
break
elif i==nbTilelayer:
printf( "ERROR : No Foreground layer data !!!" )
layer_data = bytes()
layer = data["layers"][layer_foreground]
for tile in layer["data"]:
layer_data += fxconv.u16(tile-1)
structMap += fxconv.ptr(layer_data)
return structMap
def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
print( "WE ARE COMPUTING THE EXTRA DATA OF THE MAP : ", input )
data = json.load(open(input, "r"))
nblayer = ["id" in i for i in data["layers"]].count(True) - 1
print( "I found ", nblayer, " of extradata")
#index of the various layers (may change from one map to another)
layer_extradata = 0
#import the foreground layer of the map
for i in range(nblayer+1):
datavalid = data["layers"][i]
if datavalid["name"]=="ExtraData":
layer_extradata = i
print( "Extra Data in layer : ", layer_extradata)
break
elif i==nblayer:
print( "ERROR : No ExtraData layer data !!!" )
return 0, fxconv.u32(0)
#create the structure of the map
structData = fxconv.Structure()
nbExtraData = 0
layer = data["layers"][layer_extradata]
for i in layer["objects"]:
#get the type of the item
tpe = i["type"]
#we check if the type corresponds to a items of type Point in Tiled
if tpe in ( "SGN", "NPC", "INFO" ):
nbExtraData = nbExtraData + 1
x = i["x"] + xmin
y = i["y"] + ymin
nme = i["name"]
dialogID = None
needAction = None
path = 0
path_length = 0
xdata = None
ydata = None
#we now fill all the properties of this item
for j in i["properties"]:
#property "dialog"
if j["name"]=="dialogID": dialogID = j[ "value" ]
#property "isQuestion"
elif j["name"]=="needAction": needAction = j[ "value" ]
else:
#Extra properties for NPCs (path)
if tpe=="NPC":
if j["name"]=="hasPath":
pathID = None
path = j[ "value" ]
if path==1:
print( "PNJ has path - NOW LOOKING FOR RELEVANT DATA" )
# we start looking for path data with first the ID of the path Object
for u in i["properties"]:
if u["name"]=="path":
pathID = u[ "value" ]
print( "path ID is identified : ID= ", pathID )
for v in layer["objects"]:
if v[ "id" ] == pathID:
print( "path data found : " )
xdata = bytes()
ydata = bytes()
for w in v[ "polyline" ]:
path_length = path_length + 1
print( "X= ", w[ "x" ], " Y= ", w[ "y" ] )
xdata += fxconv.u16( int( w[ "x" ] ) )
ydata += fxconv.u16( int( w[ "y" ] ) )
else:
print( "PNJ has no Path" )
else:
print( "UNIDENTIFIED PROPERTY : ", j["name"])
print( "OBJECT X= ", x, " Y= ", y, "STR= ", dialogID )
print( " Type= ", tpe, " Name= ", nme )
print( " Action?= ", needAction )
structData += fxconv.u32( int(x) )
structData += fxconv.u32( int(y) )
structData += fxconv.string( nme )
structData += fxconv.string( tpe )
structData += fxconv.u32( int(dialogID) )
structData += fxconv.u32( int(needAction) )
if path==0:
structData += fxconv.u32(0)
structData += fxconv.u32(0)
structData += fxconv.u32(0)
structData += fxconv.u32(0)
else:
o_xdata = fxconv.Structure()
o_xdata += xdata
o_ydata = fxconv.Structure()
o_ydata += ydata
structData += fxconv.u32(path)
structData += fxconv.u32(path_length)
structData += fxconv.ptr(o_xdata)
structData += fxconv.ptr(o_ydata)
#else we do nothing (yet)
else:
print( "Skip this object" )
return nbExtraData, structData
def convert_custom_image(input, output, params, target):
scale = int(params.get("scale", 1))
# Upscale image before converting
im = Image.open(input)
im = im.resize((im.width * scale, im.height * scale),
resample=Image.NEAREST)
o = fxconv.convert_image_cg(im, params)
fxconv.elf(o, output, "_" + params["name"], **target)
def convert_font(input, output, params, target):
o = fxconv.convert_topti(input, params)
fxconv.elf(o, output, "_" + params["name"], **target)
def convert_dialogs(input, output, params, target):
print( "WE ARE COMPUTING THE DIALOGS FROM : ", input )
data = json.load(open(input, "r"))
structDialogs = fxconv.Structure()
nbdialogs = 0
for d in data["dialogs"]:
print( int(d[ "ID" ]))
# print( d[ "dialog" ] )
print( int(d[ "isQuestion" ]) )
# print( d[ "choice" ].replace('$', chr(0)) )
# print( d[ "conclusion1" ] )
# print( int(d[ "next1" ] ) )
# print( d[ "conclusion2" ] )
# print( int(d[ "next2" ] ) )
# print( int(d[ "nextOther" ]) )
nbdialogs = nbdialogs + 1
structDialogs += fxconv.u32( int(d[ "ID" ] ) )
structDialogs += fxconv.string( d[ "dialog" ] )
structDialogs += fxconv.u32( int(d[ "isQuestion" ] ) )
structDialogs += fxconv.string( d[ "choice" ].replace('$', chr(0)) )
structDialogs += fxconv.string( d[ "conclusion1" ] )
structDialogs += fxconv.u32( int(d[ "next1" ] ) )
structDialogs += fxconv.string( d[ "conclusion2" ] )
structDialogs += fxconv.u32( int(d[ "next2" ] ) )
structDialogs += fxconv.u32( int(d[ "nextOther" ] ) )
return nbdialogs, structDialogs
#fxconv.elf(structDialogs, output, "_" + params["name"], **target)
import sys
# Add the assets folder to the path, to be able to import the tiled script.
sys.path.append("../assets/")
import fxconv
from tinytiled import *
# If the output of the converter should be verbose.
VERBOSE = 1
# The sign types, used to find the sign icon.
SIGN_TYPES = ["SGN", "INFO"]
# The NPC faces, used to find the face id.
FACES = ["MALE", "FEMALE", "MILKMAN", "POLICE"]
# The precision of the fixed point numbers.
# WARNING: The PRECISION define in config.h should contain the same value!
PRECISION = 8
def convert(input: str, output: str, params: dict, target):
"""
This method gets called by fxconv for each asset to convert.
"""
if params["custom-type"] == "tmx":
convert_map(input, output, params, target)
return 0
elif params["custom-type"] == "dialog":
convert_dialog(input, output, params, target)
return 0
def convert_map(input: str, output: str, params: dict, target):
"""
Convert a map.
"""
if VERBOSE: print(f"INFO: Converting map {input} -> {output}")
input_map = Map(input)
dialog_file = ""
background_layer = []
foreground_layer = []
walkable_layer = []
map_x = 0
map_y = 0
width = 0
height = 0
outdoor_tileset = None
walkable_tileset = None
dialog_num = 0
dialog_ids = []
npc_paths = {}
npcs = {}
signs = {}
portals = {}
name = os.path.splitext(os.path.basename(input))[0]
map_struct = fxconv.Structure()
# Get the dialog file
try:
if VERBOSE: print("INFO: Getting the dialog file")
dialog_file = input_map.get_property("dialogFile")
if VERBOSE: print(f"INFO: Dialog file: {dialog_file}.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the dialog file.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the map position
try:
if VERBOSE: print("INFO: Getting the map position")
map_x = int(input_map.get_property("mapX"))
map_y = int(input_map.get_property("mapY"))
if VERBOSE: print(f"INFO: Map position: ({map_x}, {map_y}).")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the map position.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get informations about dialogs
try:
if VERBOSE: print("INFO: Getting informations about dialogs")
with open(f"{input_map.parent_dir}/{dialog_file}", "r") as file:
dialog_data = json.load(file)
dialog_num = len(dialog_data["dialogs"])
for i in dialog_data["dialogs"]:
dialog_ids.append(i["ID"])
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get informations about dialogs.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the outdoor tileset
try:
if VERBOSE: print("INFO: Getting the outdoor tileset")
outdoor_tileset = input_map.get_tileset_by_firstgid(1)
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the outdoor tileset.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the walkable tileset
try:
if VERBOSE: print("INFO: Getting the walkable tileset")
walkable_tileset = input_map.get_tileset_by_firstgid(409)
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the walkable tileset.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the background
try:
if VERBOSE: print("INFO: Getting the background layer")
bg_layer = input_map.get_layer_by_name("Background")
# The bg layer will be used to set the map width and height.
width = bg_layer.get_width()
height = bg_layer.get_height()
if VERBOSE: print(f"INFO: Map size: ({width}, {height}).")
# Get the layer data himself
background_layer = bg_layer.get_data_with_tileset(outdoor_tileset)
# Check if the size of the layer data is correct.
if len(background_layer) != width*height:
raise Exception("Bad layer size!")
if VERBOSE: print("INFO: Layer data has the right size.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the background layer.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the foreground
try:
if VERBOSE: print("INFO: Getting the foreground layer")
fg_layer = input_map.get_layer_by_name("Foreground")
# Get the layer data himself
foreground_layer = fg_layer.get_data_with_tileset(outdoor_tileset)
# Check if the size of the layer data is correct.
if len(foreground_layer) != width*height:
raise Exception("Bad layer size!")
if VERBOSE: print("INFO: Layer data has the right size.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the foreground layer.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the walkable layer
try:
if VERBOSE: print("INFO: Getting the walkable layer")
wk_layer = input_map.get_layer_by_name("Walkable")
# Get the layer data himself
walkable_layer = wk_layer.get_data_with_tileset(walkable_tileset)
# Check if the size of the layer data is correct.
if len(walkable_layer) != width*height:
raise Exception("Bad layer size!")
if VERBOSE: print("INFO: Layer data has the right size.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the walkable layer.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Get the extra data
try:
if VERBOSE: print("INFO: Getting the extra data")
ed_objgroup = input_map.get_objectgroup_by_name("ExtraData")
# Get the paths the NPCs take.
for object in ed_objgroup.objects:
if object.get_data_type() == "polyline":
npc_paths[object.id] = object.get_data()
# Get the NPCs
for object in ed_objgroup.objects:
if object.get_data_type() == "point" and object.type == "NPC":
path = [0, 0]
if int(object.get_property("hasPath")):
if object.get_property("path") in npc_paths:
path = npc_paths[object.get_property("path")]
else:
raise Exception("Path required but not found!")
dialog_id = 0
has_dialog = 0
try:
dialog_id = int(object.get_property("dialogID"))
has_dialog = 1
except:
pass
data = {
"position": object.get_data(),
"name": object.name,
"needAction": int(object.get_property("needAction")),
"dialogID": dialog_id,
"hasDialog": has_dialog,
"face": FACES.index(object.get_property("face")),
"path": path
}
npcs[object.id] = data
# Get the signs
for object in ed_objgroup.objects:
if object.get_data_type() == "point" and object.type in SIGN_TYPES:
data = {
"position": object.get_data(),
"name": object.name,
"needAction": int(object.get_property("needAction")),
"dialogID": int(object.get_property("dialogID")),
"icon": SIGN_TYPES.index(object.type)
}
signs[object.id] = data
# Get the portals
for object in ed_objgroup.objects:
if (object.get_data_type() == "rectangle"
and object.type == "PORTAL"):
data = {
"rect": object.get_data(),
"name": object.name,
"dest": object.get_property("dest"),
"destPortal": object.get_property("destPortal")
}
portals[object.id] = data
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the extra data.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Generate the structs
# Map struct
map_struct += fxconv.u32(map_x)
map_struct += fxconv.u32(map_y)
map_struct += fxconv.u32(width)
map_struct += fxconv.u32(height)
map_struct += fxconv.u32(3)
map_struct += fxconv.u32(outdoor_tileset.columns)
tileset_name = os.path.splitext(os.path.basename(outdoor_tileset.source))[0]
map_struct += fxconv.ref(f"img_{tileset_name}")
# Store the walkable layer
walkable_data = bytes()
for i in walkable_layer:
if i < 0: i = 0
walkable_data += fxconv.u8(i)
map_struct += fxconv.ptr(walkable_data)
# Load NPCs
map_struct += fxconv.u32(len(npcs))
npc_struct = fxconv.Structure()
for i in npcs.values():
# Convert currentpos to a fixed point value.
npc_struct += fxconv.u32((i["position"][0]+i["path"][0])<<PRECISION)
npc_struct += fxconv.u32((i["position"][1]+i["path"][1])<<PRECISION)
npc_struct += fxconv.u32(i["position"][0])
npc_struct += fxconv.u32(i["position"][1])
npc_struct += fxconv.u16(i["face"])
npc_struct += fxconv.u8(0)
npc_struct += fxconv.u8(i["hasDialog"])
npc_struct += fxconv.u32(i["dialogID"])
npc_struct += fxconv.u32(i["needAction"])
npc_struct += fxconv.string(i["name"])
npc_struct += fxconv.u32(len(i["path"]) > 2)
npc_struct += fxconv.u32(len(i["path"])//2)
npc_struct += fxconv.u32(0)
xpath = bytes()
ypath = bytes()
x = True
for n in i["path"]:
if x: xpath += fxconv.u16(n)
else: ypath += fxconv.u16(n)
x = not x
npc_struct += fxconv.ptr(xpath)
npc_struct += fxconv.ptr(ypath)
npc_struct += fxconv.u32(0) # TODO: Type
npc_struct += fxconv.u8(0) # TODO: Group
npc_struct += fxconv.u8(0) # TODO: Hostile to
npc_struct += fxconv.u16(0) # TODO: Padding (what is it ?)
map_struct += fxconv.ptr(npc_struct)
# Load signs
map_struct += fxconv.u32(len(signs))
sign_struct = fxconv.Structure()
for i in signs.values():
# Create a sign struct for each sign.
sign_struct += fxconv.u32(i["position"][0])
sign_struct += fxconv.u32(i["position"][1])
sign_struct += fxconv.u32(i["icon"])
sign_struct += fxconv.string(i["name"])
sign_struct += fxconv.u32(i["dialogID"])
sign_struct += fxconv.u32(i["needAction"])
map_struct += fxconv.ptr(sign_struct)
# Load portals
map_struct += fxconv.u32(len(portals))
portal_struct = fxconv.Structure()
for i in portals.values():
dest_file_name = os.path.splitext(os.path.basename(i["dest"]))[0]
dest_portal = i["destPortal"]
portal_name = i["name"]
if VERBOSE: print(f"INFO: Storing portal {name}_{portal_name}")
portal_struct += fxconv.sym(f"{name}_{portal_name}")
# Add the collider
rect = i["rect"]
portal_struct += fxconv.u32(rect[0])
portal_struct += fxconv.u32(rect[1])
portal_struct += fxconv.u32(rect[2])
portal_struct += fxconv.u32(rect[3])
# Add a reference to the destination portal
portal_struct += fxconv.ref(f"{dest_file_name}_{dest_portal}")
portal_struct += fxconv.ref(f"{dest_file_name}")
map_struct += fxconv.ptr(portal_struct)
map_struct += fxconv.u32(dialog_num)
# Get the name of the dialog file and create a reference to it: it is built
# separately.
dialog_name = os.path.splitext(os.path.basename(dialog_file))[0]
map_struct += fxconv.ref(f"_{dialog_name}")
# Store the background layer
background_data = bytes()
for i in background_layer:
background_data += fxconv.u16(i)
map_struct += fxconv.ptr(background_data)
# Store the foreground layer
foreground_data = bytes()
for i in foreground_layer:
foreground_data += fxconv.u16(i)
map_struct += fxconv.ptr(foreground_data)
# Create the fxconv object
fxconv.elf(map_struct, output, f"_{name}", **target)
def convert_dialog(input: str, output: str, params: dict, target):
"""
Convert a JSON dialog file.
"""
if VERBOSE: print(f"INFO: Converting dialog file {input} -> {output}")
# Load the JSON dialog file.
dialog_data = None
try:
with open(input, "r") as file:
dialog_data = json.load(file)
except Exception as e:
sys.stderr.write(f"ERROR: Failed parse json.\n"
+ f" Error message: {e}\n")
sys.exit(1)
# Create the dialog struct
dialog_struct = fxconv.Structure()
try:
for i in dialog_data["dialogs"]:
# Create a dialog structure for each dialog.
dialog_id = i["ID"]
dialog_struct += fxconv.u32(dialog_id)
dialog_struct += fxconv.string(i["dialog"])
dialog_struct += fxconv.u32(i["isQuestion"])
dialog_struct += fxconv.string(i["choice"].replace('$', '\0'))
dialog_struct += fxconv.string(i["conclusion1"])
dialog_struct += fxconv.u32(i["next1"])
dialog_struct += fxconv.string(i["conclusion2"])
dialog_struct += fxconv.u32(i["next2"])
dialog_struct += fxconv.u32(i["nextOther"])
# Save this struct
name = os.path.splitext(os.path.basename(input))[0]
fxconv.elf(dialog_struct, output, f"__{name}", **target)
except Exception as e:
# Show an error message if the conversion fails.
sys.stderr.write(f"ERROR: Failed convert dialogs.\n"
+ f" Error message: {e}\n")
sys.exit(1)

View file

@ -1,7 +1,47 @@
WorldRPG.world:
custom-type: world
name: worldRPG
level0.tmx:
custom-type: tmx
name: level0
#DialogsRPG.json:
# custom-type: dialogs
# name: dialogRPG
level1.tmx:
custom-type: tmx
name: level1
level2.tmx:
custom-type: tmx
name: level2
level3.tmx:
custom-type: tmx
name: level3
level4.tmx:
custom-type: tmx
name: level4
level0_dialogs.json:
custom-type: dialog
name: level0_dialogs
level1_dialogs.json:
custom-type: dialog
name: level1_dialogs
level2_dialogs.json:
custom-type: dialog
name: level2_dialogs
level3_dialogs.json:
custom-type: dialog
name: level3_dialogs
level4_dialogs.json:
custom-type: dialog
name: level4_dialogs
interior1_0.tmx:
custom-type: tmx
name: level0
interior1_0_dialogs.json:
custom-type: dialog
name: interior1_0_dialogs

54
assets/interior1_0.tmx Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="12" height="8" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="3">
<properties>
<property name="dialogFile" type="file" value="interior1_0_dialogs.json"/>
<property name="mapX" type="int" value="65536"/>
<property name="mapY" type="int" value="65536"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
<layer id="1" name="Background" width="12" height="8">
<data encoding="csv">
86,90,91,89,90,91,89,90,91,89,90,92,
110,114,115,113,114,115,113,114,115,113,114,116,
86,93,94,1,1,1,1,1,9,10,1,92,
110,117,118,1,1,1,1,1,33,34,1,116,
86,1,1,1,1,1,1,1,1,1,1,92,
110,1,1,1,1,133,2,1,1,1,1,116,
110,1,1,1,1,2,2,1,1,1,1,92,
110,114,114,114,114,114,114,114,114,114,114,116
</data>
</layer>
<layer id="2" name="Foreground" width="12" height="8">
<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
</data>
</layer>
<layer id="3" name="Walkable" width="12" height="8">
<data encoding="csv">
410,410,410,410,410,410,410,410,410,410,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,
410,410,410,0,0,0,0,0,410,0,0,410,
410,410,410,0,0,0,0,0,410,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,410,410,410,410,410,410,410,410,410,410,410
</data>
</layer>
<objectgroup id="4" name="ExtraData">
<object id="2" name="porte" type="PORTAL" x="39.6736" y="40.0979" width="15.8058" height="15.9119">
<properties>
<property name="dest" type="file" value="level0.tmx"/>
<property name="destPortal" value="taverne"/>
</properties>
</object>
</objectgroup>
</map>

View file

@ -0,0 +1,13 @@
{ "dialogs":[
{ "ID":0,
"dialog":"_",
"isQuestion":0,
"choice":"_",
"conclusion1":"_",
"next1":-1,
"conclusion2":"_",
"next2":-1,
"nextOther":1
}
]
}

View file

@ -1,32 +1,34 @@
<?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="8" nextobjectid="14">
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="8" nextobjectid="17">
<editorsettings>
<export target="level0.json" format="json"/>
</editorsettings>
<properties>
<property name="dialogFile" type="file" value="DialogsLvl0.json"/>
<property name="dialogFile" type="file" value="level0_dialogs.json"/>
<property name="mapX" type="int" value="0"/>
<property name="mapY" type="int" value="0"/>
</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">
2,297,298,299,300,2,386,297,298,299,300,2,2,2,2,2,2,337,338,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,2,2,2,345,346,347,348,2,337,338,
253,205,229,205,229,280,179,180,179,156,156,156,158,157,179,180,253,361,362,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,26,27,117,118,28,369,370,371,372,2,361,362,
301,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,301,2,386,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,49,9,10,134,135,52,393,394,395,396,337,338,2,
325,149,150,151,152,2,2,327,374,375,327,2,2,185,374,375,325,387,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,73,33,34,74,219,76,2,2,2,2,361,362,2,
257,2,2,385,2,2,385,2,265,266,2,2,208,209,352,353,257,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,26,27,27,97,98,99,98,99,100,26,26,27,28,131,2,2,
281,176,2,2,2,2,176,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,49,2,2,2,121,59,60,60,61,124,2,2,2,52,132,2,2,
2,2,2,2,2,385,2,2,265,266,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,73,2,2,2,145,83,84,84,85,148,2,2,2,76,132,2,2,
2,2,2,2,326,2,385,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,190,2,2,2,2,2,2,385,2,49,404,405,2,169,107,108,108,109,172,2,402,403,76,132,2,2,
2,2,2,2,2,2,2,2,289,290,2,258,259,260,238,239,260,260,261,262,262,263,264,2,2,2,2,2,2,2,385,49,134,135,2,2,2,2,2,2,2,2,134,135,52,132,297,298,
2,2,2,2,2,2,2,2,265,266,2,282,283,284,285,285,285,285,285,285,286,287,288,297,298,299,300,2,117,118,2,73,373,2,217,2,190,373,373,190,2,219,2,373,76,132,2,2,
297,298,299,300,2,2,2,2,290,2,2,306,307,308,309,308,309,308,309,310,310,311,312,131,2,339,340,2,134,135,2,97,98,99,99,98,99,2,2,98,98,99,98,99,100,132,2,2,
253,205,229,205,229,280,179,180,179,156,156,156,158,157,179,180,253,361,362,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,358,359,117,118,28,369,370,371,372,2,361,362,
301,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,301,2,386,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,382,9,10,134,135,360,393,394,395,396,337,338,2,
325,149,150,151,152,2,2,327,374,375,327,2,2,185,374,375,325,387,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,406,33,34,2,219,384,2,2,2,2,361,362,2,
257,2,2,385,2,2,385,2,265,266,2,2,208,209,352,353,257,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,358,359,358,97,407,408,407,408,100,358,358,359,28,131,2,2,
281,176,2,2,2,2,176,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,382,2,2,2,121,59,60,60,61,124,2,2,2,360,132,2,2,
2,2,2,2,2,385,2,2,265,266,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,406,2,2,2,145,83,84,84,85,148,2,2,2,384,132,2,2,
2,2,2,2,326,2,385,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,190,2,2,2,2,2,2,385,2,406,404,405,2,169,107,108,108,109,172,2,402,403,384,132,2,2,
2,2,2,2,2,2,2,2,289,290,2,258,259,260,238,239,260,260,261,262,262,263,264,2,2,2,2,2,2,2,385,382,134,135,2,2,2,2,2,2,2,2,134,135,360,132,297,298,
2,2,2,2,2,2,2,2,265,266,2,282,283,284,285,285,285,285,285,285,286,287,288,297,298,299,300,2,117,118,2,382,373,2,217,2,190,373,373,190,2,219,2,373,384,132,2,2,
297,298,299,300,2,2,2,2,290,2,2,306,307,308,309,308,309,308,309,310,310,311,312,131,2,339,340,2,134,135,2,97,407,408,408,408,408,19,18,407,408,408,407,408,100,132,2,2,
2,2,2,386,2,2,2,2,2,2,2,330,331,332,333,332,333,332,333,334,334,335,336,132,2,363,364,2,2,2,2,121,122,122,122,123,124,81,82,121,122,123,122,123,124,132,2,2,
2,2,2,386,297,298,299,300,2,290,2,162,163,164,165,162,163,164,165,162,163,164,165,132,2,2,2,2,2,2,2,145,146,146,146,147,148,57,58,145,146,147,146,147,148,132,2,2,
2,2,2,2,2,2,2,2,2,2,2,86,87,88,89,186,187,188,189,86,87,88,89,132,385,2,2,2,2,2,2,169,170,170,170,171,172,81,82,169,170,171,14,15,27,26,27,27,
2,2,2,2,270,271,271,271,272,2,2,110,111,112,113,210,211,212,213,110,111,112,113,133,2,2,2,2,2,2,2,2,2,2,2,2,2,290,265,265,266,266,38,39,2,2,2,51,
298,299,300,2,294,1,1,1,296,2,2,2,2,2,2,234,290,265,237,2,2,2,339,340,385,2,2,2,2,2,2,327,2,2,2,160,161,386,266,289,290,265,62,63,73,74,75,75,
2,2,2,2,294,1,1,1,296,2,2,160,161,265,266,266,265,266,290,2,2,2,363,364,2,297,298,299,300,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,97,98,99,99,
2,2,2,2,2,2,2,2,2,2,2,86,87,88,89,186,187,188,189,86,87,88,89,132,385,2,2,2,2,2,2,169,170,170,170,171,172,81,82,169,170,171,14,15,42,358,359,359,
2,2,2,2,270,271,271,271,272,2,2,110,111,112,113,210,211,212,213,110,111,112,113,133,2,2,2,2,2,2,2,2,2,2,2,2,2,290,265,265,266,266,38,39,19,2,2,2,
298,299,300,2,294,1,1,1,296,2,2,2,2,2,2,234,290,265,237,2,2,2,339,340,385,2,2,2,2,2,2,327,2,2,2,160,161,386,266,289,290,265,62,63,406,2,2,2,
2,2,2,2,294,1,1,1,296,2,2,160,161,265,266,266,265,266,290,2,2,2,363,364,2,297,298,299,300,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,97,407,408,408,
2,2,2,2,318,319,319,319,320,2,386,266,266,289,290,265,266,241,265,266,266,265,266,241,385,2,2,2,241,265,266,266,265,386,265,266,266,265,266,2,2,2,2,2,121,122,123,123,
2,2,2,2,2,2,2,2,2,385,289,290,386,265,265,2,2,241,289,290,265,266,290,266,265,266,266,386,266,289,290,265,266,290,289,385,265,266,290,2,2,2,2,2,145,146,147,147,
2,2,2,2,2,2,2,2,2,2,2,2,2,265,386,2,2,2,2,2,2,2,241,241,289,290,265,266,290,241,2,2,2,2,2,2,21,22,23,24,2,2,254,255,169,170,171,171,
@ -68,28 +70,28 @@
<data encoding="csv">
0,0,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410,410,410,410,0,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410,
410,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,410,410,0,410,0,0,0,0,410,410,410,410,410,410,410,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,0,410,410,410,410,410,410,410,0,
410,410,410,410,410,0,0,410,410,410,410,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,410,410,0,
410,0,0,0,0,0,0,0,0,0,0,0,410,411,411,411,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
410,0,0,412,0,0,0,0,0,0,0,0,410,411,411,411,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,411,411,411,411,410,0,410,0,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,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,410,410,410,0,410,410,0,0,410,410,0,410,410,410,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,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,
0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0,
0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,412,0,410,410,410,0,410,410,0,0,410,410,0,410,410,410,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,0,0,0,0,0,0,0,412,410,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,
0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,410,410,0,0,410,410,0,410,0,0,0,0,410,0,0,410,0,0,0,0,410,0,0,0,
0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,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,0,0,410,410,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,410,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,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,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,0,0,410,410,410,
0,0,0,412,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0,
0,0,0,412,0,410,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,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,0,412,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,0,0,410,410,410,
0,0,0,0,412,412,412,412,412,0,0,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,410,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,
410,410,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,
0,0,0,0,412,412,412,412,412,0,0,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,410,410,
410,410,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,0,0,0,0,0,0,0,
0,0,412,0,0,0,0,410,410,410,410,410,0,0,0,0,410,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,410,410,0,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,410,410,0,410,410,410,410,410,0,0,0,0,410,412,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
</data>
</layer>
<objectgroup id="4" name="ExtraData">
@ -117,6 +119,7 @@
<object id="12" name="PNJ3" type="NPC" x="267.25" y="125.75">
<properties>
<property name="dialogID" type="int" value="12"/>
<property name="face" value="FEMALE"/>
<property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="13"/>
@ -126,6 +129,7 @@
<object id="2" name="PNJ2" type="NPC" x="164" y="132">
<properties>
<property name="dialogID" type="int" value="5"/>
<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"/>
@ -135,6 +139,7 @@
<object id="10" name="PNJ1" type="NPC" x="252" y="164">
<properties>
<property name="dialogID" type="int" value="7"/>
<property name="face" value="MILKMAN"/>
<property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="9"/>
@ -168,5 +173,11 @@
<object id="13" name="Chemin 100pas Client Auberge" type="TRJ" x="267.25" y="126.25">
<polyline points="0,0 -30.5,16.75 -182.5,15.75 -195.25,-26 -183.25,16.5 -29.25,18.5"/>
</object>
<object id="16" name="taverne" type="PORTAL" x="128.974" y="111.676" width="14.7688" height="7.99134">
<properties>
<property name="dest" type="file" value="interior1_0.tmx"/>
<property name="destPortal" value="porte"/>
</properties>
</object>
</objectgroup>
</map>

View file

@ -1,7 +1,9 @@
<?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="4">
<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="4">
<properties>
<property name="dialogFile" type="file" value="DialogsLvl1.json"/>
<property name="dialogFile" type="file" value="level1_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="0"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
@ -20,10 +22,10 @@
2,2,269,1,1,1,1,1,1,319,319,269,1,1,1,316,271,316,271,317,1,1,1,1,319,319,319,268,268,319,319,319,268,319,320,2,2,318,319,320,268,269,1,1,1,1,1,1,
2,2,2,269,1,1,1,1,320,2,2,2,269,1,1,1,1,1,1,1,1,1,267,2,2,2,2,2,2,2,2,2,2,2,2,2,2,219,2,2,2,318,319,320,269,1,1,1,
2,2,2,2,319,268,319,320,2,2,2,2,318,319,269,1,1,1,1,1,1,267,2,2,2,2,313,265,242,266,241,219,314,313,242,241,2,2,219,2,2,2,2,2,2,269,1,1,
27,26,27,26,27,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,2,2,2,297,298,299,300,2,2,318,319,320,
2,50,51,51,99,100,132,2,2,2,2,2,2,2,2,2,2,2,2,314,265,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,74,75,76,16,17,133,2,2,2,2,2,2,2,2,2,2,2,241,219,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
98,98,99,100,40,41,290,314,297,298,299,300,2,2,2,2,2,219,219,289,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,
359,358,359,358,359,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,2,2,2,297,298,299,300,2,2,318,319,320,
2,2,2,18,407,100,132,2,2,2,2,2,2,2,2,2,2,2,2,314,265,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,42,16,17,133,2,2,2,2,2,2,2,2,2,2,2,241,219,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
408,407,407,408,40,41,290,314,297,298,299,300,2,2,2,2,2,219,219,289,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,
121,122,123,124,64,65,265,289,313,289,241,265,219,2,2,2,2,290,314,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,402,403,2,374,375,2,404,405,2,2,2,2,2,2,
145,146,147,148,132,2,2,2,2,2,2,314,314,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
169,170,171,172,133,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2,
@ -79,13 +81,13 @@
410,410,410,410,410,410,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,412,412,412,
0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,
410,410,409,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,
410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,0,410,410,0,410,410,0,0,0,0,0,0,
410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,410,410,0,
410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,410,410,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
@ -100,13 +102,14 @@
<object id="2" name="Gardien" type="NPC" x="303.636" y="117.273">
<properties>
<property name="dialogID" type="int" value="1"/>
<property name="face" value="POLICE"/>
<property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="3"/>
</properties>
<point/>
</object>
<object id="3" name="Chemin Gardien" x="303.818" y="117.455">
<object id="3" name="Chemin Gardien" type="TRJ" x="303.818" y="117.455">
<properties>
<property name="dialogID" type="int" value="0"/>
<property name="needAction" type="int" value="1"/>

View file

@ -1,7 +1,9 @@
<?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="5">
<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="5">
<properties>
<property name="dialogFile" type="file" value="DialogsLvl2.json"/>
<property name="dialogFile" type="file" value="level2_dialogs.json"/>
<property name="mapX" type="int" value="0"/>
<property name="mapY" type="int" value="24"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
@ -11,13 +13,13 @@
2,2,2,2,2,386,2,2,2,2,2,277,2,386,266,2,349,385,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,
298,299,300,2,2,2,2,385,385,2,2,301,2,266,290,2,349,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,386,2,2,256,2,265,266,2,257,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,297,298,299,258,259,262,330,333,333,336,262,263,264,2,2,2,
2,2,2,2,2,2,2,2,386,386,2,281,2,266,290,2,280,2,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,2,2,283,283,3,91,87,88,92,3,312,288,2,385,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,290,266,2,2,2,385,2,297,298,299,300,2,2,2,2,2,2,2,9,10,2,2,283,283,3,115,111,112,113,3,312,312,131,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,386,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,34,385,2,283,283,3,114,114,115,114,3,312,312,132,385,2,
2,386,2,2,2,2,2,2,2,2,2,2,2,313,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2,
2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,374,375,151,152,149,150,151,152,149,150,374,375,149,150,151,152,2,2,282,283,3,3,3,3,3,3,287,288,132,2,2,
2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,208,209,352,353,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,312,132,2,2,
2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,232,233,376,377,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2,
2,2,2,2,2,2,2,2,386,386,2,281,2,266,290,2,280,2,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,2,2,283,283,5,91,87,88,92,5,312,288,2,385,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,290,266,2,2,2,385,2,297,298,299,300,2,2,2,2,2,2,2,9,10,2,2,283,283,5,115,111,112,113,5,312,312,131,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,386,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,34,385,2,283,283,5,114,114,115,114,5,312,312,132,385,2,
2,386,2,2,2,2,2,2,2,2,2,2,2,313,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,288,132,2,2,
2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,374,375,151,152,149,150,151,152,149,150,374,375,149,150,151,152,2,2,282,283,5,5,5,5,5,5,287,288,132,2,2,
2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,208,209,352,353,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,312,132,2,2,
2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,232,233,376,377,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,288,132,2,2,
2,2,2,2,2,385,2,2,2,2,2,2,2,386,313,2,2,149,149,374,375,149,150,151,152,374,375,151,152,149,150,151,152,2,2,282,330,308,308,308,308,308,308,311,312,132,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,2,2,2,2,2,385,2,2,385,2,2,2,2,2,2,330,331,331,331,331,331,331,331,331,336,132,2,2,
2,297,298,299,300,2,2,2,2,2,2,2,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,90,91,92,162,163,164,165,90,91,92,132,2,2,
@ -37,7 +39,7 @@
<data encoding="csv">
250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,297,298,299,300,0,0,0,225,226,227,228,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0,
274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,202,203,204,0,0,0,0,249,250,251,252,249,250,251,252,0,0,258,259,263,264,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,3,3,288,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,307,311,288,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,201,202,203,204,0,0,0,0,0,0,0,0,0,0,0,0,0,273,274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -63,30 +65,30 @@
</layer>
<layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,
410,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,412,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,
0,0,0,0,0,412,0,0,0,0,0,410,0,0,0,0,410,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,
410,410,0,0,0,0,0,412,412,0,0,410,0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,412,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,412,412,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,412,0,
0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,410,410,0,0,410,410,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,410,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,411,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,412,410,410,410,410,0,0,0,410,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,412,0,410,410,410,410,0,0,0,411,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0,
0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,0,0,0,0,412,412,0,
0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,412,412,412,0,0,0,412,0,0,0,0,0,412,0,0,412,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,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>
<objectgroup id="4" name="ExtraData">

View file

@ -1,7 +1,9 @@
<?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"/>
<property name="dialogFile" type="file" value="level3_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="24"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
@ -30,7 +32,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">
@ -64,29 +66,29 @@
<layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv">
0,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,410,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,410,410,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,410,410,0,0,0,0,410,0,0,412,0,0,412,0,410,410,410,410,410,410,410,410,410,410,0,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,410,410,
410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,410,410,410,410,410,410,410,410,0,410,410,410,410,0,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,0,410,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,410,410,410,410,410,410,410,410,0,410,410,410,410,0,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,410,
0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,412,410,410,0,412,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,0,412,0,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,0,0,0,0,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,412,0,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,0,0,0,0,0,410,410,410,410,0,0,
0,0,410,410,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,0,0,0
0,0,0,0,412,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,412,0,0
</data>
</layer>
<objectgroup id="4" name="ExtraData">

126
assets/level4.tmx Normal file
View file

@ -0,0 +1,126 @@
<?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="level4_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="48"/>
</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,2,2,385,386,385,2,2,2,2,2,2,2,2,2,385,386,385,265,266,385,386,385,386,385,121,122,123,122,123,122,124,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,
385,386,385,386,385,386,385,386,2,2,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,2,2,2,217,218,219,385,2,2,386,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,313,314,25,358,359,358,359,145,146,146,146,147,146,148,358,359,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,382,2,2,176,2,169,170,170,170,171,170,172,2,176,360,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,2,2,121,122,59,60,61,123,124,2,2,384,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,406,2,2,145,146,83,84,85,147,148,2,2,360,385,386,385,386,385,386,385,386,385,386,385,386,
385,386,25,26,26,26,26,238,239,28,385,386,385,386,217,218,219,386,385,265,241,14,15,43,254,255,169,170,107,108,109,171,172,254,255,360,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,19,2,2,2,2,2,2,2,176,2,2,177,384,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,407,407,408,407,407,408,407,407,408,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,359,358,359,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,2,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,2,2,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,407,408,407,408,407,408,408,407,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,21,22,23,24,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,214,215,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,409,409,412,412,412,409,409,409,409,409,409,409,409,409,412,412,412,0,0,412,412,412,412,412,410,410,410,410,410,410,410,409,409,409,409,409,409,409,409,412,409,409,409,409,409,409,
412,412,412,412,412,412,412,412,409,409,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,409,409,409,412,412,412,412,409,409,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,410,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,410,410,410,410,410,410,410,410,410,410,410,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,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,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,410,410,410,410,410,410,410,410,410,410,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,409,409,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="MALE"/>
<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" type="TRJ" 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

@ -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
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 37 B

1
assets/tileset.png Symbolic link
View file

@ -0,0 +1 @@
../assets-fx/2b/tileset/tileset2b.png

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 37 B

1
assets/tinytiled Submodule

@ -0,0 +1 @@
Subproject commit b084ecda91a2352a72a5d1a61b37e0009228ee40

1
clean
View file

@ -6,6 +6,7 @@ cd ..
rm -r build-cg
rm -r build-cg-push
rm -r build-fx
rm -r build-fxg3a
rm *.g1a
rm *.g3a

View file

@ -1,28 +1,53 @@
#ifndef CONFIG_H
#define CONFIG_H
#if !defined(FXCG50) && defined(COLOR2BIT)
#define GRAYMODEOK 1
#endif
#define USB_FEATURE 0
#define DEBUGMODE 0
#define PRECISION 8
#ifdef FXCG50
#define T_HEIGHT 16
#define T_WIDTH 16
#include <gint/display.h>
/* Enable GrayMode on either FX and FX_G3A targets */
#if GINT_RENDER_MONO && defined(COLOR2BIT)
#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
#else
#define T_HEIGHT 8
#define T_WIDTH 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
#ifdef FXCG50
#define PXSIZE 2
/* SPEED should NOT be 8 or bigger: it may cause bugs when handling
* collisions! */
#define SPEED (PXSIZE * 2)
/* The face size (in the dialogs) */
#define F_WIDTH (32 * PXSIZE)
#define F_HEIGHT (32 * PXSIZE)
/* the color of the text to go to the next dialog phase */
/* it improves readability to have something lighter */
#if GRAYMODEOK || (GINT_RENDER_RGB && !defined(COLOR1BIT))
#define NEXT_COLOR C_DARK
#else
#define PXSIZE 1
#define NEXT_COLOR C_BLACK
#endif
#endif

View file

@ -1,209 +1,223 @@
#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 <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
/* the color of the text to go to the next dialog phase */
/* it improves readability to have somathing lighter */
#if GRAYMODEOK || (defined(FXCG50) && !defined(COLOR1BIT))
#define NEXT_COLOR C_DARK
#else
#define NEXT_COLOR C_BLACK
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
void blit()
{
dupdate();
#if GRAYMODEOK
dgray_getvram( &lightVRAMnext, &darkVRAMnext );
dgray_getscreen( &lightVRAMcurrent, &darkVRAMcurrent );
memcpy( lightVRAMnext, lightVRAMcurrent, 256*sizeof( uint32_t) );
memcpy( darkVRAMnext, darkVRAMcurrent, 256*sizeof( uint32_t) );
#endif
}
int showtext_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i),
bool start_anim,
bool end_anim,
void for_each_screen(Game *game, unsigned int i),
int line_duration, bool update_screen, unsigned int start_i,
bool wait_continue) {
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i),
bool start_anim, bool end_anim,
void for_each_screen(Game *game, unsigned int i),
int line_duration, bool update_screen,
unsigned int start_i, bool wait_continue) {
text = events_parse_string(&game->handler, text);
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_npc(game);
draw(game);
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. */
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);
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);
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) while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep();
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
/* Clear the text area. */
drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2,
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) while(getkey_opt( GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep();
if(update_screen)
blit();
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
}
if(call_before_end) return_int = call_before_end(game, i);
if(end_anim){
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_npc(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);
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);
dupdate();
while(game->frame_duration < 20) sleep();
while(game->frame_duration < 20)
sleep();
game->frame_duration = 0;
}
}
return return_int;
}
void showtext_dialog(Game *game, bopti_image_t *face, char *text,
bool dialog_start, bool dialog_end) {
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. */
showtext_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;
@ -213,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
@ -253,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_npc(game);
draw(game);
showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false,
_i, false);
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE);
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1,
(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);
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);
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.
@ -319,9 +340,9 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
return selected;
}
int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount,
int default_choice) {
int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount,
int default_choice) {
/* Put some arguments in global pointers and variables to make them
* accessible by _choice_call_before_end. */
_choices = choices;
@ -331,50 +352,45 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start,
_text = text;
/* Run showtext_opt and return his return value (the return value of
*_choice_call_before_end) */
return showtext_opt(game, face, text, _choice_call_before_end, start, end,
_choice_screen_call, 100, true, 0, true);
return dialogs_text_opt(game, face, text, _choice_call_before_end, start,
end, _choice_screen_call, 100, true, 0, true);
}
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber) {
Dialog *currentDiag = &game->map_level->dialogs[dialogNumber];
/* 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;
void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNumber )
{
Dialog *currentDiag = &game->map_level->dialogs[ dialogNumber ];
/* 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 collect the information */
char *text = currentDiag->dialog;
/* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */
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 = showtext_dialog_ask( game, face, text, true, true, choices, 2, 0 );
/* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */
if (answer==0)
{
showtext_dialog( game, face, conclusion1, true, true );
if (next1!=-1) initiate_dialog_sequence( game, face, next1 );
}
else
{
showtext_dialog( game, face, conclusion2, true, true );
if (next2!=-1) initiate_dialog_sequence( game, face, next2 );
}
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
{
showtext_dialog( game, face, text, true, true );
if (nextOther!=-1) initiate_dialog_sequence( game, face, nextOther );
}
}
} else {
dialogs_text(game, face, text, true, true);
if(nextOther != -1)
dialogs_initiate_sequence(game, face, nextOther);
}
}

View file

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

110
src/events.c Normal file
View file

@ -0,0 +1,110 @@
#include "events.h"
#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) {
handler->variables[handler->vars] = var;
handler->var_names[handler->vars++] = name;
} else {
return 1;
}
return 0;
}
char op_chars[OP_AMOUNT + 1] = " =+-/*%";
int _op_null(int a, int b) { return 0; }
int _op_set(int a, int b) { return b; }
int _op_add(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;
}
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;
}
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
char _message_buffer[MESSAGE_BUFFER_SZ];
char *events_parse_string(EventHandler *handler, char *message) {
size_t message_pos = 0;
char in_token = 0;
char var_name[TOKEN_MAX_SZ];
size_t name_pos = 0;
Operation var_op = OP_NULL;
char num[TOKEN_MAX_SZ];
size_t num_pos = 0;
Token tok_type = T_NULL;
char c;
size_t i, n;
int *var;
for(i = 0; i < strlen(message); i++) {
c = message[i];
if(c == '`') {
in_token = !in_token;
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])) {
var = handler->variables[n];
if(var_op) {
*var = _operations[var_op](*var, atoi(num));
}
break;
}
}
}
/* Reset everything */
tok_type = T_NULL;
name_pos = 0;
var_op = OP_NULL;
num_pos = 0;
}
} 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(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(c == '$') {
tok_type = T_VAR_EDIT;
}
}
}
_message_buffer[MIN(message_pos, MESSAGE_BUFFER_SZ)] = '\0';
return _message_buffer;
}

60
src/events.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef EVENTS_H
#define EVENTS_H
/* The max amount of variables that can be bound. */
#define MAX_VARIABLES 32
/* The max. size of the message buffer.
* WARNING: Bigger messages will be truncated! */
#define MESSAGE_BUFFER_SZ 1024
/* The maximal size of a token. Bigger tokens will be truncated. */
#define TOKEN_MAX_SZ 1024
typedef struct {
int *variables[MAX_VARIABLES];
char *var_names[MAX_VARIABLES];
unsigned int vars;
} EventHandler;
typedef enum { T_NULL, T_VAR_EDIT, T_AMOUNT } Token;
typedef enum {
OP_NULL,
OP_SET,
OP_ADD,
OP_SUB,
OP_DIV,
OP_MUL,
OP_MOD,
OP_AMOUNT
} Operation;
/* events_init_handler()
*
* Initialize an event handler.
* handler: The Event handler to initialize.
*/
void events_init_handler(EventHandler *handler);
/* events_bind_variable()
*
* Bind a variable. Binding a variable allows it to be modified by messages
* passed to the event handler using tags written as following:
* `variable+number` (The backticks delimit the tag). Available operators:
* '=': Assign a value to the variable.
* '+': Addition.
* '-': Substraction.
* '*': Multiplication.
* '/': Division.
* '%': Modulo.
* handler: The event handler.
* var: A pointer to the variable to bind.
* name: The name of the variable. This is the name that will be used to
* refer to this variable in a tag.
*/
int events_bind_variable(EventHandler *handler, int *var, char *name);
/* events_parse_string()
* handler: The event handler.
* message: The message to parse.
*/
char *events_parse_string(EventHandler *handler, char *message);
#endif

View file

@ -1,77 +1,69 @@
#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;
extern Dialog *dialogRPG;
extern NPC *npcRPG;
extern uint32_t nbNPC;
// extern NPC *npcRPG;
// extern uint32_t nbNPC;
#define MAX_INTERACTION_DISTANCE 12
#define MAX_INTERACTION_DISTANCE 12
void interaction_available(Game *game) {
uint32_t i;
void game_logic(Game *game) {
/*NPCs take priority over signs*/
update_npc( game );
for(uint32_t i = 0; i < game->map_level->nbNPC; i++) {
if(!game->map_level->npcs[i].has_dialog)
continue;
/* we check if interactions are possible close to the player */
for( uint32_t i=0; i<game->map_level->nbextradata; i++ )
{
/* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */
if ( (abs((int) game->player.wx -
(int) game->map_level->extradata[i].x*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& (abs((int) game->player.wy -
(int) game->map_level->extradata[i].y*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& strcmp( game->map_level->extradata[i].type, "NPC") !=0 )
{
if((abs((int)game->player.x -
(int)(game->map_level->npcs[i].curx >> PRECISION) * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE) &&
(abs((int)game->player.y -
(int)(game->map_level->npcs[i].cury >> PRECISION) * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE)) {
/* the player can do something */
game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */
game->player.whichAction = i;
/* this is an interraction with a NPC */
game->player.isInteractingWithNPC = true;
return;
}
}
for(i = 0; i < game->map_level->nbSign; i++) {
/* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */
if((abs((int)game->player.x -
(int)game->map_level->signs[i].x * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE) &&
(abs((int)game->player.y -
(int)game->map_level->signs[i].y * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE)) {
/* the player can do something */
game->player.canDoSomething = true;
/* we mark the action for future treatment in player_action() */
game->player.whichAction = i;
/* this is not an interraction with a NPC */
game->player.isInteractingWithNPC = false;
return;
}
}
for( uint32_t i=0; i<nbNPC; i++ )
{
/* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */
if ( (abs((int) game->player.wx -
(int) npcRPG[i].curx*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& (abs((int) game->player.wy -
(int) npcRPG[i].cury*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& strcmp( game->map_level->extradata[i].type, "NPC") !=0 )
{
/* the player can do something */
game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */
game->player.whichAction = i;
/* this is not an interraction with a NPC */
game->player.isInteractingWithNPC = true;
return;
}
}
/* else nothing to be done here */
game->player.canDoSomething = false;
game->player.whichAction = -1;
@ -79,47 +71,101 @@ void game_logic(Game *game) {
return;
}
void game_logic(Game *game) {
void render_indicator(Game *game)
{
/* nothing to do for the player so we quit */
if (game->player.canDoSomething==false)
return;
update_npcs(game);
/* else we draw a small indicator on the screen */
dimage(5, 5, &SignAction_img);
/* we check if interactions are possible close to the player */
interaction_available(game);
}
void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */
if(game->player.canDoSomething)
dimage(5, 5, &SignAction_img);
int i;
Player *player = &game->player;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
dimage(5, 5, &SignAction_img);
break;
}
}
}
void draw(Game *game) {
void game_draw(Game *game) {
/* Draw everything. */
render_map_by_layer(game, BACKGROUND);
npc_draw( game );
dclear(C_WHITE);
map_render_by_layer(game, BACKGROUND);
npc_draw(game);
player_draw(game);
render_map_by_layer(game, FOREGROUND);
render_indicator( game );
map_render_by_layer(game, FOREGROUND);
game_render_indicator(game);
/*DEBUG*/
dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life);
dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y);
}
/* Key management */
void get_inputs(Game *game) {
key_event_t ev;
while((ev = pollevent()).type != KEYEV_NONE){
/**/
}
void game_get_inputs(Game *game) {
clearevents();
/* Key binding for the Player action */
/*************************************/
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();
}
}
Player *player = &game->player;
if(keydown(KEY_SHIFT)) {
int i;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
Portal *dest_portal = (Portal *)portal->portal;
Collider dest_collider = dest_portal->collider;
Map *dest_map = (Map *)portal->map;
player->x = (dest_collider.x1 + dest_collider.x2) / 2 * PXSIZE;
player->y = (dest_collider.y1 + dest_collider.y2) / 2 * PXSIZE;
game->map_level = dest_map;
/* TODO: Make something cleaner */
while(keydown(KEY_SHIFT)) {
clearevents();
sleep();
}
}
}
}
/* Display Debug Information on screen */
#if DEBUGMODE
@ -134,13 +180,13 @@ void 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,49 +1,41 @@
#ifndef GAME_H
#define GAME_H
#include "events.h"
#include <gint/display.h>
#include <stdint.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,
P_CENTER = 0,
P_RIGHTDOWN = 1
} Checkpos;
typedef enum { P_LEFTUP = -1, P_CENTER = 0, P_RIGHTDOWN = 1 } Checkpos;
typedef struct {
uint32_t x1, y1;
uint32_t x2, y2;
} Collider;
/* 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 in 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. */
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;
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*/
@ -61,47 +53,77 @@ typedef struct {
int32_t nextOther;
} Dialog;
typedef struct {
/* position of the item */
uint32_t x;
uint32_t y;
/* its name */
/*id of it's icon*/
uint32_t icon;
char *name;
/* its class (NPC, SGN, INFO, ... )*/
char *type;
/* the ID of the first element of the dialog */
/* (to be aligned with "dialogs.json" IDs)*/
uint32_t dialogID;
/* 0 if imperative dialog (story mode) */
/* or 1 if the player need to press [SHIFT] to initiate the sequence*/
/*if the dialog is interactive or not*/
uint32_t needAction;
} Sign;
typedef struct {
/* current coordinates of the NPC */
uint32_t curx;
uint32_t cury;
/* initial coordinates of the NPC (needed to get absolute coordinates of
* path) */
uint32_t x;
uint32_t y;
/* id of it's face */
uint16_t face;
uint8_t paused;
uint8_t has_dialog;
/* the ID of the first element of the dialog */
/* (to be aligned with "dialogs.json" IDs)*/
uint32_t dialogID;
/*if the dialog is interactive or not*/
uint32_t needAction;
char *name;
/* data for NPC's trajectories */
uint32_t hasPath;
uint32_t path_length;
uint32_t currentPoint;
int16_t *xpath;
int16_t *ypath;
/* ... this can be extended as per needs ... */
} ExtraData;
int type : 32;
uint8_t current_group;
uint8_t hostile_to_group;
uint16_t __padding;
} NPC;
typedef struct {
Collider collider;
/* The destination portal */
void *portal;
/* The destination map */
void *map;
} Portal;
typedef struct {
/* width, height and the number of layer of the map */
uint32_t x;
uint32_t y;
uint32_t w;
uint32_t h;
uint32_t nblayers;
uint32_t tileset_size;
/* world coordinates of the upper left and bootom right*/
/* corners of the current map to be multiplied in game by PXSIZE */
uint32_t xmin;
uint32_t ymin;
uint32_t xmax;
uint32_t ymax;
/* the tileset to use */
bopti_image_t *tileset;
@ -109,11 +131,14 @@ typedef struct {
/* this is given by the layer Walkable of the map in Tiled */
uint8_t *walkable;
/* structure that contains all the items on the map to interract with */
/* each portion of the map has its own list to avoid scrutinizing too much */
/* data when lloking for proximity of items */
uint32_t nbextradata;
ExtraData *extradata;
uint32_t nbNPC;
NPC *npcs;
uint32_t nbSign;
Sign *signs;
uint32_t nbPortal;
Portal *portals;
/* structure that contains all the dialogs for that part of the map */
uint32_t nbdialogsdata;
@ -121,16 +146,16 @@ typedef struct {
/* list of all the tiles to draw the background and the foreground layers */
uint16_t *layers[];
} 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 (see player.h). */
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 */
bool exittoOS;
@ -145,20 +170,33 @@ typedef struct {
bool debug_map;
bool debug_player;
bool debug_extra;
int mana; /* Only for testing events TODO: Remove this! */
} Game;
/* (Mibi88) TODO: Describe what this function is doing. */
void game_logic(Game *game);
/* Draws everything on screen. */
void draw(Game *game);
/* game_draw()
*
* Draws everything on screen.
* game: The game struct.
*/
void game_draw(Game *game);
/* This render a small sign on the upper lecft corner of the screen */
/* if the player can do an action */
void render_indicator(Game *game);
/* game_render_indicator()
*
* This render a small sign on the upper left corner of the screen
* if the player can do an action
* game: The game struct.
*/
void game_render_indicator(Game *game);
/* Handle key presses. */
void get_inputs(Game *game);
/* game_get_inputs()
*
* Handle key presses.
* game: The game struct.
*/
void game_get_inputs(Game *game);
#endif

View file

@ -1,83 +1,86 @@
#include "config.h"
#include <fxlibc/printf.h>
#include <gint/cpu.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <gint/cpu.h>
#include <fxlibc/printf.h>
#include "config.h"
#include "npc.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>
#endif //GRAYMODEOK
#include <gint/gray.h>
#endif // GRAYMODEOK
#include <stdint.h>
#include <stdbool.h>
#if DEBUGMODE
#include <gint/gdb.h>
#endif /*DEBUGMODE*/
#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},
false, false, false, 0
{12 * PXSIZE, 36 * PXSIZE, 0, 0, 100, SPEED, false, 0, false, false, true},
{{}, {}, 0},
false,
false,
false,
0,
/* debug variables*/
, false, false, false
};
false,
false,
false,
100};
/* screen capture management code */
/* 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
@ -89,48 +92,51 @@ int update_time(void) {
}
int main(void) {
#if DEBUGMODE
gdb_start_on_exception();
#endif /*DEBUGMODE*/
__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, &game.mana, "mana");
reload_npc(&game);
#if USB_FEATURE
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
usb_open(interfaces, GINT_CALL_NULL);
#endif
// reload_npc(&game);
#if USB_FEATURE
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
usb_open(interfaces, GINT_CALL_NULL);
#endif
/* start grayscale engine */
#if GRAYMODEOK
dgray(DGRAY_ON);
#endif
#if GRAYMODEOK
dgray(DGRAY_ON);
#endif
/*
showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true);
int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0);
if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true);
else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true);
else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true);
*/
#if DEBUGMODE
dupdate();
getkey();
#endif
do{
do {
/* clear screen */
dclear(C_WHITE);
/* render the map */
draw(&game);
game_draw(&game);
#if DEBUGMODE && FXCG50
/*#if DEBUGMODE && GINT_RENDER_RGB
if (game.debug_map)
{
dfont( NULL );
@ -141,7 +147,7 @@ int main(void) {
dprint(10, 20, C_RED, "Map[%d] : Xmn %d Ymn %d Xmx %d Ymx %d",
1, worldRPG[1]->xmin, worldRPG[1]->ymin,
worldRPG[1]->xmax, worldRPG[1]->ymax);
dprint(10, 30, C_RED, "Map[%d] : Xmn %d Ymn %d Xmx %d Ymx %d",
dprint(10, 30, C_RED, "Map[%d] : Xmn %d Ymn %d Xmx %d Ymx %d",
2, worldRPG[2]->xmin, worldRPG[2]->ymin,
worldRPG[2]->xmax, worldRPG[2]->ymax);
dprint(10, 40, C_RED, "Map[%d] : Xmn %d Ymn %d Xmx %d Ymx %d",
@ -160,14 +166,15 @@ int main(void) {
{
dfont( NULL );
for (int i=0; i<game.map_level->nbextradata; i++ )
dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %d - ID: %d - S: %c",
game.map_level->extradata[i].x,
dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %d - ID: %d
- S: %c", game.map_level->extradata[i].x,
game.map_level->extradata[i].y,
game.map_level->extradata[i].dialogID,
game.map_level->dialogs[ game.map_level->extradata[i].dialogID ].ID,
game.map_level->dialogs[ game.map_level->extradata[i].dialogID ].conclusion1[0] );
game.map_level->dialogs[
game.map_level->extradata[i].dialogID ].ID, game.map_level->dialogs[
game.map_level->extradata[i].dialogID ].conclusion1[0] );
}
#endif
#endif*/
/* start the logic of the game */
game_logic(&game);
@ -175,33 +182,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 */
get_inputs(&game);
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;
}

196
src/map.c
View file

@ -1,14 +1,22 @@
#include "map.h"
#include "config.h"
#include "game.h"
#include <gint/display.h>
#include <gint/keyboard.h>
extern Map *worldRPG[];
//extern ExtraData *extraRPG[];
extern Map level0;
extern Map level1;
extern Map level2;
extern Map level3;
extern Map level4;
Map *worldRPG[] = {&level0, &level1, &level2, &level3, &level4, NULL};
void render_map(Game *game) {
// extern ExtraData *extraRPG[];
void map_render(Game *game) {
Map *map_level = game->map_level;
Player *player = &game->player;
@ -25,9 +33,10 @@ void render_map(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 */
@ -39,62 +48,62 @@ void render_map(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);
}
@ -104,8 +113,8 @@ void render_map(Game *game) {
}
}
void render_map_by_layer(Game *game, int layer) {
void map_render_by_layer(Game *game, int layer) {
Map *map_level = game->map_level;
Player *player = &game->player;
@ -121,9 +130,10 @@ void render_map_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 */
@ -131,109 +141,101 @@ void render_map_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];
/* 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);
}
}
}
}
}
short int get_tile(Game *game, int x, int y, int l) {
short int map_get_tile(Game *game, int x, int y, int l) {
Map *map_level = game->map_level;
/* 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 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;
/* 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 *get_map_for_coordinates( Game *game, int x, int y )
{
/* check if the current map contains the point */
if (x>= (int)game->map_level->xmin && x< (int)game->map_level->xmax &&
y>= (int)game->map_level->ymin && y< (int)game->map_level->ymax)
return game->map_level;
/* else we check in worldRPG if there is a mal containing that point */
Map *map_get_for_tile(Game *game, int x, int y) {
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)
return current;
Map *map = worldRPG[i];
do {
int rx = x - map->x;
int ry = y - map->y;
if(rx >= 0 && rx < (int)map->w && ry >= 0 && ry < (int)map->h) {
return map;
}
i++;
current = worldRPG[i];
}
while (current!=NULL);
/* else we return NULL cause the point is a not within a map */
return NULL;
}
map = worldRPG[i];
} while(map != NULL);
return game->map_level;
}

View file

@ -1,39 +1,55 @@
#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 */
/* Draws the map map on the entire screen to be viewed by the player player. */
void render_map(Game *game);
/* Draws the map layer on the entire screen to be viewed by the player player.
/* map_render()
*
* Draws the map map on the entire screen to be viewed by the player player.
* game: The game struct.
*/
void render_map_by_layer(Game *game, int layer);
void map_render(Game *game);
/* Get the tile at (x, y) of the map map. If the tile is located outside of the
* screen, MAP_OUTSIDE is returned. */
short int get_tile(Game *game, int x, int y, int l);
/* map_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.
*/
void map_render_by_layer(Game *game, int layer);
/* Returns what is in the walkable layer at (x, y). */
short int get_walkable(Game *game, int x, int y);
/* map_get_tile()
*
* Get the tile at (x, y) of the map map. If the tile is located outside of the
* screen, MAP_OUTSIDE is returned.
* game: The game struct.
* x: The coordinates of the tile.
* y: The coordinates of the tile.
* l: The layer of the tile.
*/
short int map_get_tile(Game *game, int x, int y, int l);
/* return the pointer to the map containing the given position */
Map* get_map_for_coordinates(Game *game, int x, int y );
/* map_get_walkable()
*
* Returns what is in the walkable layer at (x, y).
* game: The game struct.
* x: The coordinates of the tile.
* y: The coordinates of the tile.
*/
short int map_get_walkable(Game *game, int x, int y);
Map *map_get_for_tile(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

@ -1,12 +1,11 @@
#include "memory.h"
bool is_in(short int *array, short int array_length, short int item) {
bool memory_is_in(short int *array, short int array_length, short int item) {
short int i;
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

@ -2,8 +2,13 @@
#define MEMORY_H
#include <stdbool.h>
bool is_in(short int *array, short int array_length, short int item);
/* memory_is_in()
*
* returns true if item is in array.
* array: The array to search in.
* array_length: The length of the array.
* item: The item to search for.
*/
bool memory_is_in(short int *array, short int array_length, short int item);
#endif

405
src/npc.c
View file

@ -1,208 +1,275 @@
#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 tiny_npc_male;
extern bopti_image_t tiny_npc_female;
extern bopti_image_t tiny_npc_milkman;
extern bopti_image_t tiny_npc_police;
extern bopti_image_t demo_PNJ_img;
// NPC *npcRPG;
// uint32_t nbNPC = 0;
float length(float x, float y) { return sqrtf(x * x + y * y); }
/* the color of the text to go to the next dialog phase */
/* it improves readability to have somathing lighter */
#if defined(FXCG50)
#define PATH_COLOR C_RED
#else
#define PATH_COLOR C_BLACK
#endif
NPC *npcRPG;
uint32_t nbNPC = 0;
float length( float x, float y )
{
return sqrtf( x*x+y*y );
int npc_clear_path(NPC *npc) {
npc->currentPoint = 0;
npc->hasPath = 0;
npc->path_length = 0;
free(npc->xpath);
free(npc->ypath);
npc->xpath = malloc(4);
npc->ypath = malloc(4);
if(npc->xpath == NULL || npc->ypath == NULL)
return 1;
return 0;
}
void update_npc( [[maybe_unused]] Game *game)
{
for( uint32_t u=0; u<nbNPC; u++ )
{
/* if the NPC has a path to follow AND is not currently in pause */
/* (talking with the player) */
if (npcRPG[u].hasPath==1 && npcRPG[u].paused==false)
{
float vecX = (float) (npcRPG[u].xpath[ npcRPG[u].currentPoint ] +
npcRPG[u].x) - npcRPG[u].curx;
float vecY = (float) (npcRPG[u].ypath[ npcRPG[u].currentPoint ] +
npcRPG[u].y) - npcRPG[u].cury;
float vecN = length(vecX, vecY);
if (vecN>0.5f)
{
vecX /= vecN*2.0;
vecY /= vecN*2.0;
}
else
{
npcRPG[u].currentPoint++;
npcRPG[u].currentPoint = npcRPG[u].currentPoint % npcRPG[u].path_length;
}
npcRPG[u].curx += vecX;
npcRPG[u].cury += vecY;
}
}
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;
return 0;
}
void reload_npc(Game *game)
{
if (npcRPG!=NULL)
{
free(npcRPG);
npcRPG = NULL;
void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
free(visited);
free(gscore);
free(fscore);
}
}
nbNPC = 0;
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 next = came_from[dest];
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
{
ExtraData *Data = &game->map_level->extradata[u];
unsigned int i;
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */
{
nbNPC++;
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))
goto as_recons_fail;
break;
}
}
npcRPG = (NPC*) malloc( nbNPC * sizeof(NPC) );
int currentNPC=0;
uint16_t tx, ty;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
{
ExtraData *Data = &game->map_level->extradata[u];
// Flip the path because it started from the end
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */
{
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].hasPath = Data->hasPath;
npcRPG[currentNPC].path_length = Data->path_length;
npcRPG[currentNPC].xpath = Data->xpath;
npcRPG[currentNPC].ypath = Data->ypath;
npcRPG[currentNPC].paused = false;
currentNPC++;
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;
}
free(came_from);
npc->hasPath = true;
return 0;
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) {
int32_t i, j;
int32_t w = full_map->w;
int32_t h = full_map->h;
int32_t x = (npc->curx >> PRECISION) / T_WIDTH;
int32_t y = (npc->cury >> PRECISION) / T_HEIGHT;
dest_x /= T_WIDTH;
dest_y /= T_HEIGHT;
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;
npc_clear_path(npc);
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;
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 bscore;
int32_t bx = x;
int32_t by = y;
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;
bscore = fscore[i];
}
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);
}
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;
}
}
}
}
as_clean(visited, gscore, fscore);
free(came_from);
return 3;
}
// Refactoring to make adding complexity cleaner
void update_npcs(Game *game) {
for(uint32_t u = 0; u < game->map_level->nbNPC; u++) {
update_npc(&game->map_level->npcs[u]);
}
}
void update_npc(NPC *npc) {
/* if the NPC has no path or is paused, skip it */
if(!npc->hasPath || npc->paused == true)
return;
float vecX = (float)(npc->xpath[npc->currentPoint] + npc->x) -
(npc->curx >> PRECISION);
float vecY = (float)(npc->ypath[npc->currentPoint] + npc->y) -
(npc->cury >> PRECISION);
float vecN = length(vecX, vecY);
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 * (float)(1 << PRECISION);
npc->cury += vecY * (float)(1 << PRECISION);
}
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<nbNPC; u++) //uint pour enlever un warning
{
NPC *Data = &npcRPG[u];
/* TODO : This is for debugging purpose, JUste to render the path */
/* to be followed by the NPC when this will be implemented */
#if DEBUGMODE
if (Data->hasPath==1) /* this NPC has a trajectory */
{
int NbPoints = Data->path_length+1;
for(int v=0; v<NbPoints; v++)
{
int16_t deltaX1=((int16_t) (Data->x +
Data->xpath[v % NbPoints]) * PXSIZE)
-(int16_t) pl->wx;
int16_t deltaY1=((int16_t) (Data->y +
Data->ypath[v % NbPoints]) * PXSIZE)
-(int16_t) pl->wy;
int16_t deltaX2=((int16_t) (Data->x +
Data->xpath[(v+1) % NbPoints]) * PXSIZE)
-(int16_t) pl->wx;
int16_t deltaY2=((int16_t) (Data->y +
Data->ypath[(v+1) % NbPoints]) * PXSIZE)
-(int16_t) pl->wy;
dline( pl->px + deltaX1, pl->py + deltaY1,
pl->px + deltaX2, pl->py + deltaY2,
PATH_COLOR);
}
}
#endif // DEBUGMODE
for(uint32_t u = 0; u < game->map_level->nbNPC; u++) {
NPC *Data = &game->map_level->npcs[u];
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);
}
}
/* Render the path if in debug*/
#if DEBUGMODE
if(!Data->hasPath)
continue; /* this NPC has a trajectory */
int NbPoints = Data->path_length + 1;
for(int v = 0; v < NbPoints; v++) {
int16_t deltaX1 =
((int16_t)(Data->x + Data->xpath[v % NbPoints]) * PXSIZE) -
(int16_t)pl->wx;
int16_t deltaY1 =
((int16_t)(Data->y + Data->ypath[v % NbPoints]) * PXSIZE) -
(int16_t)pl->wy;
int16_t deltaX2 =
((int16_t)(Data->x + Data->xpath[(v + 1) % NbPoints]) *
PXSIZE) -
(int16_t)pl->wx;
int16_t deltaY2 =
((int16_t)(Data->y + Data->ypath[(v + 1) % NbPoints]) *
PXSIZE) -
(int16_t)pl->wy;
void OLD_npc_draw(Game *game) {
Player *player = &game->player;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
{
ExtraData *Data = &game->map_level->extradata[u];
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */
{
/* TODO : This is for debugging purpose, JUste to render the path */
/* to be followed by the NPC when this will be implemented */
#if DEBUGMODE
if (Data->hasPath==1) /* this NPC has a trajectory */
{
int NbPoints = Data->path_length+1;
for(int v=0; v<NbPoints; v++)
{
int16_t deltaX1=((int16_t) (Data->x + Data->xpath[v % NbPoints]) * PXSIZE)-(int16_t) player->wx;
int16_t deltaY1=((int16_t) (Data->y + Data->ypath[v % NbPoints]) * PXSIZE)-(int16_t) player->wy;
int16_t deltaX2=((int16_t) (Data->x + Data->xpath[(v+1) % NbPoints]) * PXSIZE)-(int16_t) player->wx;
int16_t deltaY2=((int16_t) (Data->y + Data->ypath[(v+1) % NbPoints]) * PXSIZE)-(int16_t) player->wy;
dline( player->px + deltaX1, player->py + deltaY1,
player->px + deltaX2, player->py + deltaY2,
PATH_COLOR);
}
}
#endif // DEBUGMODE
int16_t deltaX=((int16_t) (Data->x * PXSIZE))-(int16_t) player->wx;
int16_t deltaY=((int16_t) (Data->y * PXSIZE))-(int16_t) player->wy;
dimage( player->px-P_WIDTH/2+deltaX,
player->py-P_HEIGHT/2+deltaY,
&demo_PNJ_img);
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
pl->py + deltaY2, PATH_COLOR);
}
#endif // DEBUGMODE
int16_t delX = ((Data->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
int16_t delY = ((Data->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
bopti_image_t *face = npc_sprites[Data->face];
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face);
}
}

Some files were not shown because too many files have changed in this diff Show more