python – How to load a new map when player reaches a certain point using if tile_object.name == ‘door” (pygame)

I have been working on creating a 2d game, and I am now at the point where I want the character to be able to interact with his environment, I have created a few different obstacles such as a house, fence and a wall is it possible to load a new map when the player reached the tile named “door” I have it written out as if tile_object.name == ‘door’: but not sure what to load after that so that a new map loads when he reaches that obstacle named door any help would be greatly appreciated 🙂 I have attached my code below for main.py

import pygame as pg
import sys
from os import path
from settings import *
from sprites import *
from tilemap import *

class Game:
def init(self):
pg.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.font_name = pg.font.match_font(FONT_NAME)
self.bg_img = pg.image.load(‘background.jpg’)
self.load_data()

def load_data(self):
    game_folder = path.dirname(__file__)
    img_folder = path.join(game_folder, 'img')
    map_folder = path.join(game_folder, 'maps')
    self.map = TiledMap(path.join(map_folder, 'map2use.tmx'))
    self.map_img = self.map.make_map()
    self.map_rect = self.map_img.get_rect()
    self.spritesheet = Spritesheet(path.join(img_folder, SPRITESHEET))
    self.mob_img = pg.image.load(path.join(img_folder, MOB_IMG)).convert_alpha()
    self.snd_dir = path.join(game_folder, 'snd')

def load_data2(self):
    game_folder = path.dirname(__file__)
    img_folder = path.join(game_folder, 'img')
    map_folder = path.join(game_folder, 'maps')
    self.map = TiledMap_2(path.join(map_folder, 'map3use.tmx'))
    self.map_img = self.map.make_map2()
    self.map_rect = self.map_img.get_rect()
    self.spritesheet = Spritesheet(path.join(img_folder, SPRITESHEET))

def new(self):
    self.all_sprites = pg.sprite.Group()
    self.mobs = pg.sprite.Group()
    self.walls = pg.sprite.Group()
    pg.mixer.music.load(path.join(self.snd_dir, "midnight_drive.ogg"))
    for tile_object in self.map.tmxdata.objects:
        if tile_object.name == 'player':
            self.player = Player(self, tile_object.x, tile_object.y)
        if tile_object.name == "enemy":
            Mob(self, tile_object.x, tile_object.y)
        if tile_object.name == 'Wall':
            Obstacle(self, tile_object.x, tile_object.y, tile_object.width, tile_object.height)
        if tile_object.name == 'tree':
            Obstacle(self, tile_object.x, tile_object.y, tile_object.width, tile_object.height)
        if tile_object.name == 'house':
            Obstacle(self, tile_object.x, tile_object.y, tile_object.width, tile_object.height)
        if tile_object.name == 'fence':
            Obstacle(self, tile_object.x, tile_object.y, tile_object.width, tile_object.height)
        if tile_object.name == 'door':
            Obstacle(self, tile_object.x, tile_object.y, tile_object.width, tile_object.height)

    self.camera = Camera(self.map.width, self.map.height)
    self.draw_debug = False
    self.run()

def run(self):
    self.playing = True
    pg.mixer.music.play(loops=-1)
    while self.playing:
        self.dt = self.clock.tick(FPS) / 1000
        self.events()
        self.update()
        self.draw()
    pg.mixer.music.fadeout(500)

def quit(self):
    pg.quit()
    sys.exit()

def update(self):
    self.all_sprites.update()
    self.camera.update(self.player)
    #mob spawn
    
def draw_grid(self):
    for x in range(0, WIDTH, TILESIZE):
        pg.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
    for y in range(0, HEIGHT, TILESIZE):
        pg.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))

def draw(self):
    pg.display.set_caption('{:.2f}'.format(self.clock.get_fps()))
    self.screen.blit(self.map_img, self.camera.apply_rect(self.map_rect))
    for sprite in self.all_sprites:
        self.screen.blit(sprite.image, self.camera.apply(sprite))
        if self.draw_debug:
            pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(sprite.hit_rect), 1)
    if self.draw_debug:
        for wall in self.walls:
            pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(wall.rect), 1)

    pg.display.flip()

def events(self):
    for event in pg.event.get():
        if event.type == pg.QUIT:
            self.quit()
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                self.quit()
            if event.key == pg.K_h:
                self.draw_debug = not self.draw_debug

def show_start_screen(self):
    # game splash/start screen
    #self.screen.fill(BGCOLOR)
    pg.mixer.music.load(path.join(self.snd_dir, "Feat.ogg"))
    pg.mixer.music.play(loops=-1)
    self.screen.blit(self.bg_img, self.bg_img.get_rect())
    pg.display.flip()
    self.wait_for_key()
    pg.mixer.music.fadeout(500)

