Beispiel #1
0
 def create_map_sprite(self, x, y):
     sprite = Sprite(center_x=x, center_y=y)
     try:
         terrain_type, index, rotation = self.nodes_data[(x, y)]
         t, i, r = set_terrain_texture(terrain_type, index, rotation)
     except KeyError:
         terrain_type = 'mud'
         t, i, r = set_terrain_texture(terrain_type)
         self.nodes_data[(x, y)] = terrain_type, i, r
     sprite.texture = t
     self.game.terrain_tiles.append(sprite)
Beispiel #2
0
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