def __init__(self, pos: Tuple[int, int], animated_tex: List[arcade.Texture], scale=1): super().__init__(scale=scale, center_x=pos[0], center_y=pos[1]) i = 0 for tex in animated_tex: self.append_texture(tex) self.frames.append(AnimationKeyframe(i, 80, tex)) i += 1 self.set_texture(0)
def __init__(self, x, y): super().__init__() path = "../resources/objects/animated/flag_100_sprite_green.png" for i in range(10): tex: arcade.Texture = arcade.load_texture(path, x=0, y=i * 100, width=108, height=100) self.append_texture(tex) a = AnimationKeyframe(i, 50, tex) self.frames.append(a) self.update_animation() self.center_x = x self.center_y = y self.scale = 0.25
def _create_sprite_from_tile(map_object, tile: pytiled_parser.objects.Tile, scaling, base_directory: str = None): if base_directory: tmx_file = base_directory + tile.image.source else: tmx_file = tile.image.source if not os.path.exists(tmx_file): tmx_file = Path(map_object.parent_dir, tile.image.source) if not os.path.exists(tmx_file): print(f"Warning: can't file {tmx_file} ") return None # print(f"Creating tile: {tmx_file}") if tile.animation: # my_sprite = AnimatedTimeSprite(tmx_file, scaling) my_sprite: Sprite = AnimatedTimeBasedSprite(tmx_file, scaling) else: image_x = 0 image_y = 0 if tile.tileset.image is not None: row = tile.id_ // tile.tileset.columns image_y = row * tile.tileset.max_tile_size.height col = tile.id_ % tile.tileset.columns image_x = col * tile.tileset.max_tile_size.width if tile.image.size: # Individual image, use image width and height width = tile.image.size.width height = tile.image.size.height else: # Sprite sheet, use max width/height from sheet width = tile.tileset.max_tile_size.width height = tile.tileset.max_tile_size.height my_sprite = Sprite(tmx_file, scaling, image_x, image_y, width, height) if tile.properties is not None and len(tile.properties) > 0: for my_property in tile.properties: my_sprite.properties[my_property.name] = my_property.value # print(tile.image.source, my_sprite.center_x, my_sprite.center_y) if tile.objectgroup is not None: if len(tile.objectgroup) > 1: print( f"Warning, only one hit box supported for tile with image {tile.image.source}." ) for hitbox in tile.objectgroup: points: List[Point] = [] if isinstance(hitbox, pytiled_parser.objects.RectangleObject): if hitbox.size is None: print( f"Warning: Rectangle hitbox created for without a " f"height or width for {tile.image.source}. Ignoring.") continue # print(my_sprite.width, my_sprite.height) sx = hitbox.location[0] - (my_sprite.width / (scaling * 2)) sy = -(hitbox.location[1] - (my_sprite.height / (scaling * 2))) ex = (hitbox.location[0] + hitbox.size[0]) - (my_sprite.width / (scaling * 2)) ey = -((hitbox.location[1] + hitbox.size[1]) - (my_sprite.height / (scaling * 2))) # print(f"Size: {hitbox.size} Location: {hitbox.location}") p1 = [sx, sy] p2 = [ex, sy] p3 = [ex, ey] p4 = [sx, ey] # print(f"w:{my_sprite.width:.1f}, h:{my_sprite.height:.1f}", end=", ") points = [p1, p2, p3, p4] # for point in points: # print(f"({point[0]:.1f}, {point[1]:.1f}) ") # print() elif isinstance(hitbox, pytiled_parser.objects.PolygonObject) \ or isinstance(hitbox, pytiled_parser.objects.PolylineObject): for point in hitbox.points: adj_x = point[0] + hitbox.location[0] - my_sprite.width / ( scaling * 2) adj_y = -(point[1] + hitbox.location[1] - my_sprite.height / (scaling * 2)) adj_point = [adj_x, adj_y] points.append(adj_point) # If we have a polyline, and it is closed, we need to # remove the duplicate end-point if points[0][0] == points[-1][0] and points[0][1] == points[ -1][1]: points.pop() elif isinstance(hitbox, pytiled_parser.objects.ElipseObject): if hitbox.size is None: print( f"Warning: Ellipse hitbox created for without a height " f"or width for {tile.image.source}. Ignoring.") continue # print(f"Size: {hitbox.size} Location: {hitbox.location}") hw = hitbox.size[0] / 2 hh = hitbox.size[1] / 2 cx = hitbox.location[0] + hw cy = hitbox.location[1] + hh acx = cx - (my_sprite.width / (scaling * 2)) acy = cy - (my_sprite.height / (scaling * 2)) # print(f"acx: {acx} acy: {acy} cx: {cx} cy: {cy} hh: {hh} hw: {hw}") total_steps = 8 angles = [ step / total_steps * 2 * math.pi for step in range(total_steps) ] for angle in angles: x = (hw * math.cos(angle) + acx) y = (-(hh * math.sin(angle) + acy)) point = [x, y] points.append(point) # for point in points: # print(f"({point[0]:.1f}, {point[1]:.1f}) ") # print() else: print(f"Warning: Hitbox type {type(hitbox)} not supported.") my_sprite.points = points if tile.animation is not None: key_frame_list = [] for frame in tile.animation: frame_tile = _get_tile_by_id(map_object, tile.tileset, frame.tile_id) if frame_tile: frame_tile.image.source = Path(map_object.parent_dir, frame_tile.image.source) if not os.path.exists(tmx_file): print(f"Warning: can't file {tmx_file} ") return None key_frame = AnimationKeyframe(frame.tile_id, frame.duration, frame_tile.image) key_frame_list.append(key_frame) # print(f"Add tile {frame.tile_id} for keyframe. Source: {frame_tile.image.source}") cast(AnimatedTimeBasedSprite, my_sprite).frames = key_frame_list return my_sprite
def _create_sprite_from_tile(map_object: pytiled_parser.objects.TileMap, tile: pytiled_parser.objects.Tile, scaling: float = 1.0, base_directory: str = None, hit_box_algorithm="Simple", hit_box_detail: float = 4.5): """ Given a tile from the parser, see if we can create a sprite from it """ # --- Step 1, find a reference to an image this is going to be based off of map_source = map_object.tmx_file map_directory = os.path.dirname(map_source) image_file = _get_image_source(tile, base_directory, map_directory) # print(f"Creating tile: {tmx_file}") if tile.animation: # my_sprite = AnimatedTimeSprite(tmx_file, scaling) my_sprite: Sprite = AnimatedTimeBasedSprite(image_file, scaling) else: image_x, image_y, width, height = _get_image_info_from_tileset(tile) my_sprite = Sprite(image_file, scaling, image_x, image_y, width, height, flipped_horizontally=tile.flipped_horizontally, flipped_vertically=tile.flipped_vertically, flipped_diagonally=tile.flipped_diagonally, hit_box_algorithm=hit_box_algorithm, hit_box_detail=hit_box_detail) if tile.properties is not None and len(tile.properties) > 0: for my_property in tile.properties: my_sprite.properties[my_property.name] = my_property.value if tile.type_: my_sprite.properties['type'] = tile.type_ # print(tile.image.source, my_sprite.center_x, my_sprite.center_y) if tile.objectgroup is not None: if len(tile.objectgroup) > 1: print( f"Warning, only one hit box supported for tile with image {tile.image.source}." ) for hitbox in tile.objectgroup: points: List[Point] = [] if isinstance(hitbox, pytiled_parser.objects.RectangleObject): if hitbox.size is None: print( f"Warning: Rectangle hitbox created for without a " f"height or width for {tile.image.source}. Ignoring.") continue # print(my_sprite.width, my_sprite.height) sx = hitbox.location[0] - (my_sprite.width / (scaling * 2)) sy = -(hitbox.location[1] - (my_sprite.height / (scaling * 2))) ex = (hitbox.location[0] + hitbox.size[0]) - (my_sprite.width / (scaling * 2)) ey = -((hitbox.location[1] + hitbox.size[1]) - (my_sprite.height / (scaling * 2))) # print(f"Size: {hitbox.size} Location: {hitbox.location}") p1 = [sx, sy] p2 = [ex, sy] p3 = [ex, ey] p4 = [sx, ey] # print(f"w:{my_sprite.width:.1f}, h:{my_sprite.height:.1f}", end=", ") points = [p1, p2, p3, p4] # for point in points: # print(f"({point[0]:.1f}, {point[1]:.1f}) ") # print() elif isinstance(hitbox, pytiled_parser.objects.PolygonObject) \ or isinstance(hitbox, pytiled_parser.objects.PolylineObject): for point in hitbox.points: adj_x = point[0] + hitbox.location[0] - my_sprite.width / ( scaling * 2) adj_y = -(point[1] + hitbox.location[1] - my_sprite.height / (scaling * 2)) adj_point = [adj_x, adj_y] points.append(adj_point) # If we have a polyline, and it is closed, we need to # remove the duplicate end-point if points[0][0] == points[-1][0] and points[0][1] == points[ -1][1]: points.pop() elif isinstance(hitbox, pytiled_parser.objects.ElipseObject): if hitbox.size is None: print( f"Warning: Ellipse hitbox created for without a height " f"or width for {tile.image.source}. Ignoring.") continue # print(f"Size: {hitbox.size} Location: {hitbox.location}") hw = hitbox.size[0] / 2 hh = hitbox.size[1] / 2 cx = hitbox.location[0] + hw cy = hitbox.location[1] + hh acx = cx - (my_sprite.width / (scaling * 2)) acy = cy - (my_sprite.height / (scaling * 2)) # print(f"acx: {acx} acy: {acy} cx: {cx} cy: {cy} hh: {hh} hw: {hw}") total_steps = 8 angles = [ step / total_steps * 2 * math.pi for step in range(total_steps) ] for angle in angles: x = (hw * math.cos(angle) + acx) y = (-(hh * math.sin(angle) + acy)) point = [x, y] points.append(point) # for point in points: # print(f"({point[0]:.1f}, {point[1]:.1f}) ") # print() else: print(f"Warning: Hitbox type {type(hitbox)} not supported.") my_sprite.set_hit_box(points) if tile.animation is not None: # Animated image key_frame_list = [] # Loop through each frame for frame in tile.animation: # Get the tile for the frame frame_tile = _get_tile_by_id(map_object, tile.tileset, frame.tile_id) if frame_tile: image_file = _get_image_source(frame_tile, base_directory, map_directory) # Does the tile have an image? if frame_tile.image: # Yes, use it texture = load_texture(image_file) else: # No image for tile? Pull from tilesheet image_x, image_y, width, height = _get_image_info_from_tileset( frame_tile) texture = load_texture(image_file, image_x, image_y, width, height) key_frame = AnimationKeyframe(frame.tile_id, frame.duration, texture) key_frame_list.append(key_frame) # If this is the first texture in the animation, go ahead and # set it as the current texture. if len(key_frame_list) == 1: my_sprite.texture = key_frame.texture # print(f"Add tile {frame.tile_id} for keyframe. Source: {frame_tile.image.source}") cast(AnimatedTimeBasedSprite, my_sprite).frames = key_frame_list return my_sprite
def _create_sprite_from_tile(map_object, tile: pytiled_parser.objects.Tile, scaling, base_directory: str = ""): tmx_file = base_directory + tile.image.source # print(f"Creating tile: {tmx_file}") if tile.animation: # my_sprite = AnimatedTimeSprite(tmx_file, scaling) my_sprite = AnimatedTimeBasedSprite(tmx_file, scaling) else: my_sprite = Sprite(tmx_file, scaling) if tile.properties is not None and len(tile.properties) > 0: for my_property in tile.properties: my_sprite.properties[my_property.name] = my_property.value # print(tile.image.source, my_sprite.center_x, my_sprite.center_y) if tile.objectgroup is not None: if len(tile.objectgroup) > 1: print(f"Warning, only one hit box supported for tile with image {tile.image.source}.") for hitbox in tile.objectgroup: half_width = map_object.tile_size.width / 2 half_height = map_object.tile_size.height / 2 points = [] if isinstance(hitbox, pytiled_parser.objects.RectangleObject): if hitbox.size is None: print(f"Warning: Rectangle hitbox created for without a " f"height or width for {tile.image.source}. Ignoring.") continue p1 = [hitbox.location[0] - half_width, half_height - hitbox.location[0]] p2 = [hitbox.location[0] + hitbox.size[0] - half_width, half_height - hitbox.size[0]] p3 = [hitbox.location[0] + hitbox.size[0] - half_width, half_height - (hitbox.location[1] + hitbox.size[1])] p4 = [hitbox.location[0] - half_width, half_height - (hitbox.location[1] + hitbox.size[1])] points = [p4, p3, p2, p1] elif isinstance(hitbox, pytiled_parser.objects.PolygonObject): for point in hitbox.points: adj_x = point[0] + hitbox.location[0] - half_width adj_y = half_height - (point[1] + hitbox.location[1]) adj_point = [adj_x, adj_y] points.append(adj_point) elif isinstance(hitbox, pytiled_parser.objects.PolylineObject): for point in hitbox.points: adj_x = point[0] + hitbox.location[0] - half_width adj_y = half_height - (point[1] + hitbox.location[1]) adj_point = [adj_x, adj_y] points.append(adj_point) # If we have a polyline, and it is closed, we need to # remove the duplicate end-point if points[0][0] == points[-1][0] and points[0][1] == points[-1][1]: points.pop() elif isinstance(hitbox, pytiled_parser.objects.ElipseObject): if hitbox.size is None: print(f"Warning: Ellipse hitbox created for without a height " f"or width for {tile.image.source}. Ignoring.") continue w = hitbox.size[0] / 2 h = hitbox.size[1] / 2 cx = (hitbox.location[0] + hitbox.size[0] / 2) - half_width cy = map_object.tile_size.height - (hitbox.location[1] + hitbox.size[1] / 2) - half_height total_steps = 8 angles = [step / total_steps * 2 * math.pi for step in range(total_steps)] for angle in angles: x = w * math.cos(angle) + cx y = h * math.sin(angle) + cy point = [x, y] points.append(point) else: print(f"Warning: Hitbox type {type(hitbox)} not supported.") # Scale the points to our sprite scaling for point in points: point[0] *= scaling point[1] *= scaling my_sprite.points = points if tile.animation is not None: key_frame_list = [] for frame in tile.animation: frame_tile = _get_tile_by_id(map_object, tile.tileset, frame.tile_id) key_frame = AnimationKeyframe(frame.tile_id, frame.duration, frame_tile.image) key_frame_list.append(key_frame) my_sprite.frames = key_frame_list return my_sprite