Merge branch 'master' of gitea.planet-casio.com:Slyvtt/Collab_RPG
|
@ -13,4 +13,5 @@ __pycache__/
|
|||
*.sublime-workspace
|
||||
.vscode
|
||||
|
||||
*.json
|
||||
level*.json
|
||||
tilesetnpp.json
|
||||
|
|
|
@ -25,6 +25,7 @@ set(SOURCES
|
|||
src/memory.c
|
||||
src/game.c
|
||||
src/dialogs.c
|
||||
src/npc.c
|
||||
# ...
|
||||
)
|
||||
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
||||
|
|
|
@ -13,11 +13,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 (sauts de lignes et mots plus grands que l'écran pas supportés)
|
||||
- [ ] Fontes de caractères
|
||||
- [ ] Interaction
|
||||
- [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] Fontes de caractères
|
||||
- [x] Interaction
|
||||
- [ ] NPC
|
||||
- [x] Changement de map durant le jeu
|
||||
- [ ] Système d'événements
|
||||
|
||||
|
||||
## Crédits
|
||||
|
||||
|
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 650 B |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 683 B |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
@ -1,44 +1,18 @@
|
|||
demo_player.png:
|
||||
type: bopti-image
|
||||
name: demo_player_img
|
||||
*.png:
|
||||
custom-type: custom-image
|
||||
name_regex: (.*)\.png \1_img
|
||||
profile: p8
|
||||
scale: 2
|
||||
|
||||
demo_PNJ.png:
|
||||
type: bopti-image
|
||||
name: demo_PNJ_img
|
||||
profile: p8
|
||||
|
||||
player_face.png:
|
||||
type: bopti-image
|
||||
name: player_face_img
|
||||
profile: p8
|
||||
|
||||
SignAction.png:
|
||||
type: bopti-image
|
||||
name: SignAction_img
|
||||
profile: p8
|
||||
|
||||
INFO_Icon.png:
|
||||
type: bopti-image
|
||||
name: INFO_Icon_img
|
||||
profile: p8
|
||||
|
||||
NPC_Icon.png:
|
||||
type: bopti-image
|
||||
name: NPC_Icon_img
|
||||
profile: p8
|
||||
|
||||
SGN_Icon.png:
|
||||
type: bopti-image
|
||||
name: SGN_Icon_img
|
||||
profile: p8
|
||||
demo_PNG.png:
|
||||
scale: 1
|
||||
|
||||
font.png:
|
||||
name: fontRPG
|
||||
type: font
|
||||
custom-type: font
|
||||
charset: print
|
||||
grid.size: 10x10
|
||||
grid.padding: 2
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
height: 10
|
||||
height: 10
|
||||
|
|
Before Width: | Height: | Size: 246 B After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 875 B After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,134 @@
|
|||
{ "dialogs":[
|
||||
{ "ID":0,
|
||||
"dialog":"Bienvenue a Toi, l'Ami, dans cette magnifique ville de Nabrouch. Comme tu peux le constater, les habitants ne sont pas tres nombreux et ont tendance a se terrer dans leur maison depuis la revolution. Il faut dire que les Anciens dirigeants, bien qu'exiles, exercent encore une certaine forme de pouvoir ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":1
|
||||
},
|
||||
{
|
||||
"ID":1,
|
||||
"dialog":"Depuis la mort de ton Pere, la region a bien change ... Enfin, surtout ses habitants. Tu devras te mefier de tout le monde.",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":2
|
||||
},
|
||||
{
|
||||
"ID":2,
|
||||
"dialog":"Tu devrais commencer par rejoindre la taverne que ton pere t'a laisse en heritage.",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":3,
|
||||
"dialog":"Taverne de Pue Le Bouc",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":4,
|
||||
"dialog":"Tiens !! Quelqu'un est mort ici. Tu le connais ?",
|
||||
"isQuestion":1,
|
||||
"choice":"Oui$Non",
|
||||
"conclusion1":"C'est bien triste mon Ami.`$life-2``$power-5`",
|
||||
"next1":-1,
|
||||
"conclusion2":"Dommage quand meme pour Lui.",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":5,
|
||||
"dialog":"Salut Hero !! Quel bon vent t'ammene ici a Nabrouch ?",
|
||||
"isQuestion":1,
|
||||
"choice":"De Passage$La Famille",
|
||||
"conclusion1":"Entre donc te reposer dans la taverne, c'est la seule du coin.",
|
||||
"next1":-1,
|
||||
"conclusion2":"Fais bien attention alors.",
|
||||
"next2":6,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":6,
|
||||
"dialog":"On dit qu'il se passe des choses étranges par ici depuis quelques temps. Fais bien attention a Toi.",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":7,
|
||||
"dialog":"Salut Hero, je suis le cremier. Veux tu me delester un peu ?",
|
||||
"isQuestion":1,
|
||||
"choice":"Oui$Non",
|
||||
"conclusion1":"Voici donc pour toi`$life+5``$mana+5``$power+2`",
|
||||
"next1":-1,
|
||||
"conclusion2":"Bon bah casse toi ...",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":8,
|
||||
"dialog":"Le Sanctuaire Maudit ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":9,
|
||||
"dialog":"Etrange ce coffre abandonne et ouvert ... Fouiller dedans ?",
|
||||
"isQuestion":1,
|
||||
"choice":"Oui$Non",
|
||||
"conclusion1":"Trop cool, du stuff `$life+5``$mana+5``$power+2`",
|
||||
"next1":-1,
|
||||
"conclusion2":"Je ferai mieux de partir loin ...",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":10,
|
||||
"dialog":"Et sa tombe est en train d'etre creusee ?",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":11
|
||||
},
|
||||
{
|
||||
"ID":11,
|
||||
"dialog":"Beaucoup de morts pour une si petite bourgade ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{ "dialogs":[
|
||||
{ "ID":0,
|
||||
"dialog":"Le tombeau du Chevalier Legendaire",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":3
|
||||
},
|
||||
{
|
||||
"ID":1,
|
||||
"dialog":"Salut, je suis le gardien du Tombeau. As-tu remarque quelque chose d'etrange en venant ici ?",
|
||||
"isQuestion":1,
|
||||
"choice":"Rien de special$Des pas dans les bois",
|
||||
"conclusion1":"Ok, soit prudent tout de meme",
|
||||
"next1":2,
|
||||
"conclusion2":"Je vais finir mon tour de ronde et verifier",
|
||||
"next2":2,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":2,
|
||||
"dialog":"A bientot l'ami et prend garde aux brigands.",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":3,
|
||||
"dialog":"Ce Hero de la Revolution a marque le pays de son Aura. Peut-etre aurais-je la meme destinee ... ",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{ "dialogs":[
|
||||
{ "ID":0,
|
||||
"dialog":"Encore une tombe ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":1,
|
||||
"dialog":"Un passage souterrain ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":2
|
||||
},
|
||||
{
|
||||
"ID":2,
|
||||
"dialog":"Je me demande bien ou il peut conduire. Une prochaine expedition a faire peut-etre ...",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
},
|
||||
{
|
||||
"ID":3,
|
||||
"dialog":"C'est la maison du gardien du cimetiere",
|
||||
"isQuestion":0,
|
||||
"choice":"_",
|
||||
"conclusion1":"_",
|
||||
"next1":-1,
|
||||
"conclusion2":"_",
|
||||
"next2":-1,
|
||||
"nextOther":-1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"dialogs": [
|
||||
{
|
||||
"ID": 0,
|
||||
"dialog": "Maison du Fermier",
|
||||
"isQuestion": 0,
|
||||
"choice": "_",
|
||||
"conclusion1": "_",
|
||||
"next1": -1,
|
||||
"conclusion2": "_",
|
||||
"next2": -1,
|
||||
"nextOther": -1
|
||||
},
|
||||
{
|
||||
"ID": 1,
|
||||
"dialog": "Maison du Marechal Ferrand",
|
||||
"isQuestion": 0,
|
||||
"choice": "_",
|
||||
"conclusion1": "_",
|
||||
"next1": -1,
|
||||
"conclusion2": "_",
|
||||
"next2": -1,
|
||||
"nextOther": -1
|
||||
},
|
||||
{
|
||||
"ID": 2,
|
||||
"dialog": "Maison du Boucher",
|
||||
"isQuestion": 0,
|
||||
"choice": "_",
|
||||
"conclusion1": "_",
|
||||
"next1": -1,
|
||||
"conclusion2": "_",
|
||||
"next2": -1,
|
||||
"nextOther": -1
|
||||
},
|
||||
{
|
||||
"ID": 3,
|
||||
"dialog": "Maison du Boulanger",
|
||||
"isQuestion": 0,
|
||||
"choice": "_",
|
||||
"conclusion1": "_",
|
||||
"next1": -1,
|
||||
"conclusion2": "_",
|
||||
"next2": -1,
|
||||
"nextOther": -1
|
||||
},
|
||||
{
|
||||
"ID": 4,
|
||||
"dialog": "Maison du Maire",
|
||||
"isQuestion": 0,
|
||||
"choice": "_",
|
||||
"conclusion1": "_",
|
||||
"next1": -1,
|
||||
"conclusion2": "_",
|
||||
"next2": -1,
|
||||
"nextOther": -1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,18 +1,29 @@
|
|||
from random import randint
|
||||
from PIL import Image
|
||||
import fxconv
|
||||
import json
|
||||
import pathlib
|
||||
import csv
|
||||
import os
|
||||
|
||||
|
||||
def convert(input, output, params, target):
|
||||
if params["custom-type"] == "map":
|
||||
#convert_map(input, output, params, target)
|
||||
#return 0
|
||||
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
|
||||
|
||||
|
@ -62,20 +73,8 @@ def convert_world(input, output, params, target):
|
|||
print( "Map = ", map )
|
||||
structWorld += fxconv.ptr( map )
|
||||
|
||||
#ext = get_extra_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax )
|
||||
#print( "Data = ", ext )
|
||||
#if (ext!=fxconv.u32(0)): structExtra += fxconv.ptr( ext )
|
||||
|
||||
structWorld += fxconv.u32(0)
|
||||
|
||||
#structExtra += fxconv.u32(0)
|
||||
"""
|
||||
#and all the extra data (PNJ, SGN, ...)
|
||||
fxconv.elf_multi(
|
||||
[("_" + params["varMapData"], structWorld),
|
||||
("_" + params["varExtraData"], structExtra)],
|
||||
output, **target)
|
||||
"""
|
||||
#generate !
|
||||
fxconv.elf(structWorld, output, "_" + params["name"], **target)
|
||||
|
||||
|
@ -123,10 +122,10 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
|||
#create the structure of the map
|
||||
structMap = fxconv.Structure()
|
||||
|
||||
structMap += fxconv.u16(w) + fxconv.u16(h) + fxconv.u16(nbTilelayer)
|
||||
structMap += fxconv.u16(tileset_size)
|
||||
structMap += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(nbTilelayer)
|
||||
structMap += fxconv.u32(tileset_size)
|
||||
|
||||
structMap += fxconv.u16(xmin) + fxconv.u16(ymin) + fxconv.u16(xmax) + fxconv.u16(ymax)
|
||||
structMap += fxconv.u32(xmin) + fxconv.u32(ymin) + fxconv.u32(xmax) + fxconv.u32(ymax)
|
||||
|
||||
structMap += fxconv.ref(f"img_{nameTilesetFree}")
|
||||
|
||||
|
@ -150,6 +149,8 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
|||
structMap += fxconv.ptr(walk_data)
|
||||
|
||||
|
||||
|
||||
|
||||
nbextra = 0
|
||||
extradata = fxconv.Structure()
|
||||
|
||||
|
@ -163,6 +164,26 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
|||
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
|
||||
|
||||
|
||||
|
@ -208,8 +229,7 @@ def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
|||
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")
|
||||
|
||||
|
@ -230,24 +250,156 @@ def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
|||
#create the structure of the map
|
||||
structData = fxconv.Structure()
|
||||
|
||||
|
||||
nbExtraData = 0
|
||||
layer = data["layers"][layer_extradata]
|
||||
for i in layer["objects"]:
|
||||
nbExtraData = nbExtraData + 1
|
||||
x = i["x"] + xmin
|
||||
y = i["y"] + ymin
|
||||
nme = i["name"]
|
||||
|
||||
#get the type of the item
|
||||
tpe = i["type"]
|
||||
for j in i["properties"]:
|
||||
stg = j[ "value" ]
|
||||
print( "OBJECT X= ", x, " Y= ", y, "STR= ", stg )
|
||||
|
||||
#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 )
|
||||
|
||||
structData += fxconv.u16( int(x) )
|
||||
structData += fxconv.u16( int(y) )
|
||||
structData += fxconv.string( nme )
|
||||
structData += fxconv.string( tpe )
|
||||
structData += fxconv.string( stg )
|
||||
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)
|
|
@ -1,11 +1,7 @@
|
|||
# *.json:
|
||||
# custom-type: map
|
||||
# name_regex: (.*)\.json map_\1
|
||||
|
||||
|
||||
WorldRPG.world:
|
||||
custom-type: world
|
||||
#name: xxx #unused but mandatory (Do not touch)
|
||||
#varMapData: worldRPG
|
||||
#varExtraData: extraRPG
|
||||
name: worldRPG
|
||||
|
||||
#DialogsRPG.json:
|
||||
# custom-type: dialogs
|
||||
# name: dialogRPG
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
<?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="9">
|
||||
<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="12">
|
||||
<editorsettings>
|
||||
<export target="level0.json" format="json"/>
|
||||
</editorsettings>
|
||||
<properties>
|
||||
<property name="dialogFile" type="file" value="DialogsLvl0.json"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="tilesetnpp.tsx"/>
|
||||
<tileset firstgid="409" source="Walkable.tsx"/>
|
||||
<layer id="1" name="Background" width="48" height="24">
|
||||
|
@ -92,37 +95,64 @@
|
|||
<objectgroup id="4" name="ExtraData">
|
||||
<object id="1" name="INFO3" type="INFO" x="232" y="79.75">
|
||||
<properties>
|
||||
<property name="dialog" value="Etrange ce coffre ouvert ..."/>
|
||||
<property name="dialogID" type="int" value="9"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="8" name="INFO2" type="INFO" x="119.75" y="47.25">
|
||||
<properties>
|
||||
<property name="dialog" value="Et sa tombe est en train d'etre creusee ...^"/>
|
||||
<property name="dialogID" type="int" value="10"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="7" name="INFO2" type="INFO" x="52" y="44">
|
||||
<object id="7" name="INFO1" type="INFO" x="52" y="44">
|
||||
<properties>
|
||||
<property name="dialog" value="Quelqu'un est mort ici ..."/>
|
||||
<property name="dialogID" type="int" value="4"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="2" name="PNJ1" type="NPC" x="252" y="164">
|
||||
<object id="2" name="PNJ2" type="NPC" x="164" y="132">
|
||||
<properties>
|
||||
<property name="dialog" value="Salut, je suis un PNJ"/>
|
||||
<property name="dialogID" type="int" value="5"/>
|
||||
<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="10" name="PNJ1" type="NPC" x="252" y="164">
|
||||
<properties>
|
||||
<property name="dialogID" type="int" value="7"/>
|
||||
<property name="hasPath" type="int" value="1"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
<property name="path" type="object" value="9"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="4" name="SGN1" type="SGN" x="96" y="136">
|
||||
<properties>
|
||||
<property name="dialog" value="Indication sur le panneau. Bienvenue dans la maison du Tondu ..."/>
|
||||
<property name="dialogID" type="int" value="3"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="5" name="SGN2" type="SGN" x="288" y="128">
|
||||
<properties>
|
||||
<property name="dialog" value="Indication sur le panneau. Entree dans le Sanctuaire Maudit ..."/>
|
||||
<property name="dialogID" type="int" value="8"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="9" name="Chemin Crémier" type="TRJ" x="251.967" y="164.12">
|
||||
<polyline points="0,0 -72.25,-18.5 -171.75,-19 -172.5,-99.25 -206.25,-122.75 -140.75,-114.75 -175.25,-97.5 -174.5,-33 -148.25,-20.5 -73.25,-20.25 39,-30.25 81.25,-45 79.25,-24.5"/>
|
||||
</object>
|
||||
<object id="11" name="DébutHistoire" type="INFO" x="18.6666" y="42.6667">
|
||||
<properties>
|
||||
<property name="dialogID" type="int" value="0"/>
|
||||
<property name="needAction" type="int" value="0"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="2">
|
||||
<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">
|
||||
<properties>
|
||||
<property name="dialogFile" type="file" value="DialogsLvl1.json"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="tilesetnpp.tsx"/>
|
||||
<tileset firstgid="409" source="Walkable.tsx"/>
|
||||
<layer id="1" name="Background" width="48" height="24">
|
||||
|
@ -89,9 +92,26 @@
|
|||
<objectgroup id="4" name="ExtraData">
|
||||
<object id="1" name="INFO1" type="INFO" x="303.75" y="143.25">
|
||||
<properties>
|
||||
<property name="dialog" value="Le tombeau du Chevalier Legendaire"/>
|
||||
<property name="dialogID" type="int" value="0"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="2" name="Gardien" type="NPC" x="303.636" y="117.273">
|
||||
<properties>
|
||||
<property name="dialogID" type="int" value="1"/>
|
||||
<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">
|
||||
<properties>
|
||||
<property name="dialogID" type="int" value="0"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -31.2727,-11.0909 -87.2727,-16.1818 -100.909,-6.72727 -100.182,28.9091 -72.3636,32.7273 -11.4546,37.8181 42.5455,42.5454 75.4546,22.9091 77.4545,1.45453 32.3636,-0.727273"/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="5">
|
||||
<properties>
|
||||
<property name="dialogFile" type="file" value="DialogsLvl2.json"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="tilesetnpp.tsx"/>
|
||||
<tileset firstgid="409" source="Walkable.tsx"/>
|
||||
<layer id="1" name="Background" width="48" height="24">
|
||||
|
@ -89,19 +92,22 @@
|
|||
<objectgroup id="4" name="ExtraData">
|
||||
<object id="1" name="INFO1" type="INFO" x="128" y="87.5">
|
||||
<properties>
|
||||
<property name="dialog" value="Encore une tombe ..."/>
|
||||
<property name="dialogID" type="int" value="0"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="2" name="INFO2" type="INFO" x="262.75" y="49">
|
||||
<properties>
|
||||
<property name="dialog" value="Un passage souterrain ..."/>
|
||||
<property name="dialogID" type="int" value="1"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="3" name="SGN1" type="SGN" x="296" y="143.75">
|
||||
<properties>
|
||||
<property name="dialog" value="C'est la maison du gardien du cimetiere"/>
|
||||
<property name="dialogID" type="int" value="3"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="6">
|
||||
<properties>
|
||||
<property name="dialogFile" type="file" value="DialogsLvl3.json"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="tilesetnpp.tsx"/>
|
||||
<tileset firstgid="409" source="Walkable.tsx"/>
|
||||
<layer id="1" name="Background" width="48" height="24">
|
||||
|
@ -13,21 +16,21 @@
|
|||
325,313,290,265,313,265,241,290,313,314,290,241,313,290,325,2,330,331,332,333,333,333,333,333,334,335,336,132,2,2,2,2,2,2,2,86,87,88,186,187,188,189,90,91,92,132,2,2,
|
||||
349,2,2,2,2,2,2,2,2,2,2,2,2,2,349,2,162,163,164,162,163,164,165,162,163,164,165,132,2,297,298,299,300,2,2,110,111,112,210,211,212,213,114,115,116,133,2,2,
|
||||
387,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,86,87,88,186,187,188,189,86,87,88,92,132,2,2,2,2,2,385,2,2,2,2,2,265,266,2,2,2,2,2,2,2,
|
||||
2,2,258,259,260,261,261,262,263,264,2,21,22,23,24,2,110,111,112,210,211,212,213,110,111,112,116,133,386,241,241,313,241,313,266,265,266,266,265,289,290,2,160,161,385,2,2,387,
|
||||
2,2,282,283,284,285,285,286,287,288,2,45,46,47,48,2,2,2,2,2,265,266,2,2,2,2,2,313,290,265,313,265,313,266,290,289,290,265,266,313,314,2,2,2,2,2,2,2,
|
||||
2,2,306,307,308,309,309,310,311,312,131,69,70,71,72,2,266,265,266,266,265,386,160,161,2,386,2,265,265,266,241,2,258,259,260,261,261,262,263,264,2,2,2,2,2,2,2,2,
|
||||
2,2,258,259,260,261,261,262,263,264,2,21,22,23,24,2,110,111,112,210,211,212,213,110,111,112,116,133,2,241,241,313,241,313,266,265,266,266,265,289,290,2,160,161,385,2,2,387,
|
||||
2,2,282,283,284,285,285,286,287,288,2,45,46,47,48,2,2,2,2,2,265,266,2,2,2,2,2,2,2,265,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,306,307,308,309,309,310,311,312,131,69,70,71,72,2,2,2,2,2,265,386,160,161,2,386,2,2,2,266,241,2,258,259,260,261,261,262,263,264,2,2,2,2,2,2,2,2,
|
||||
386,2,330,331,332,333,333,334,335,336,132,2,2,2,2,266,290,289,290,265,266,290,266,265,266,266,265,289,289,290,386,2,282,283,284,285,285,286,287,288,2,2,2,2,2,2,2,2,
|
||||
2,2,162,163,165,162,163,163,165,165,132,2,313,290,265,313,265,2,2,2,2,2,290,289,290,265,266,313,313,314,241,2,306,307,308,309,309,310,311,312,131,2,2,2,2,2,2,2,
|
||||
2,2,86,87,88,186,187,188,189,92,132,2,265,266,266,2,258,259,260,261,261,261,261,261,261,262,263,264,2,265,266,2,330,331,332,333,333,334,335,336,132,2,2,2,2,2,2,2,
|
||||
2,2,110,111,112,210,211,212,213,116,133,2,289,290,2,2,282,283,284,285,285,285,285,285,285,286,287,288,2,289,290,2,162,163,164,162,163,164,165,165,132,2,2,297,298,299,300,2,
|
||||
2,2,2,2,2,2,265,266,2,2,2,386,313,314,2,2,306,307,308,309,309,309,309,309,309,310,311,312,131,241,265,2,86,87,88,186,187,188,189,92,132,2,2,2,2,2,2,2,
|
||||
2,2,2,386,2,2,289,290,160,161,2,2,265,266,2,2,330,331,332,333,333,333,333,333,333,334,335,336,132,266,266,2,110,111,112,210,211,212,213,116,133,2,2,2,2,2,386,2,
|
||||
2,2,2,2,2,2,313,314,289,265,266,290,289,290,2,2,162,163,164,165,162,163,164,162,163,163,165,165,132,265,266,241,2,2,2,2,265,266,2,2,2,2,2,2,2,2,386,2,
|
||||
265,266,266,265,386,313,265,266,265,266,313,314,313,314,266,2,86,87,88,90,90,87,88,186,187,188,189,92,132,289,289,290,266,265,266,266,289,290,2,160,161,2,21,22,23,24,2,2,
|
||||
289,290,265,266,290,2,2,2,2,2,2,2,266,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,241,313,314,290,289,290,265,313,314,2,386,2,2,45,46,47,48,2,2,
|
||||
2,2,162,163,165,162,163,163,165,165,132,2,2,290,265,313,2,2,2,2,2,2,2,2,2,2,2,2,2,314,241,2,306,307,308,309,309,310,311,312,131,2,2,2,2,2,2,2,
|
||||
2,2,86,87,88,186,187,188,189,92,132,2,2,266,266,2,258,259,260,261,261,261,261,261,261,262,263,264,2,265,266,2,330,331,332,333,333,334,335,336,132,2,2,2,2,2,2,2,
|
||||
2,2,110,111,112,210,211,212,213,116,133,2,2,290,2,2,282,283,284,285,285,285,285,285,285,286,287,288,2,289,290,2,162,163,164,162,163,164,165,165,132,2,2,297,298,299,300,2,
|
||||
2,2,2,2,2,2,265,266,2,2,2,386,2,314,2,2,306,307,308,309,309,309,309,309,309,310,311,312,131,241,265,2,86,87,88,186,187,188,189,92,132,2,2,2,2,2,2,2,
|
||||
2,2,2,386,2,2,289,290,160,161,2,2,2,266,2,2,330,331,332,333,333,333,333,333,333,334,335,336,132,266,266,2,110,111,112,210,211,212,213,116,133,2,2,2,2,2,386,2,
|
||||
2,2,2,2,2,2,313,314,2,2,2,2,2,290,2,2,162,163,164,165,162,163,164,162,163,163,165,165,132,265,266,241,2,2,2,2,265,266,2,2,2,2,2,2,2,2,386,2,
|
||||
265,266,266,265,386,313,265,266,265,266,313,314,313,314,2,2,86,87,88,90,90,87,88,186,187,188,189,92,132,289,289,290,266,265,266,266,289,290,2,160,161,2,21,22,23,24,2,2,
|
||||
289,290,265,266,290,2,2,2,2,2,2,2,2,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,2,2,2,2,2,2,2,2,2,2,386,2,2,45,46,47,48,2,2,
|
||||
2,2,2,2,2,2,2,2,2,386,2,2,2,265,266,2,2,2,2,2,2,2,2,2,265,266,2,2,2,2,345,346,347,348,2,339,340,2,2,2,2,2,69,70,71,72,2,2,
|
||||
2,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,313,314,290,289,290,265,266,290,289,290,265,313,314,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,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
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Foreground" width="48" height="24">
|
||||
|
@ -89,31 +92,36 @@
|
|||
<objectgroup id="4" name="ExtraData">
|
||||
<object id="1" name="SGN5" type="SGN" x="224" y="183.25">
|
||||
<properties>
|
||||
<property name="dialog" value="Maison du Maire"/>
|
||||
<property name="dialogID" type="int" value="4"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="5" name="SGN4" type="SGN" x="320.5" y="159.25">
|
||||
<properties>
|
||||
<property name="dialog" value="Maison du Boulanger"/>
|
||||
<property name="dialogID" type="int" value="3"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="3" name="SGN3" type="SGN" x="184.25" y="95.75">
|
||||
<properties>
|
||||
<property name="dialog" value="Maison du Boucher"/>
|
||||
<property name="dialogID" type="int" value="2"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="4" name="SGN2" type="SGN" x="343.75" y="80">
|
||||
<properties>
|
||||
<property name="dialog" value="Maison du Marechal Ferrand"/>
|
||||
<property name="dialogID" type="int" value="1"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
<object id="2" name="SGN1" type="SGN" x="71.75" y="143.25">
|
||||
<properties>
|
||||
<property name="dialog" value="Maison du Fermier"/>
|
||||
<property name="dialogID" type="int" value="0"/>
|
||||
<property name="needAction" type="int" value="1"/>
|
||||
</properties>
|
||||
<point/>
|
||||
</object>
|
||||
|
|
3
clean
|
@ -1,5 +1,6 @@
|
|||
cd assets
|
||||
rm -f *.json
|
||||
rm -f level*.json
|
||||
rm -f tilesetnpp.json
|
||||
rm -r __pycache__
|
||||
cd ..
|
||||
rm -r build-cg
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#define USB_FEATURE 0
|
||||
|
||||
#define DEBUGMODE 1
|
||||
#define DEBUGMODE 0
|
||||
|
||||
#ifdef FXCG50
|
||||
#define T_HEIGHT 16
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "game.h"
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
@ -19,6 +24,14 @@ extern font_t fontRPG;
|
|||
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
|
||||
#endif
|
||||
|
||||
|
||||
void blit()
|
||||
{
|
||||
|
@ -125,15 +138,15 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
|
|||
if(update_screen) blit();
|
||||
while(game->frame_duration < line_duration) sleep();
|
||||
game->frame_duration = 0;
|
||||
/* Ask the user to press EXE to continue. */
|
||||
dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ...");
|
||||
/* Ask the user to press SHIFT to continue. */
|
||||
dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite...");
|
||||
}
|
||||
/* Make a little animation :). */
|
||||
if(update_screen) blit();
|
||||
if(l>=max_lines_amount-1){
|
||||
/* If we drew one entire screen. */
|
||||
/* Wait that the EXE key is pressed if we should. */
|
||||
if(wait_continue) while(getkey().key != KEY_EXE) sleep();
|
||||
/* 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();
|
||||
/* Clear the text area. */
|
||||
drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2,
|
||||
C_WHITE);
|
||||
|
@ -153,11 +166,11 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
|
|||
if(update_screen) blit();
|
||||
while(game->frame_duration < line_duration) sleep();
|
||||
game->frame_duration = 0;
|
||||
/* Ask the user to press EXE to continue. */
|
||||
dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ...");
|
||||
/* Update the screen and wait for EXE being pressed, if needed. */
|
||||
/* Ask the user to press SHIFT to continue. */
|
||||
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().key != KEY_EXE) sleep();
|
||||
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){
|
||||
|
@ -187,8 +200,6 @@ void showtext_dialog(Game *game, bopti_image_t *face, char *text,
|
|||
true, 0, true);
|
||||
}
|
||||
|
||||
#define CHOICE_BOX_HEIGHT 10
|
||||
#define CHOICE_BOX_PADDING_TOP 3
|
||||
|
||||
/* Some variables and pointers used to get some arguments passed in
|
||||
* showtext_dialog_ask in _choice_call_before_end. */
|
||||
|
@ -253,7 +264,7 @@ int _choice_call_before_end(Game *game, unsigned int org_i) {
|
|||
C_BLACK, ">");
|
||||
}
|
||||
blit();
|
||||
key = getkey().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){
|
||||
|
@ -280,9 +291,9 @@ int _choice_call_before_end(Game *game, unsigned int org_i) {
|
|||
/* Move the selection arrow and update the selected item. */
|
||||
selected++;
|
||||
}
|
||||
/* If the user has not validated his choice by pressing EXE, we loop one
|
||||
/* If the user has not validated his choice by pressing SHIFT, we loop one
|
||||
* more time. */
|
||||
}while(key != KEY_EXE);
|
||||
}while(key != KEY_SHIFT);
|
||||
/* Make a little animation because we looove little animations ;) */
|
||||
for(i=DWIDTH/8+1;i>0;i--){
|
||||
/* I'm drawing the same box as on the start animation */
|
||||
|
@ -319,3 +330,47 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start,
|
|||
return showtext_opt(game, face, text, _choice_call_before_end, start, end,
|
||||
_choice_screen_call, 100, true, 0, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void initiate_dialog_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;
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showtext_dialog( game, face, text, true, true );
|
||||
if (nextOther!=-1) initiate_dialog_sequence( game, face, nextOther );
|
||||
}
|
||||
}
|
|
@ -89,4 +89,6 @@ int showtext_dialog_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 );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
#include <gint/cpu.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
#include "npc.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
extern bopti_image_t SignAction_img;
|
||||
|
||||
extern Dialog *dialogRPG;
|
||||
|
||||
|
||||
#define MAX_INTERACTION_DISTANCE 12
|
||||
|
||||
|
@ -58,6 +61,7 @@ void render_indicator(Game *game)
|
|||
void draw(Game *game) {
|
||||
/* Draw everything. */
|
||||
render_map_by_layer(game, BACKGROUND);
|
||||
npc_draw( game );
|
||||
player_draw(game);
|
||||
render_map_by_layer(game, FOREGROUND);
|
||||
render_indicator( game );
|
||||
|
|
58
src/game.h
|
@ -42,33 +42,63 @@ typedef struct {
|
|||
} Player;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t ID;
|
||||
/* data to be shown in the dialog*/
|
||||
char *dialog;
|
||||
/* is it a question or a simple dialog ? */
|
||||
uint32_t isQuestion;
|
||||
/* if it is a question, then the choices for answering */
|
||||
char *choices;
|
||||
/* the conclusion of the dialog for answer 1 and 2 respectively */
|
||||
/* Note : it may contain a set of event with a dedicated syntax */
|
||||
char *conclusion1;
|
||||
int32_t next1;
|
||||
char *conclusion2;
|
||||
int32_t next2;
|
||||
int32_t nextOther;
|
||||
} Dialog;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* position of the item */
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
/* its name */
|
||||
char *name;
|
||||
/* its class (NPC, SGN, INFO, ... )*/
|
||||
char *type;
|
||||
/* data to be shown in the dialog*/
|
||||
char *dialog;
|
||||
|
||||
/* 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*/
|
||||
uint32_t needAction;
|
||||
|
||||
/* data for NPC's trajectories */
|
||||
uint32_t hasPath;
|
||||
uint32_t path_length;
|
||||
uint16_t *xpath;
|
||||
uint16_t *ypath;
|
||||
|
||||
/* ... this can be extended as per needs ... */
|
||||
} ExtraData;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* width, height and the number of layer of the map */
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint16_t nblayers;
|
||||
uint16_t tileset_size;
|
||||
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 */
|
||||
uint16_t xmin;
|
||||
uint16_t ymin;
|
||||
uint16_t xmax;
|
||||
uint16_t ymax;
|
||||
uint32_t xmin;
|
||||
uint32_t ymin;
|
||||
uint32_t xmax;
|
||||
uint32_t ymax;
|
||||
|
||||
/* the tileset to use */
|
||||
bopti_image_t *tileset;
|
||||
|
@ -84,6 +114,10 @@ typedef struct {
|
|||
uint32_t nbextradata;
|
||||
ExtraData *extradata;
|
||||
|
||||
/* structure that contains all the dialogs for that part of the map */
|
||||
uint32_t nbdialogsdata;
|
||||
Dialog *dialogs;
|
||||
|
||||
/* list of all the tiles to draw the background and the foreground layers */
|
||||
uint16_t *layers[];
|
||||
} Map;
|
||||
|
|
10
src/main.c
|
@ -32,7 +32,7 @@ extern Map *worldRPG[];
|
|||
/* Game data (defined in "game.h")*/
|
||||
Game game = {
|
||||
NULL,
|
||||
{12*PXSIZE, 36*PXSIZE, 0, 0, 10*PXSIZE, 48*PXSIZE, 100, SPEED, false, 0, false},
|
||||
{12*PXSIZE, 36*PXSIZE, 0, 0, 12*PXSIZE, 36*PXSIZE, 100, SPEED, false, 0, false},
|
||||
false, false, false, 0
|
||||
|
||||
/* debug variables*/
|
||||
|
@ -108,11 +108,13 @@ int main(void) {
|
|||
dgray(DGRAY_ON);
|
||||
#endif
|
||||
|
||||
/*
|
||||
showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true);
|
||||
int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0);
|
||||
if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true);
|
||||
else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true);
|
||||
else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true);
|
||||
*/
|
||||
|
||||
do{
|
||||
/* clear screen */
|
||||
|
@ -151,10 +153,12 @@ 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: %s",
|
||||
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].dialog );
|
||||
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] );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <gint/display.h>
|
||||
|
||||
extern Map *worldRPG[];
|
||||
extern ExtraData *extraRPG[];
|
||||
//extern ExtraData *extraRPG[];
|
||||
|
||||
|
||||
void render_map(Game *game) {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
#include "npc.h"
|
||||
#include "dialogs.h"
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "config.h"
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h> /*debug*/
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
extern bopti_image_t demo_PNJ_img;
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
void 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef NPC_H
|
||||
#define NPC_H
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "game.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
|
||||
/* Draws the player player. This function should be called after drawing the
|
||||
* map! */
|
||||
void npc_draw(Game *game);
|
||||
|
||||
|
||||
#endif
|
||||
|
32
src/player.c
|
@ -1,5 +1,6 @@
|
|||
#include "player.h"
|
||||
#include "dialogs.h"
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "config.h"
|
||||
#include <gint/display.h>
|
||||
|
@ -26,10 +27,6 @@ const char damage_taken_walkable[WALKABLE_TILE_MAX] = {
|
|||
};
|
||||
|
||||
extern bopti_image_t demo_player_img;
|
||||
extern bopti_image_t NPC_Icon_img;
|
||||
extern bopti_image_t SGN_Icon_img;
|
||||
extern bopti_image_t INFO_Icon_img;
|
||||
|
||||
|
||||
void player_draw(Game *game) {
|
||||
Player *player = &game->player;
|
||||
|
@ -82,6 +79,12 @@ void player_move(Game *game, Direction direction) {
|
|||
}
|
||||
|
||||
|
||||
extern bopti_image_t demo_player_img;
|
||||
extern bopti_image_t NPC_Icon_img;
|
||||
extern bopti_image_t SGN_Icon_img;
|
||||
extern bopti_image_t INFO_Icon_img;
|
||||
|
||||
|
||||
void player_action(Game *game) {
|
||||
if( game->player.isDoingAction ) return; /* alreday doing something */
|
||||
|
||||
|
@ -90,21 +93,26 @@ void player_action(Game *game) {
|
|||
/* we indicate that the player is occupied */
|
||||
game->player.isDoingAction = true;
|
||||
|
||||
/* we collect the information */
|
||||
char *text = game->map_level->extradata[game->player.whichAction].dialog;
|
||||
ExtraData *currentData = &game->map_level->extradata[game->player.whichAction];
|
||||
|
||||
/* we use the correct image as per the class of the item */
|
||||
|
||||
bopti_image_t *face;
|
||||
if (strcmp("INFO", game->map_level->extradata[game->player.whichAction].type)==0)
|
||||
/* we use the correct image as per the class of the item */
|
||||
|
||||
|
||||
if (strcmp("INFO", currentData->type)==0)
|
||||
face = &INFO_Icon_img;
|
||||
else if (strcmp("NPC", game->map_level->extradata[game->player.whichAction].type)==0)
|
||||
else if (strcmp("NPC", currentData->type)==0)
|
||||
face = &NPC_Icon_img;
|
||||
else if (strcmp("SGN", game->map_level->extradata[game->player.whichAction].type)==0)
|
||||
else if (strcmp("SGN", currentData->type)==0)
|
||||
face = &SGN_Icon_img;
|
||||
else face = &demo_player_img;
|
||||
|
||||
/* we treat the action - i.e. we show a dialog */
|
||||
showtext_dialog( game, face, text, true, true );
|
||||
|
||||
uint32_t dialogStart = currentData->dialogID;
|
||||
|
||||
initiate_dialog_sequence( game, face, dialogStart );
|
||||
|
||||
/* when done we release the occupied status of the player */
|
||||
game->player.isDoingAction = false;
|
||||
}
|
||||
|
|