2

I just started pygame and I started coding a little game, but when I put the code for the tiled map my game lagged! I don't understand why so I ask you. my code:

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

and 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) 

there is also player.py but it's not important! Thank you !

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Nat' code
  • 55
  • 6

1 Answers1

2

The game is lagging, because the playground is generated in every frame. Create a pygame.Surface with the size of the playground and draw all the tiles on it:

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 the playground an area of the playground with the size of the window, on the window, in every frame:

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

Class 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
  • 202,892
  • 27
  • 131
  • 174
  • I just tought @Rabbid76, with your proposition I cannot put collisions ! – Nat' code Jun 01 '20 at 18:28
  • @Nat'code I've no idea what you mean. Which collision? You don't need `screenRect.colliderect(tile_rect):` at all. Is that a new question? – Rabbid76 Jun 01 '20 at 18:29
  • The game is a RPG (I just try to code it) and there are trees in the map so if I blit all the tiles on a surface (good idea) my player can't collides with tree (bad idea) and sorry for the english (very bad idea) – Nat' code Jun 01 '20 at 18:39
  • 1
    @Nat'code What has the the drawing of the surface to do with the collision detection? `blit` each tile separately slows down the application. For the collision detection you have to write a separate method and you don't need to test all the tiles it is sufficient to test the collision against "T". The information is stored in `self.structure`. Anyway that is a new question and it is not intended to switch between accept/unaccept for each new issue. – Rabbid76 Jun 01 '20 at 18:44
  • Yes you true I will reflect that thank you for solve my anwser – Nat' code Jun 01 '20 at 19:02