def show_go_screen(self):
    # game over/continue
    if not self.running:
        return
    #self.screen.fill(BGCOLOR)
    self.screen.blit(self.bg_img, self.bg_img.get_rect())
    pg.display.flip()
    self.wait_for_key()

def wait_for_key(self):
    waiting = True
    while waiting:
        self.clock.tick(FPS)
        for event in pg.event.get():
            if event.type == pg.QUIT:
                waiting = False
                self.running = False
            if event.type == pg.KEYUP:
                waiting = False

def draw_text(self, text, size, color, x, y):
    font = pg.font.Font(self.font_name, size)
    text_surface = font.render(text, True, color)
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    self.screen.blit(text_surface, text_rect)

g = Game()
g.show_start_screen()
while True:
g.new()
g.run()
g.show_go_screen()

python – Pygame is not responding even though event handler and quit settings are present?

I am a beginner at programming with less than 4 months of experience so, please pardon me if I haven’t asked the question correctly according to the standards

FEW DAYS AGO, I have created a project but whenever I tried to run it on Spyder(IDE) and Jupyter notebook, the Pygame window opens up but it is not responding (not working or showing anything on the screen) I have tried everything I can like updating Pygame to version 2.0,updating Spyder, putting one event handler:

while True:
     for event in pygame.event.get():
        if event.type==pygame.QUIT:
            terminate()
            sys.exit()

the Spyder console on the other hand shows:

Restarting kernel...

and

(SpyderKernelApp) WARNING | No such comm: 7657c0fb289911eb9a4124b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: e7112fb1289b11eb90d224b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: b71d4cc1289d11eb906324b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: 8c66b5c828a011eb964024b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: 56eda5f928a411eba08524b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: d7db00b428a411ebac6824b6fd3c7b5a
(SpyderKernelApp) WARNING | No such comm: 3de6c19428a611eb91d124b6fd3c7b5a

and after I try to close the window it shows:

Kernel died, restarting

and always restarts.
I don’t know whether there is any bug or not in my code because I am a beginner and it is not showing on my (IDE) so please also recommend me how to debug any code and please give a detailed answer for my problem. Some of the starting code that I think may be wrong:

def main():
    global BASICFONT
    BASICFONT=pygame.font.Font(None,50)
    window.fill(bgcolor)
    def startscreen():
        font=BASICFONT.render("Snake Game X",True,dgreen)
        fontRect=font.get_rect.center=(250,250)
        fontRect.fill(black)
        window.blit(font,fontRect)
        
        def keymsg():
           font=BASICFONT.render("Please Press A Key To Start",True, red)
           fontRect=font.get_rect.midbottom=(0,10)
           fontRect.fill(black)
           window.blit(font,fontRect)
        
        def keypressed():
           keypressed=pygame.key.get_pressed()
           if keypressed==0 or keypressed==keypressed(pygame.K_ESCAPE):
               terminate()
           elif keypressed:
                return
           else:
                 pygame.time.wait(500)
                 terminate()
        startscreen.keymsg()
        startscreen.keypressed()
    while run:
        startscreen()
        run()
if __name__=="Snake Game X":
    main()
