1

I have start to developed my first game and I use the Pygame library for this. For the map and the object I use Tiled. When I want to go to the up part of the map (which isn't display at first) I can see that there is a lot of latency with the sprite of the player. The two file that run the map:

game.py

from entities import *
from map import MapManager
from text import DialogBox


class Game:
    def __init__(self, screen_dimensions: tuple = (1920, 1020)):
        # create game window
        screen_dimensions = list(screen_dimensions)
        if screen_dimensions[0] < 480:
            screen_dimensions[0] = 480
        if screen_dimensions[1] < 255:
            screen_dimensions[1] = 255
        screen_dimensions = tuple(screen_dimensions)

        self.screen = pygame.display.set_mode(screen_dimensions)
        pygame.display.set_caption("Project ReBorn")

        self.zoom = screen_dimensions[0] / 480

        # generate player
        self.player = Player()

        self.map_manager = MapManager(self.screen, self.player, self.zoom)

        self.in_dialog = False

        self.dialog_box = DialogBox('dialog', screen_dimensions=screen_dimensions,
                                    width=int(200 * self.zoom), height=int(40 * self.zoom), zoom=self.zoom)

    def handle_input(self):
        pressed = pygame.key.get_pressed()
        dir_x = None
        dir_y = None
        go_up, go_down, go_left, go_right = False, False, False, False
        face = ''
        sprint = pressed[pygame.K_LSHIFT]

        handed = "right_handed"

        if handed == "right_handed":
            go_up = pygame.K_w
            go_down = pygame.K_s
            go_left = pygame.K_a
            go_right = pygame.K_d
        elif handed == "left_handed":
            go_up = pygame.K_i
            go_down = pygame.K_k
            go_left = pygame.K_j
            go_right = pygame.K_l
        if pressed[go_up] is not pressed[go_down]:
            if pressed[go_up]:
                dir_y, face = "up", "up"
            elif pressed[go_down]:
                dir_y, face = "down", "down"
        if pressed[go_left] is not pressed[go_right]:
            if pressed[go_left]:
                dir_x, face = "left", "left"
            elif pressed[go_right]:
                dir_x, face = "right", "right"
        self.player.move(face, sprint, dir_x, dir_y)

    def run(self):  # game loop
        clock = pygame.time.Clock()
        running: bool = True
        while running:
            self.player.save_location()
            if not self.in_dialog:
                self.handle_input()
            self.map_manager.update()
            self.dialog_box.render(self.screen, self.zoom)
            pygame.display.flip()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        self.in_dialog = self.map_manager.check_npc_collisions(self.dialog_box)

            clock.tick(60)
        pygame.quit()

map.py

from dataclasses import dataclass
import pytmx
import pyscroll
from entities import *


@dataclass
class Portal:
    origin_map: str
    target_map: str
    point: str


@dataclass
class Map:
    name: str
    walls: list
    group: pyscroll.PyscrollGroup
    tmx_data: pytmx.TiledMap
    portals: list
    npcs: list


class MapManager:
    def __init__(self, screen, player, zoom):
        self.maps = dict()
        self.screen = screen
        self.player = player
        self.zoom = zoom
        self.current_map = "Around_Home"
        self.register_all_map()
        self.tp_player("Spawn")
        self.tp_npcs()

    def check_npc_collisions(self, dialog_box):
        for sprite in self.get_group().sprites():
            if sprite.feet.colliderect(self.player.rect) and type(sprite) is NPC:
                return dialog_box.execute(sprite.dialog)

    def check_collisions(self):
        # portals
        for portal in self.get_map().portals:
            if portal.origin_map == self.current_map:
                point = self.get_object(portal.point)
                rect = pygame.Rect(point.x, point.y, point.width, point.height)

                if self.player.feet.colliderect(rect):
                    copy_portal = portal
                    self.current_map = portal.target_map
                    self.tp_player(copy_portal.point)
        # walls/entities
        for sprite in self.get_group().sprites():
            if type(sprite) is NPC:
                if sprite.feet.colliderect(self.player.rect):
                    sprite.speed = 0
                else:
                    sprite.speed = 1.75
            
            if sprite.feet.collidelist(self.get_walls()) > -1:
                sprite.move_back()

    def tp_player(self, name: str):
        point = self.get_object(name)
        self.player.position[0] = point.x
        self.player.position[1] = point.y
        self.player.save_location()

    def register_all_map(self):
        #self.register_map(
        #     "Map",
        #     "ref"
        #)

        self.register_map(
            "Around_Home",
            "Beach",
            zoom=self.zoom,
            portals=[
                Portal(origin_map="Around_Home", target_map="Home_down", point="Home_enter"),
                #Portal(origin_map="Around_Home", target_map="Atlantis", point="Atlantis_north_enter")
            ],
            npcs=[
                NPC("Beach", "Honey", nb_points=2, dialog=['Hello~', 'How are you ?'])
                ],
            layer=3

        )

        self.register_map(
            "Home_down",
            "Beach",
            zoom=self.zoom,
            portals=[
                Portal(origin_map="Home_down", target_map="Around_Home", point="Home_exit"),
                Portal(origin_map='Home_down', target_map="Home_up", point="Home_up")
            ],
            layer=4
        )

        self.register_map(
            "Home_up",
            "Beach",
            zoom=self.zoom,
            portals=[
                Portal(origin_map="Home_up", target_map="Home_down", point="Home_down")
            ]
        )

    def register_map(self, name: str, area: str, zoom: float = 4, portals: list = [], npcs: list = [], layer: int = 3):
        # load map
        tmx_data = pytmx.util_pygame.load_pygame(f"../assets/map/map_tmx/{area}/{name}.tmx")
        map_data = pyscroll.data.TiledMapData(tmx_data)
        map_layer = pyscroll.orthographic.BufferedRenderer(
            map_data, self.screen.get_size()
        )
        map_layer.zoom = zoom

        # define list of walls
        walls: list = []

        for obj in tmx_data.objects:
            if obj.name == "collision":
                walls.append(pygame.Rect(obj.x, obj.y, obj.width, obj.height))
        # draw layers group
        group = pyscroll.PyscrollGroup(map_layer=map_layer, default_layer=2)

        # add entities
        group.add(self.player)
        for npc in npcs:
            group.add(npc)
        # add map to dict
        self.maps[name] = Map(name, walls, group, tmx_data, portals, npcs)

    def get_map(self):
        return self.maps[self.current_map]

    def get_group(self):
        return self.get_map().group

    def get_walls(self):
        return self.get_map().walls

    def get_object(self, name: str):
        return self.get_map().tmx_data.get_object_by_name(name)

    def tp_npcs(self):
        for _map in self.maps:
            map_data = self.maps[_map]
            npcs = map_data.npcs

            for npc in npcs:
                npc.load_points(map_data.tmx_data)
                npc.tp_spawn()

    def draw(self):
        self.get_group().draw(self.screen)
        self.get_group().center(self.player.rect.center)

    def update(self):
        self.get_group().update()
        self.check_collisions()

        for npc in self.get_map().npcs:
            npc.npc_move()
        self.draw()

I have already tried to increase the fps and reduce the player speed but it wasn't successful.

Matsune
  • 11
  • 2
  • 1
    Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Feb 20 '23 at 20:15

0 Answers0