From 563ed477531e73301156920c5f70ea3cbf17e53c Mon Sep 17 00:00:00 2001 From: mibi88 <76903855+mibi88@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:06:00 +0200 Subject: [PATCH] Moved parts of the converter to another file --- assets/converters.py | 239 ++----------------------------------------- assets/tiled.py | 231 +++++++++++++++++++++++++++++++++++++++++ src/game.h | 9 +- src/player.c | 57 +---------- 4 files changed, 241 insertions(+), 295 deletions(-) diff --git a/assets/converters.py b/assets/converters.py index f2340d3..5ee1245 100644 --- a/assets/converters.py +++ b/assets/converters.py @@ -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}") diff --git a/assets/tiled.py b/assets/tiled.py index e69de29..03fe645 100644 --- a/assets/tiled.py +++ b/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!") diff --git a/src/game.h b/src/game.h index 4e8627e..306c464 100644 --- a/src/game.h +++ b/src/game.h @@ -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; diff --git a/src/player.c b/src/player.c index b81a424..8957bb3 100644 --- a/src/player.c +++ b/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;