def run(score,run):
   while run:
     for event in pygame.event.get():
        if event.type==pygame.QUIT:
            terminate()
            sys.exit()
        def randomlocation():
             ({"x":random.randint(20,win_w-20),
               "y":random.randint(20,win_h-20)})
        apple=randomlocation()
        assert win_w % cell_s==0
        assert win_h % cell_s==0

        startX=random.randint(20,win_w-20)
        startY=random.randint(20,win_h-20)
        appleX=apple('x')*cell_s
        appleY=apple('y')*cell_s
        
        def drawgame():
            def drawapple():
                appleRect=window.rect(appleX,appleY,cell_s,cell_s)
                appleRect.fill(red)
            def drawgrid():
                for x in range(0,win_w,20):
                    pygame.draw.line(window,dgray,0,win_h,5)
                for y in range(0,win_h,20):
                    pygame.draw.line(window,dgray,0,win_w,5)
            def drawsnake(snakeCoords):
                snakeX=snakeCoords('x')
                snakeY=snakeCoords('y')
                snakeRect=window.get_rect(snakeX,snakeY,cell_s,cell_s)
                snakeRect.fill(green)
                window.blit(snakeRect)
            def drawscore(score):
                scorefont=BASICFONT.render(('SCORE: ',score),True,white)
                scoreRect=scorefont.get_rect.topleft=(20,20)
                window.blit(scorefont,scoreRect)
        def gameover():
             gameFont=BASICFONT.render("Game",True,red)
             overFont=BASICFONT.render("Over",True,red)
             gameRect=gameFont.get_rect.center=(100,100)
             overRect=overFont.get_rect.center(100,100+30)
             window.blit(gameFont,gameRect)
             window.blit(overFont,overRect)
    
        snakeCoords=({"x":startX,"y":startY},
                     {"x":startX-1,"y":startY},
                     {"x":startX-2,"y":startY})
        direction=RIGHT
        if snakeCoords(head)('x')==win_w-20 or snakeCoords(head)('y')==win_h-20:
            gameover()
            pygame.time.wait(500)
            terminate()
            sys.exit()
        #apple eating snake
        if appleX==snakeCoords(head)('x') or appleY==snakeCoords(head)('y'):
            apple=randomlocation()
            drawgame.drawApple()
            score+=1
            if appleX==snakeCoords(head)('x') and direction==RIGHT:
                newhead=({'x':startX-3,'y':startY})
                snakeCoords+=newhead
            if appleX==snakeCoords(head)('x') and direction==LEFT:
                newhead=({'x':startX+3,'y':startY})
                snakeCoords+=newhead
            if appleY==snakeCoords(head)('y') and direction==UP:
                newhead=({'x':startX,'y':startY+3})
                snakeCoords+=newhead
            if appleY==snakeCoords(head)('y') and direction==DOWN:
                newhead=({'x':startX,'y':startY-3})
                snakeCoords+=newhead
        #keys pressed
       
        if event.type==pygame.event.get(pygame.KEYDOWN):
             if keypressed==keypressed(pygame.K_RIGHT)  and direction!=LEFT:
                direction=RIGHT
             elif keypressed==keypressed(pygame.K_LEFT)  and direction!=RIGHT:
                direction=LEFT
             elif keypressed==keypressed(pygame.K_UP) and direction!=DOWN:
                direction=UP
             elif keypressed==keypressed(pygame.K_DOWN)  and direction!=UP:
                direction=DOWN
             elif keypressed==keypressed(pygame.K_ESCAPE) :
                 terminate()
                 sys.exit()
             else:
                 print("Invalid Key Pressed")
       
        drawgame()
        pygame.display.update()
        if score==10:
            gameover()
            pygame.time.wait(500)
        
   terminate()

and my Python version is 3.8.3 .

python – Using pygame with multiple threads

I have decided to try out pygame. I created a class that is supposed to handle all the GUI and game related stuff.

My idea is that I would have two seperate threads. One to handle the GUI and one to handle all the calculations the game does in the background.

import threading
import pygame
import pygame_gui


class Game ():


    engine_running = True
    gui_running = True
    clock = pygame.time.Clock()

    gui_framerate = 60.0
    engine_framerate = 120.0

    def __init__(self):

        pygame.init()
        pygame.display.set_caption('Explodotech')
        self.window_surface = pygame.display.set_mode((800, 600))
        self.background = pygame.Surface((800, 600))
        self.background.fill(pygame.Color('#000000'))

        self.manager = pygame_gui.UIManager((800, 600))

        ### Define GUI Elements here

        self.quit_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((650, 500),
                        (100, 50)), text='Quit', manager=self.manager,                         
                        tool_tip_text = "Quit the game")

        ### Create and start the threads
        self.gui_thread = threading.Thread(target = self.gui_loop)
        self.engine_thread = threading.Thread(target = self.engine_loop, args = ())

        self.gui_thread.start()
        self.engine_thread.start()


    def start_polling(self):
        """Starts the main loop"""
        self.engine_running = True

    def stop_polling(self):
        """Stops the main loop"""
        self.engine_running = False

    def gui_loop(self):
        """Managing all the GUI stuff"""

        print ("GUI-loop started!")

        while self.gui_running:
            print("Polling GUI")
            dT = self.clock.tick_busy_loop(60)/1000.0

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    self.gui_running = False

                if event.type == pygame.USEREVENT:
                    if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                        if event.ui_element == self.quit_button:
                            self.quit_button_event()

                self.manager.process_events(event)

            self.manager.update(dT)

            self.window_surface.blit(self.background, (0, 0))
            self.manager.draw_ui(self.window_surface)

            pygame.display.update()

    def engine_loop(self):
        """Doing all the game calculations in the background"""
        while self.engine_running:
            print(self.clock.tick_busy_loop(1))
        

    ### Define GUI events here

    def quit_button_event(self):
        """Shut down the GUI"""
        print("Quit-button pressed!")
        self.gui_running = False
        self.engine_running = False

