mirror of
https://git.planet-casio.com/Slyvtt/Collab_RPG.git
synced 2024-12-28 04:23:42 +01:00
Moved parts of the converter to another file
This commit is contained in:
parent
ea50bed171
commit
563ed47753
4 changed files with 241 additions and 295 deletions
|
@ -2,240 +2,13 @@ import xml.etree.ElementTree as ET
|
|||
import json
|
||||
import os
|
||||
import sys
|
||||
sys.path.append("../assets/")
|
||||
import fxconv
|
||||
from tiled import *
|
||||
|
||||
VERBOSE = 1
|
||||
SIGN_TYPES = ["INFO", "SGN"]
|
||||
|
||||
# TODO: Add more doc.
|
||||
|
||||
class Tileset:
|
||||
"""
|
||||
Handle the tiled tileset.
|
||||
"""
|
||||
def __init__(self, element: ET.Element, parent_dir = ""):
|
||||
firstgid_str = element.get("firstgid")
|
||||
if firstgid_str == None: raise Exception("firstgid not found!")
|
||||
self.firstgid = int(firstgid_str)
|
||||
self.source = element.get("source")
|
||||
if self.source == None: raise Exception("source not found!")
|
||||
self.source = parent_dir + self.source
|
||||
tree = ET.parse(self.source)
|
||||
self.root = tree.getroot()
|
||||
tilecount_str = self.root.get("tilecount")
|
||||
if tilecount_str == None: raise Exception("tilecount not found!")
|
||||
self.tilecount = int(tilecount_str)
|
||||
columns_str = self.root.get("columns")
|
||||
if columns_str == None: raise Exception("columns not found!")
|
||||
self.columns = int(columns_str)
|
||||
|
||||
def is_raw_in_tileset(self, raw: int) -> bool:
|
||||
if raw >= self.firstgid and raw < self.firstgid+self.tilecount:
|
||||
return True
|
||||
return False
|
||||
def get_tile_from_raw(self, raw: int) -> int:
|
||||
if not self.is_raw_in_tileset(raw) and raw:
|
||||
raise Exception(f"Tile {raw} not in tileset!")
|
||||
return raw-self.firstgid
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
A class to handle a tiled map layer
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
|
||||
def get_width(self) -> int:
|
||||
"""
|
||||
Get the layer width
|
||||
"""
|
||||
value = self.element.get("width")
|
||||
if value == None: raise Exception("Layer width not found")
|
||||
return int(value)
|
||||
|
||||
def get_height(self) -> int:
|
||||
"""
|
||||
Get the layer height
|
||||
"""
|
||||
value = self.element.get("height")
|
||||
if value == None: raise Exception("Layer height not found")
|
||||
return int(value)
|
||||
|
||||
def get_raw_data(self) -> list:
|
||||
"""
|
||||
Get the data of the map
|
||||
"""
|
||||
data_tag = self.element.find("data")
|
||||
if data_tag == None: raise Exception("Data not found!")
|
||||
raw_data = data_tag.text.split(",")
|
||||
int_data = []
|
||||
for tile in raw_data:
|
||||
int_data.append(int(tile))
|
||||
return int_data
|
||||
def get_data_with_tileset(self, tileset: Tileset):
|
||||
raw_data = self.get_raw_data()
|
||||
out_data = []
|
||||
for i in raw_data:
|
||||
out_data.append(tileset.get_tile_from_raw(i))
|
||||
return out_data
|
||||
|
||||
class Object:
|
||||
"""
|
||||
An group object (see ObjectGroup) object.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.name = element.get("name")
|
||||
if self.name == None: raise Exception("Name attribute missing!")
|
||||
self.type = element.get("type")
|
||||
if self.type == None:
|
||||
self.type = ""
|
||||
if VERBOSE: print("WARNING: Type attribute missing!")
|
||||
x_str = element.get("x")
|
||||
if x_str == None: raise Exception("X attribute missing!")
|
||||
self.x = int(float(x_str))
|
||||
y_str = element.get("y")
|
||||
if y_str == None: raise Exception("Y attribute missing!")
|
||||
self.y = int(float(y_str))
|
||||
self.id = element.get("id")
|
||||
if self.id == None: raise Exception("ID attribute missing!")
|
||||
|
||||
def __get_point(self) -> list:
|
||||
# Private method to get a point. Used in get_data.
|
||||
return [self.x, self.y]
|
||||
|
||||
def __get_polyline(self) -> list:
|
||||
# Private method to get a polyline. Used in get_data.
|
||||
data = self.element.find("polyline").get("points")
|
||||
if data == None: raise Exception("Data not found!")
|
||||
data = data.replace(' ', ',').split(',')
|
||||
out_data = []
|
||||
for i in data:
|
||||
out_data.append(int(float(i)))
|
||||
return out_data
|
||||
|
||||
def get_data(self) -> list:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return self.__get_point()
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return self.__get_polyline()
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_data_type(self) -> str:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return "point"
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return "polyline"
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get the value of a property.
|
||||
"""
|
||||
properties = self.element.find("properties")
|
||||
if properties == None: raise Exception("Properties not found!")
|
||||
for i in properties:
|
||||
if i.get("name") == property:
|
||||
value = i.get("value")
|
||||
if value == None: raise Exception("Property value not found!")
|
||||
return value
|
||||
raise Exception(f"Property {property} not found!")
|
||||
|
||||
class ObjectGroup:
|
||||
"""
|
||||
Handle tiled object groups. They can contain points, lines and other
|
||||
geometric shapes that can be very handy to add NPCs, the path they walk on,
|
||||
as we do it here, in Collab_RPG.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.objects = []
|
||||
for object in self.element.iterfind("object"):
|
||||
self.objects.append(Object(object))
|
||||
|
||||
|
||||
|
||||
class Map:
|
||||
"""
|
||||
A class to handle the tiled maps.
|
||||
"""
|
||||
def __init__(self, input: str):
|
||||
"""
|
||||
Loads a tmx map made with tiled.
|
||||
"""
|
||||
tree = ET.parse(input)
|
||||
self.root = tree.getroot()
|
||||
self.parent_dir = os.path.abspath(input).rpartition('/')[0]
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get a map property.
|
||||
"""
|
||||
properties = self.root.find("properties")
|
||||
# If properties wasn't found.
|
||||
if properties == None:
|
||||
raise Exception("Properties not found!")
|
||||
for child in properties:
|
||||
# Look at the name attribute of each property
|
||||
if child.get("name") == property:
|
||||
value = child.get("value")
|
||||
if value == None: raise Exception("Value attribute not found!")
|
||||
return value
|
||||
# The dialog file property wasn't found.
|
||||
raise Exception(f"\"{property}\" property not found!")
|
||||
|
||||
def get_layer_by_id(self, layer_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("id") == layer_id:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_layer_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("name") == name:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_objectgroup_by_id(self, group_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("id") == group_id:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_objectgroup_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("name") == name:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_tileset_by_firstgid(self, firstgid: int) -> Tileset:
|
||||
for tileset in self.root.iterfind("tileset"):
|
||||
if tileset.get("firstgid") == str(firstgid):
|
||||
return Tileset(tileset, self.parent_dir + "/")
|
||||
raise Exception("Tileset not found!")
|
||||
|
||||
def convert(input, output, params, target):
|
||||
if params["custom-type"] == "tmx":
|
||||
convert_map(input, output, params, target)
|
||||
|
@ -251,6 +24,8 @@ def convert_map(input, output, params, target):
|
|||
background_layer = []
|
||||
foreground_layer = []
|
||||
walkable_layer = []
|
||||
map_x = 0
|
||||
map_y = 0
|
||||
width = 0
|
||||
height = 0
|
||||
outdoor_tileset = None
|
||||
|
@ -393,14 +168,12 @@ def convert_map(input, output, params, target):
|
|||
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)
|
||||
map_struct += fxconv.u32(0)
|
||||
map_struct += fxconv.u32(0)
|
||||
map_struct += fxconv.u32(0)
|
||||
map_struct += fxconv.u32(0)
|
||||
tileset_name = os.path.splitext(os.path.basename(outdoor_tileset.source))[0]
|
||||
map_struct += fxconv.ref(f"img_{tileset_name}")
|
||||
|
||||
|
|
231
assets/tiled.py
231
assets/tiled.py
|
@ -0,0 +1,231 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
import os
|
||||
|
||||
# TODO: Add more doc.
|
||||
|
||||
class Tileset:
|
||||
"""
|
||||
Handle the tiled tileset.
|
||||
"""
|
||||
def __init__(self, element: ET.Element, parent_dir = ""):
|
||||
firstgid_str = element.get("firstgid")
|
||||
if firstgid_str == None: raise Exception("firstgid not found!")
|
||||
self.firstgid = int(firstgid_str)
|
||||
self.source = element.get("source")
|
||||
if self.source == None: raise Exception("source not found!")
|
||||
self.source = parent_dir + self.source
|
||||
tree = ET.parse(self.source)
|
||||
self.root = tree.getroot()
|
||||
tilecount_str = self.root.get("tilecount")
|
||||
if tilecount_str == None: raise Exception("tilecount not found!")
|
||||
self.tilecount = int(tilecount_str)
|
||||
columns_str = self.root.get("columns")
|
||||
if columns_str == None: raise Exception("columns not found!")
|
||||
self.columns = int(columns_str)
|
||||
|
||||
def is_raw_in_tileset(self, raw: int) -> bool:
|
||||
if raw >= self.firstgid and raw < self.firstgid+self.tilecount:
|
||||
return True
|
||||
return False
|
||||
def get_tile_from_raw(self, raw: int) -> int:
|
||||
if not self.is_raw_in_tileset(raw) and raw:
|
||||
raise Exception(f"Tile {raw} not in tileset!")
|
||||
return raw-self.firstgid
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
A class to handle a tiled map layer
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
|
||||
def get_width(self) -> int:
|
||||
"""
|
||||
Get the layer width
|
||||
"""
|
||||
value = self.element.get("width")
|
||||
if value == None: raise Exception("Layer width not found")
|
||||
return int(value)
|
||||
|
||||
def get_height(self) -> int:
|
||||
"""
|
||||
Get the layer height
|
||||
"""
|
||||
value = self.element.get("height")
|
||||
if value == None: raise Exception("Layer height not found")
|
||||
return int(value)
|
||||
|
||||
def get_raw_data(self) -> list:
|
||||
"""
|
||||
Get the data of the map
|
||||
"""
|
||||
data_tag = self.element.find("data")
|
||||
if data_tag == None: raise Exception("Data not found!")
|
||||
raw_data = data_tag.text.split(",")
|
||||
int_data = []
|
||||
for tile in raw_data:
|
||||
int_data.append(int(tile))
|
||||
return int_data
|
||||
def get_data_with_tileset(self, tileset: Tileset):
|
||||
raw_data = self.get_raw_data()
|
||||
out_data = []
|
||||
for i in raw_data:
|
||||
out_data.append(tileset.get_tile_from_raw(i))
|
||||
return out_data
|
||||
|
||||
class Object:
|
||||
"""
|
||||
An group object (see ObjectGroup) object.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.name = element.get("name")
|
||||
if self.name == None: raise Exception("Name attribute missing!")
|
||||
self.type = element.get("type")
|
||||
if self.type == None:
|
||||
self.type = ""
|
||||
print("WARNING: Type attribute missing!")
|
||||
x_str = element.get("x")
|
||||
if x_str == None: raise Exception("X attribute missing!")
|
||||
self.x = int(float(x_str))
|
||||
y_str = element.get("y")
|
||||
if y_str == None: raise Exception("Y attribute missing!")
|
||||
self.y = int(float(y_str))
|
||||
self.id = element.get("id")
|
||||
if self.id == None: raise Exception("ID attribute missing!")
|
||||
|
||||
def __get_point(self) -> list:
|
||||
# Private method to get a point. Used in get_data.
|
||||
return [self.x, self.y]
|
||||
|
||||
def __get_polyline(self) -> list:
|
||||
# Private method to get a polyline. Used in get_data.
|
||||
data = self.element.find("polyline").get("points")
|
||||
if data == None: raise Exception("Data not found!")
|
||||
data = data.replace(' ', ',').split(',')
|
||||
out_data = []
|
||||
for i in data:
|
||||
out_data.append(int(float(i)))
|
||||
return out_data
|
||||
|
||||
def get_data(self) -> list:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return self.__get_point()
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return self.__get_polyline()
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_data_type(self) -> str:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return "point"
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return "polyline"
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get the value of a property.
|
||||
"""
|
||||
properties = self.element.find("properties")
|
||||
if properties == None: raise Exception("Properties not found!")
|
||||
for i in properties:
|
||||
if i.get("name") == property:
|
||||
value = i.get("value")
|
||||
if value == None: raise Exception("Property value not found!")
|
||||
return value
|
||||
raise Exception(f"Property {property} not found!")
|
||||
|
||||
class ObjectGroup:
|
||||
"""
|
||||
Handle tiled object groups. They can contain points, lines and other
|
||||
geometric shapes that can be very handy to add NPCs, the path they walk on,
|
||||
as we do it here, in Collab_RPG.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.objects = []
|
||||
for object in self.element.iterfind("object"):
|
||||
self.objects.append(Object(object))
|
||||
|
||||
|
||||
|
||||
class Map:
|
||||
"""
|
||||
A class to handle the tiled maps.
|
||||
"""
|
||||
def __init__(self, input: str):
|
||||
"""
|
||||
Loads a tmx map made with tiled.
|
||||
"""
|
||||
tree = ET.parse(input)
|
||||
self.root = tree.getroot()
|
||||
self.parent_dir = os.path.abspath(input).rpartition('/')[0]
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get a map property.
|
||||
"""
|
||||
properties = self.root.find("properties")
|
||||
# If properties wasn't found.
|
||||
if properties == None:
|
||||
raise Exception("Properties not found!")
|
||||
for child in properties:
|
||||
# Look at the name attribute of each property
|
||||
if child.get("name") == property:
|
||||
value = child.get("value")
|
||||
if value == None: raise Exception("Value attribute not found!")
|
||||
return value
|
||||
# The dialog file property wasn't found.
|
||||
raise Exception(f"\"{property}\" property not found!")
|
||||
|
||||
def get_layer_by_id(self, layer_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("id") == layer_id:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_layer_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("name") == name:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_objectgroup_by_id(self, group_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("id") == group_id:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_objectgroup_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("name") == name:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_tileset_by_firstgid(self, firstgid: int) -> Tileset:
|
||||
for tileset in self.root.iterfind("tileset"):
|
||||
if tileset.get("firstgid") == str(firstgid):
|
||||
return Tileset(tileset, self.parent_dir + "/")
|
||||
raise Exception("Tileset not found!")
|
|
@ -117,18 +117,13 @@ typedef struct {
|
|||
|
||||
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;
|
||||
|
||||
|
|
57
src/player.c
57
src/player.c
|
@ -87,8 +87,8 @@ void player_move(Game *game, Direction direction) {
|
|||
player->y += dy;
|
||||
}
|
||||
|
||||
player->wx = game->map_level->xmin * PXSIZE + player->x;
|
||||
player->wy = game->map_level->ymin * PXSIZE + player->y;
|
||||
player->wx = game->map_level->x * T_WIDTH * PXSIZE + player->x;
|
||||
player->wy = game->map_level->y * T_HEIGHT * PXSIZE + player->y;
|
||||
}
|
||||
|
||||
void player_action(Game *game) {
|
||||
|
@ -168,59 +168,6 @@ bool player_collision(Game *game, Direction direction,
|
|||
int player_tile_x = player->x + dx;
|
||||
int player_tile_y = player->y + dy;
|
||||
|
||||
/* check where the player is expected to go on the next move */
|
||||
/* if outside the map, we check if there is a map on the other */
|
||||
/* side of the current map*/
|
||||
if(0) {
|
||||
// if(map_get_walkable(game, player_tile_x, player_tile_y) ==
|
||||
// MAP_OUTSIDE) {
|
||||
// we compute the expected world coordinates accordingly
|
||||
// while taking care of the scaling between fx and cg models (PXSIZE)
|
||||
int worldX = (player->wx + dx) / PXSIZE;
|
||||
int worldY = (player->wy + dy) / PXSIZE;
|
||||
Map *map = map_get_for_coordinates(game, worldX, worldY);
|
||||
if(map != NULL && map != game->map_level) {
|
||||
Map *backupmap = game->map_level;
|
||||
int backupx = player->x;
|
||||
int backupy = player->y;
|
||||
int backupwx = player->wx;
|
||||
int backupwy = player->wy;
|
||||
|
||||
game->map_level = map;
|
||||
|
||||
player->wx = worldX * PXSIZE;
|
||||
player->wy = worldY * PXSIZE;
|
||||
|
||||
player->x = (worldX - map->xmin) * PXSIZE;
|
||||
player->y = (worldY - map->ymin) * PXSIZE;
|
||||
|
||||
int on_walkable = map_get_walkable(game, player->x / T_WIDTH,
|
||||
player->y / T_HEIGHT);
|
||||
|
||||
int speed = (on_walkable >= 0 && on_walkable < WALKABLE_TILE_MAX)
|
||||
? walkable_speed[on_walkable]
|
||||
: 0;
|
||||
|
||||
/* if he's on a hard tile and we need to revert the changes as */
|
||||
/* tile on the next side of the border is not walkable */
|
||||
|
||||
if(!speed) {
|
||||
game->map_level = backupmap;
|
||||
player->x = backupx;
|
||||
player->y = backupy;
|
||||
player->wx = backupwx;
|
||||
player->wy = backupwy;
|
||||
return true; /* He will collide with it. */
|
||||
}
|
||||
|
||||
/* we update the list of NPCs in the current map */
|
||||
/* to follow the trajectories */
|
||||
// reload_npc(game);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a negative position differently than a positive one. */
|
||||
if(player_tile_x < 0)
|
||||
player_tile_x = player_tile_x / T_WIDTH - 1;
|
||||
|
|
Loading…
Reference in a new issue