【问题标题】:Why my pygame game with a tiled map is lagging?为什么我的带有平铺地图的 pygame 游戏滞后?
【发布时间】:2020-06-01 16:21:10
【问题描述】:

我刚开始使用 pygame 并开始编写一个小游戏,但是当我为平铺地图编写代码时,我的游戏滞后了!我不明白为什么,所以我问你。 我的代码:

import pygame
from player import Player
from level import Level

clock = pygame.time.Clock()

from pygame.locals import *

pygame.init()

WIDHT = 1024
HEIGHT = 768
MAP_FILE = "niveau.txt"

pygame.display.set_caption("TEST")
screen = pygame.display.set_mode((WIDHT, HEIGHT))

player = Player()
moving_right = False
moving_left = False
moving_up = False
moving_down = False
i = 0

level = Level()
level.generer(MAP_FILE)

while True:
    screen.fill((146,244,255))
    level.afficher(screen, 0, 0, WIDHT, HEIGHT)

    player.movement = [0, 0]
    if moving_right == True:
        player.movement[0] += 5
    if moving_left == True:
        player.movement[0] -= 5
    if moving_up == True:
        player.movement[1] -= 5
    if moving_down == True:
        player.movement[1] += 5
    player.rect.x += player.movement[0]
    player.rect.y += player.movement[1]
    screen.blit(player.original_image, player.rect)

    for event in pygame.event.get():   
        if event.type == pygame.QUIT:
            break
            pygame.quit()

        if event.type == KEYDOWN:
            if event.key == K_RIGHT:
                moving_right = True
            if event.key == K_LEFT:
                moving_left = True
            if event.key == K_UP:
                moving_up = True
            if event.key == K_DOWN:
                moving_down = True

        if event.type == KEYUP:
            if event.key == K_RIGHT:
                moving_right = False
            if event.key == K_LEFT:
                moving_left = False
            if event.key == K_UP:
                moving_up = False
            if event.key == K_DOWN:
                moving_down = False

    pygame.display.update()
    clock.tick(60)
    #i += 1

和level.py:

import pygame

class Level():
    def __init__(self):
        self.structure = 0
        self.map = []
        self.grass = pygame.image.load("assets/bloc/normal_blocks/grass.png").convert_alpha()
        self.tree = pygame.image.load("assets/bloc/collidables_blocks/tree_grass.png").convert_alpha()
        self.no_texture = pygame.image.load("assets/bloc/specials_blocks/no_texture.png").convert_alpha()

    def generer(self, map_file_name):
        with open(map_file_name, "r") as fichier:
            structure_niveau = []
            for ligne in fichier:
                ligne_niveau = []
                for sprite in ligne:
                    if sprite != '\n':
                        ligne_niveau.append(sprite)
                structure_niveau.append(ligne_niveau)
            self.structure = structure_niveau

    def afficher(self, fenetre, x, y, screen_widht, screen_height):
        tileSize = 64
        num_ligne = 0
        for ligne in self.structure:
            num_case = 0
            for sprite in ligne:
                x = num_case * tileSize
                y = num_ligne * tileSize
                tile_rect = pygame.Rect(x, y, 64, 64)
                screenRect = pygame.Rect(0, 0, screen_widht + 64, screen_height + 64)

                #Normal Bolcks
                if sprite == 'G' and screenRect.colliderect(tile_rect):
                    fenetre.blit(self.grass, (x, y))

                #Collidables blocks    
                elif sprite == 'T' and screenRect.colliderect(tile_rect):
                    fenetre.blit(self.tree, (x, y))

                #specials bolcks    
                else:
                    if screenRect.colliderect(tile_rect):
                        fenetre.blit(self.no_texture, (x, y))

                num_case += 1
            num_ligne += 1  
        #pygame.draw.rect(fenetre, (255, 0, 0), self.aroundPlayer) 

还有player.py,但这并不重要! 谢谢!

【问题讨论】:

    标签: python pygame pygame-surface


    【解决方案1】:

    游戏是滞后的,因为游乐场是在每一帧中生成的。创建一个pygame.Surface,其大小与操场相同,并在其上绘制所有图块:

    tileSize = 64
    size_y, size_x = len(self.structure), len(self.structure[0])
    self.field = pygame.Surface((size_x * tileSize, size_y * tileSize))
    for iy, line in enumerate(self.structure):
        for ix, sprite in enumerate(line):
            tile_surf = self.no_texture
            if sprite == 'G':
                tile_surf = self.grass
            if sprite == 'T':
                tile_surf = self.tree
            self.field.blit(tile_surf, (ix*tileSize, iy*tileSize))
    

    在操场上用窗口大小,在窗口上,在每一帧中对操场的一个区域进行 Blit:

    fenetre.blit(self.field, (0, 0), (x, y, screen_widht, screen_height))
    

    班级Level:

    class Level():
        def __init__(self):
            self.structure = 0
            self.map = []
            self.grass = pygame.image.load("assets/bloc/normal_blocks/grass.png").convert_alpha()
            self.tree = pygame.image.load("assets/bloc/collidables_blocks/tree_grass.png").convert_alpha()
            self.no_texture = pygame.image.load("assets/bloc/specials_blocks/no_texture.png").convert_alpha()
    
        def generer(self, map_file_name):
            with open(map_file_name, "r") as fichier:
                structure_niveau = []
                for ligne in fichier:
                    ligne_niveau = []
                    for sprite in ligne:
                        if sprite != '\n':
                            ligne_niveau.append(sprite)
                    structure_niveau.append(ligne_niveau)
                self.structure = structure_niveau
                self.createMap()
    
        def createMap(self):
            tileSize = 64
            size_y, size_x = len(self.structure), len(self.structure[0])
            self.field = pygame.Surface((size_x * tileSize, size_y * tileSize))
            for iy, line in enumerate(self.structure):
                for ix, sprite in enumerate(line):
                    tile_surf = self.no_texture
                    if sprite == 'G':
                        tile_surf = self.grass
                    if sprite == 'T':
                        tile_surf = self.tree
                    self.field.blit(tile_surf, (ix*tileSize, iy*tileSize))
    
        def afficher(self, fenetre, x, y, screen_widht, screen_height):
            fenetre.blit(self.field, (0, 0), (x, y, screen_widht, screen_height))
    

    【讨论】:

    • 我只是坚持@Rabbid76,你的提议我不能提出冲突!
    • @Nat'code 我不明白你的意思。哪个碰撞?你根本不需要screenRect.colliderect(tile_rect):。这是一个新问题吗?
    • 这个游戏是一个角色扮演游戏(我只是尝试编写代码)并且地图中有树,所以如果我将表面上的所有图块都涂掉(好主意),我的玩家就不会与树发生碰撞(坏主意)和英语对不起(非常坏主意)
    • @Nat'code 表面的绘制与碰撞检测有什么关系? blit 每个图块单独减慢应用程序的速度。对于碰撞检测,您必须编写一个单独的方法,并且您不需要测试所有瓦片,测试与“T”的碰撞就足够了。信息存储在self.structure。无论如何,这是一个新问题,并不打算为每个新问题在接受/不接受之间切换。
    • 是的,你是真的,我会反映,谢谢你解决我的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多