Basically what’s happening here is that I have two threads one should run the “gui_loop” function the other should run the “engine_loop”. However when the gui thread starts and gets into its while-loop it get stuck. The windows goes unresponsive and I have to force windows to shut it down.
However if I a create a Game-object and call the function directly it all works fine (obviously commenting out the party where I create the Thread-object):

g = Game()
g.gui_loop()

Any pointers what I am doing wrong would be greatly appreciated!

python – Word finder using pygame

I made a word searching app that allows the user to inout words into a text box,
and parts of the word grid will be highlighted to show the location of the words.
The letters of the grid can be edited while you are using it by clicking on the cell,
and pressing the key you want to replace the current letter with.

Here is how it goes:

enter image description here

I made this recursive function to find each word:

    def adj(self, c, idx, lstlst, wrd):
        x, y = self.cells.index(c) % self.cols, self.cells.index(c) // self.cols
        x1, x2 = max(0, x - 1), min(x + 2, self.cols + 2)
        y1, y2 = max(0, y - 1), min(y + 2, self.rows + 2)
        adjs = (cell for row in self.grid(y1:y2) for cell in row(x1:x2) if cell != c)
        taillst = lstlst(-1)
        for cell in adjs:
            if len(wrd) > idx:
                if cell.text == wrd(idx) and cell not in taillst:
                    lstlst.append(taillst(:) + (cell))
                    self.adj(cell, idx+1, lstlst, wrd)

This is how I called it:

        elif event.type == pygame.KEYDOWN:
            grid.type(event)
            word.type(event)
            for cell in grid.cells:
                cell.color = (0, 0, 0)
            for cell in grid.cells:
                lstlst = ((cell))
                grid.adj(cell, 1, lstlst, word.text)
                for lst in lstlst:
                    if ''.join((c.text for c in lst)) == word.text:
                        for c in lst:
                            c.color = (255, 0, 0)

I know, it’s a mess, but I am trying. Despite that, can you show me how can I improve the efficiency of my word-searching algorithim?

Here is my entire code:

import pygame

pygame.font.init()
wn = pygame.display.set_mode((600, 600))

letters = 
'''
KJDJCIOSDZ
PGRIWOTAID
VETVALCGLS
OFZESGZASW
SOYRBKOADL
FUWTQOXNGE
CILIWMEPAV
NEZCJRVZNL
GXZAOQMFIG
EUPLIESCGP
HORIZONTAL
'''

class Cell():
    def __init__(self, x, y, s, text='', color=(0, 0, 0), cell=True):
        self.input_box = pygame.Rect(x, y, s, s)
        self.x = x
        self.y = y
        self.s = s
        self.w = s
        self.color_inactive = color
        self.color_active = pygame.Color('purple')
        self.color = self.color_inactive
        self.text = text
        self.active = False
        self.pad = 10
        self.cell = cell
        self.font = pygame.font.Font(None, s)

    def check_status(self, pos):
        if self.input_box.collidepoint(pos):
            self.active = not self.active
        else:
            self.active = False
        self.color = self.color_active if self.active else self.color_inactive

    def type(self, event):
        if self.active:
            if self.cell:
                if event.unicode and event.unicode.lower() in 'abcdefghijklmnopqrstuvwxyz ':
                    self.text = event.unicode
            else:
                if event.key == pygame.K_BACKSPACE:
                    self.text = '' if len(self.text) < 2 else self.text(:-1)
                elif event.unicode and event.unicode.lower() in 'abcdefghijklmnopqrstuvwxyz ':
                    self.text += event.unicode 
            
    def draw(self):
        txt = self.font.render(self.text, True, self.color)
        if not self.cell:
            width = max(self.w, txt.get_width())
            self.input_box.w = width + self.pad * 2
            x = self.x + self.pad
        else:
            x = self.x+(self.s-txt.get_width())//2
        y = self.y+(self.s-txt.get_height())*5//7
        wn.blit(txt, (x, y))
        pygame.draw.rect(wn, self.color, self.input_box, 2)

class Grid():
    def __init__(self, x, y, size, letters, color=(0, 0, 0)):
        rows = len(letters)
        cols = len(letters(0))
        self.grid =  ((Cell(i*size+x, j*size+y, size, letter) for i, letter in enumerate(row)) for j, row in enumerate(letters))
        self.cells = (cell for row in self.grid for cell in row)
        self.rows = rows
        self.cols = cols

    def check_status(self, pos):
        for cell in self.cells:
            cell.check_status(pos)

    def type(self, event):
        for cell in self.cells:
            cell.type(event)

    def adj(self, c, idx, lstlst, wrd):
        x, y = self.cells.index(c) % self.cols, self.cells.index(c) // self.cols
        x1, x2 = max(0, x - 1), min(x + 2, self.cols + 2)
        y1, y2 = max(0, y - 1), min(y + 2, self.rows + 2)
        adjs = (cell for row in self.grid(y1:y2) for cell in row(x1:x2) if cell != c)
        taillst = lstlst(-1)
        for cell in adjs:
            if len(wrd) > idx:
                if cell.text == wrd(idx) and cell not in taillst:
                    lstlst.append(taillst(:) + (cell))
                    self.adj(cell, idx+1, lstlst, wrd)

    def draw(self):
        for cell in self.cells:
            cell.draw()

grid = Grid(50, 70, 32, list(filter(None, letters.split('n'))))
word = Cell(50, 20, 32, cell=False)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            grid.check_status(event.pos)
            word.check_status(event.pos)
        elif event.type == pygame.KEYDOWN:
            grid.type(event)
            word.type(event)
            for cell in grid.cells:
                cell.color = (0, 0, 0)
            for cell in grid.cells:
                lstlst = ((cell))
                grid.adj(cell, 1, lstlst, word.text)
                for lst in lstlst:
                    if ''.join((c.text for c in lst)) == word.text:
                        for c in lst:
                            c.color = (255, 0, 0)

    wn.fill((255, 255, 255))
    grid.draw()
    word.draw()
    pygame.display.flip()

Error ao designar um atributo no Pygame, não esta aceitando o que coloquei

Esse é o problema que estou tendo no momento...

Traceback (most recent call last):
File "C:/Users/lealv/Desktop/pyzzle escape/main.py", line 130, in
game_state.state_manager()
File "C:/Users/lealv/Desktop/pyzzle escape/main.py", line 51, in state_manager
if self.state == ‘intro’:
AttributeError: ‘GameState’ object has no attribute ‘state’

class GameState():
def _init_(self):
    self.state == 'intro'

def intro(self):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            self.state == 'main_game'

    screen.fill((0, 0, 0))
    pygame.display.update()

def main_game(self):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    keys = pygame.key.get_pressed()
    move()
    screen.fill((0, 0, 0))
    GameWindow()

def state_manager(self):
    if self.state == 'intro':
        self.intro()
    if self.state == 'main_game':
        self.main_game()


#general_setup
game_state = GameState()

#main_loop
run = True
while run:
    game_state.state_manager()
    clock.tick(27)

rendering – How would I blit objects behind other objects in pygame?

I am currently trying to make a custom isometric rendering extension to Pygame for a game I am making. However, I have noticed that you need to draw objects in a certain order for them to display correctly, which would be a problem for updating any moving objects. Is there a way to blit objects behind others so I don’t have to deal with this problem?
Code:

import pygame as pyg #For drawing to screen and all of that

def init(scrn): #Initialization function. Basically just inits pygame and gets the screen
    pyg.init()
    global screen
    screen = scrn

class Grid: #Creates an isometric grid of tiles on the screen

    def __init__(self, width, height, t_width, t_height): #Initialization
        self.grid = (width-1, height-1, ()) #Width, height, children
        self.t_size = (t_width, t_height)

    def fill(self, tile): #Fill the grid with a certain tile
        centered = screen.get_rect().center #Get center position of screen
        for x in range(self.grid(0)+1):
            for y in range(self.grid(1)+1):
                screen.blit(tile, (centered(0)-self.t_size(0)/2+self.t_size(0)*x/2-self.t_size(0)*y/2+self.t_size(0)*(((self.grid(0)+1)-(self.grid(1)+1))/4), centered(1)-self.t_size(1)/2+self.t_size(1)*y/2+self.t_size(1)*x/2-self.t_size(1)*((self.grid(1)+1)/4)-self.t_size(1)/2)) #Blits tile to screen, runs from top to left then right to bottom
        pyg.display.flip() #Update the display

    def place_sprite(self, sprite, x, y): #Place image/sprite on grid
        x -= 1
        y -= 1 #Weird necessary alignment
        centered = screen.get_rect().center #Get center position of screen
        screen.blit(sprite, (centered(0)-self.t_size(0)/2+self.t_size(0)*x/2-self.t_size(0)*y/2+self.t_size(0)*(((self.grid(0)+1)-(self.grid(1)+1))/4), centered(1)-self.t_size(1)/2+self.t_size(1)*y/2+self.t_size(1)*x/2-self.t_size(1)*((self.grid(1)+1)/4)-self.t_size(1)/2)) #Blits sprite
        pyg.display.flip() #Update the display
```

pygame – Tocando musica mp3 em Python

tudo bem?
bem eu venho aqui pedir uma solução referente a tocar musica mp3 em Python.
Eu importei a biblioteca do Pygame e utilizei o módulo mixer para tocar musicas em python:

import pygame
pygame.init()
pygame.mixer.music.load('brain_damage.mp3')
pygame.mixer.music.play(loops=0, start=0.0)
pygame.event.wait()

Após eu escrever esse script e rodar o meu programa, ele dá uma saída de erro, dizendo:

Traceback (most recent call last):
File "/home/gabriel/Documentos/GitHub/Projetos Pessoais/olamundo.py/_exercicios/teste.py", line 3, in <module>

pygame.mixer.music.load('music/brain_damage.mp3')
pygame.error: Couldn't open 'music/brain_damage.mp3'

Esse é o arquivo Python que fica dando erro

Para efeito de comparação, eu criei um outro arquivo Python e utilizei o mesmo código da imagem acima, e para a minha surpresa, o mixer conseguiu rodar o meu arquivo mp3. Vocês sabem o por quê procede?
Segundo print com o programa rodando

tilemap – Scrolling background in PyGame with Entity Component System

I know this type of question has been asked to death for ‘normal’ games, however I am struggling with relating a scrolling background to an entity component system (ECS) approach.

Generic samples here and here and here.

What I struggle with is how to take a fairly procedural view of this problem and abstract it out to an ECS. I’m trying to get a roguelike game up and running in PyGame using Esper. I do have a proof of concept up and running where I generate a large map, however I’m having issues relating how to add a camera here as an entity that other objects would relate to. I’m guessing that I need to refactor my movement code to be based around a camera, and have each separate entity update their relative position as a result.

At present, the background is being directly drawn and needs to be abstracted to an Entity in this system, but I was somewhat holding off on that until I figured out the camera. Here is a snippet of the Renderable class that each drawn entity has:

class Renderable:
    def __init__(self, image, posx, posy, depth=0):
        self.image = image
        self.depth = depth
        self.x = posx
        self.y = posy
 
        self.curr_row, self.curr_col = convert_to_cells(posx, posy)
 
        self.w = image.get_width()
        self.h = image.get_height()
        self.rect = pygame.Rect(self.x,self.y,self.w,self.h)

And here are the Movement processor and Render processors:

class MovementProcessor(esper.Processor):
    def __init__(self, minx, maxx, miny, maxy, game_map):
        super().__init__()
        self.minx = minx
        self.maxx = maxx
        self.miny = miny
        self.maxy = maxy
        self.game_map = game_map
 
    def process(self):
        # This will iterate over every Entity that has BOTH of these components:
        for ent, (vel, rend) in self.world.get_components(Velocity, Renderable):
            # Check if movement is valid:
            newx = rend.x + int(vel.x * TILE_SIZE)
            newy = rend.y + int(vel.y * TILE_SIZE)
            new_row, new_col = convert_to_cells(newx, newy)
 
            if self.game_map.data(new_row)(new_col) > 1:
              # Update the Renderable Component's position by it's Velocity:
              rend.x = newx
              rend.y = newy
              rend.curr_row = new_row
              rend.curr_col = new_col
 
class RenderProcessor(esper.Processor):
    def __init__(self, window, clear_color=(0, 0, 0)):
        super().__init__()
        self.window = window
        self.clear_color = clear_color
 
    def process(self):
        # Clear the window:
        self.window.fill(self.clear_color)
 
        # This will iterate over every Entity that has this Component, and blit it:
        for ent, rend in self.world.get_component(Renderable):
            self.window.blit(rend.image, (rend.x, rend.y))
 
        # Flip the framebuffers
        pygame.display.flip()

Later on in my main loop I iterate over my tilemap (Map class) and simply draw it to a surface, add some debugging overlays, and then assign that surface to the entity associated with the background (bg_entity):

        # Blit background directly -- this needs to be abstracted out
        for row in range(len(game_map.data)):
          for col in range(len(game_map.data(0))):
            rect = pygame.Rect(col*TILE_SIZE,row*TILE_SIZE,TILE_SIZE,TILE_SIZE)

            # Blit a wall sprite
            if game_map.data(row)(col) in (0,1):
              bg_surface.blit(walls(game_map.data(row)(col)),rect)

            # Blit a floor/grass sprite
            elif game_map.data(row)(col) in (2,3,4,5):
              bg_surface.blit(floors(game_map.data(row)(col)-2),rect)

Here is the full listing:

https://pastebin.com/N7c4TXXB

python – Pygame – RPG Battle-Style Animation and movement when not controlled by player

Examples: https://www.youtube.com/watch?v=C2cOiFntLY4 https://www.youtube.com/watch?v=iHl1YFkeR78

I am making a small little RPG based on a text-adventure game that I made. This RPG involves a battle system similar to the SNES Final Fantasy games. I am currently limited to the player character and a single enemy, since those are the only actors that were ever present in the text-adventure game.

My battle system involves selecting your choice (attack or run away) and, upon attacking, the damage is calculated, battle text is displayed showing the damage, and then there is a short delay before the enemy attacks in return. This is all fine and good, but I don’t want static images of my player and the enemy.

In the first example above, you can see the enemies jump onto the player for their attacks and you can see that the player runs to the enemy and then swings his sword. In the second example, you can see that the players will run forward a short distance and then either cast a spell or swing their weapon. What I’m looking for is something somewhere in the middle — I want my player sprite to run/jump over to a position directly in front of the enemy, perform an attack animation in that position, and then run/jump back to their starting position.

I don’t have my code in front of me, but I do know that I am currently drawing the sprites in specific locations, basically using standard pygame.draw functionality.

So: Any chance someone could walk me through this? I know how to move my player around when outside of the battle system, but I don’t know how to properly do the same thing when the player is not in control… and adding the Y-axis to the equation (for the jump) just stumps me in this situation. I have (extremely basic) knowledge of tweening/easing functions, which I suspect will be relevant here, but I’ve only ever used them along one axis to make an item bounce up and down in place, so I’m not sure how to apply them to a sprite moving in two different axes.

Any help would be appreciated, especially code examples. Thanks!

python – Tic-tac-toe game using Pygame

I programmed a tic-tac-toe game using pygame. It’s the first game I make. I’d really appreaciate any comments you have about the coding style and any improvements that could be made.

import pygame
import graphics # External module graphics.py
import logic    # External module logic.py

# Setting up window
HEIGHT = 600
WIDTH = 480
FPS = 30
TITLE = "Tic-tac-toe"

# Defining colors
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)

# Initializing pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
clock = pygame.time.Clock()

# Game settings
TOP = 100
SIZE = 450
CELL = SIZE // 3
CPU_SPEED = FPS // 2


class TicTacToe():
    """Main tic-tac-toe game object.

    Attributes
    ----------
    board : graphics.Board
        pygame.Sprite object. Consists mainly of the lines that make
        up the grid.
    board_logic : logic.Board
        Object that defines the game logic and AI.
    cells : 3 x 3 nested list.
        List containing individual graphics.Cell objects.
        Each `Cell` object is a cell sprite.
    player_score : graphics.Text
        Sprite object that shows the player score.
    cpu_score : graphics.Text
        Sprite object that shows the cpu score.
    end_message : graphics.Text
        Sprite object that shows a message when the game ends:
        win/lose/tie.
    player_play : bool
        Determine when it's the player's turn to play.
    check : bool
        Determine when the check the end of the game.
        Set to `True` after each player or cpu move.
    reset : bool
        Determines when to reset the board after the end of game.
    timer : int
        Counter to limit cpu moves speed.
    timer2 : int
        Counter to limit end game reactions speed.

    Methods
    -------
    add_to_group(sprites_group)
        Add all of the sprite objects of the `TicTacToe` object
        to `sprites_group`.
    create_cells(CELL)
        Create 9 `graphics.Cell` objects of size `SIZE` x `SIZE`
        and append them to `self.cells`.
    update()
        Check if the game has ended or a player has won. Calls
        methods accordingly. Verify when to check with `self.check`
        and limit frequency using `self.timer2`.
        Verifies it's the computer's turn to play by checking
        `self.player_turn`. Calls `computer_turn` method when
        corresponds. Limits computer's play speed using
        `self.timer`.
    computer_turn()
        Use `graphics.board_logic.computer_turn()` method to determine
        next case to fill.
        Fill cell accordingly and update to check board end game
        conditions and player's turn.
    reset_game()
        Reset `graphics.Board` to delete extra lines on the board.
        Reset all `graphics.Cell` sprites to a blank surface.
        Reset `self.end_message` to show an empty string.
    update_score()
        Add one point to the corresponding current player score.
        Either `self.cpu_score` or `self.player_score`.
    win_message()
        Modify `self.end_message` to show a win or lose message.
    tie_message()
        Modify `self.end_message` to show a tied game message.
    get_cells():
        Return `self.cells` containing all the `graphics.Cell`
        sprite objects.
    is_player_turn():
        Return `True` when player's turn conditions are met.
        `False` otherwise.
    to_reset():
        Return `self.reset` attribute. Use to determine when
        to reset the game board.

    """

    def __init__(self):
        self.board = graphics.Board()
        self.board_logic = logic.Board()
        self.cells = self.create_cells(CELL)
        self.player_score = graphics.Text('P1 : 0',
                                          (WIDTH * 4 // 5, TOP * 1 // 3))
        self.cpu_score = graphics.Text('CPU : 0',
                                       (WIDTH * 4 // 5, TOP * 2 // 3))
        self.end_message = graphics.Text('',
                                         (WIDTH * 2 // 5, TOP // 2))
        self.player_play = False
        self.check = False
        self.reset = False
        self.timer = 0
        self.timer2 = 0

    def add_to_group(self, sprites_group):
        sprites_group.add(self.player_score)
        sprites_group.add(self.cpu_score)
        sprites_group.add(self.end_message)
        for cell in self.cells:
            sprites_group.add(cell)
        sprites_group.add(self.board)

    def create_cells(self, CELL=CELL):
        cells = ()
        for i in range(3):
            row = ()
            for j in range(3):
                pos = (self.board.rect.left + j * CELL,
                       self.board.rect.top + i * CELL)
                row.append(graphics.Cell(pos))
            cells.append(row)
        return cells

    def update(self):
        if self.check:
            if self.timer2 > CPU_SPEED // 2:
                self.timer2 = 0
                self.check = False
                if self.board_logic.check_winner():
                    self.board.draw_triple(self.board_logic.win_line_pos())
                    self.win_message()
                    self.update_score()
                    self.reset = True
                elif self.board_logic.endgame():
                    self.tie_message()
                    self.reset = True
            else:
                self.timer2 += 1

        if self.timer < CPU_SPEED:
            self.timer += 1
        else:
            self.timer = 0
            if not self.is_player_turn() and not self.to_reset():
                self.computer_turn()

    def computer_turn(self):
        i, j = self.board_logic.computer_turn()
        # print(self.board_logic)
        self.cells(i)(j).computer_fill()
        self.check = True
        self.player_play = True

    def player_turn(self, ij):
        self.timer = 0
        self.board_logic.user_turn(ij)
        i, j = ij
        self.cells(i)(j).player_fill()
        self.player_play = False
        self.check = True

    def reset_game(self):
        self.board.new_board()
        self.board_logic.reset()
        self.end_message.write('')
        for i in range(3):
            for j in range(3):
                self.cells(i)(j).reset()
        self.reset = False

    def update_score(self):
        if self.board_logic.current_player() == 'o':
            self.player_score.add1()
        else:
            self.cpu_score.add1()

    def win_message(self):
        if self.board_logic.current_player() == 'o':
            self.end_message.write('You win!')
        else:
            self.end_message.write('You lose!')

    def tie_message(self):
        self.end_message.write('     Tie!')

    def get_cells(self):
        return self.cells

    def is_player_turn(self):
        return self.player_play and not self.board_logic.check_winner()

    def to_reset(self):
        return self.reset


all_sprites = pygame.sprite.Group()
game = TicTacToe()
game.add_to_group(all_sprites)

# Game loop
running = True
while running:
    clock.tick(FPS)

    # Process input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONUP:
            if game.to_reset():
                game.reset_game()
            elif game.is_player_turn():
                pos = pygame.mouse.get_pos()
                cells = game.get_cells()
                for i in range(3):
                    for j in range(3):
                        if cells(i)(j).hits(pos):
                            game.player_turn((i, j))

    game.update()

    # Draw / render
    screen.fill(BLACK)
    all_sprites.draw(screen)
    pygame.display.flip()

pygame.quit()

I separated the code in different modules. The graphics module includes the classes to create the different sprites used by the game (the game board, the board cells and the text messages).
The logic module is used for the computer AI.

I’m sharing only this “game part” of the code because this is where I’d appreciate your comments. If you’d like to check the other modules or get them in order to play the game, you can do it here.

Thank you very much for your time.