【问题标题】:Integrating sprite snippet into maze program将精灵片段集成到迷宫程序中
【发布时间】:2019-04-12 12:01:59
【问题描述】:

我正在尝试将此代码与我的精灵代码自动生成迷宫的代码集成,但是当我尝试添加我的精灵代码 sn-p 时,程序一直出错。

我试图删除和重新定义变量,并用我自己的 sn-p 对齐程序变量

import random
import pygame
pygame.init()

WHITE = (255,255,255)
GREY = (20,20,20)
BLACK = (0,0,0)
PURPLE = (100,0,100)
RED = (255,0,0)

size = (701,701)
screen = pygame.display.set_mode(size)

pygame.display.set_caption("Maze Generator")

done = False

clock = pygame.time.Clock()

width = 25
cols = int(size[0] / width)
rows = int(size[1] / width)

stack = []

pos = (0,0)
class Player(pygame.sprite.Sprite):
    def __init__(self, image, pos, background):
        super().__init__()
        self.image = image
        self.pos = pygame.Vector2(pos)
        self.rect = self.image.get_rect(center=self.pos)
        self.background = background

    def update(self, events, dt):
        pressed = pygame.key.get_pressed()
        move = pygame.Vector2((0, 0))
        if pressed[pygame.K_w]: move += (0, -1)
        if pressed[pygame.K_a]: move += (-1, 0)
        if pressed[pygame.K_s]: move += (0, 1)
        if pressed[pygame.K_d]: move += (1, 0)
        #if move.length() > 0: move.normalise_ip()

        new_pos = self.pos + move*(dt/5)
        new_rect = self.rect.copy()
        new_rect.center = new_pos
        new_rect.clamp_ip(self.background.get_rect())
        new_pos = new_rect.center

        hit_box = self.background.subsurface(new_rect)
        for x in range(new_rect.width):
            for y in range(new_rect.height):
                if sum(hit_box.get_at((x, y))) < 500:
                    return

def load_background(filename):
    background = (pygame.image.load("background.jpg"))
    background = pygame.transform.rotate(background, -90)
    background = pygame.transform.scale(background, (800,600))
    return background

def load_player(background):
    pimg = pygame.Surface((10, 10))
    pimg.fill((200, 20, 20))
    return Player(pimg, (25, 325), background)

class Cell():
    def __init__(self,x,y):
        global width
        self.x = x * width
        self.y = y * width

        self.visited = False
        self.current = False

        self.walls = [True,True,True,True] # top , right , bottom , left

        # neighbors
        self.neighbors = []

        self.top = 0
        self.right = 0
        self.bottom = 0
        self.left = 0

        self.next_cell = 0

    def draw(self):
        if self.current:
            pygame.draw.rect(screen,RED,(self.x,self.y,width,width))
        elif self.visited:
            pygame.draw.rect(screen,WHITE,(self.x,self.y,width,width))

            if self.walls[0]:
                pygame.draw.line(screen,BLACK,(self.x,self.y),((self.x + width),self.y),1) # top
            if self.walls[1]:
                pygame.draw.line(screen,BLACK,((self.x + width),self.y),((self.x + width),(self.y + width)),1) # right
            if self.walls[2]:
                pygame.draw.line(screen,BLACK,((self.x + width),(self.y + width)),(self.x,(self.y + width)),1) # bottom
            if self.walls[3]:
                pygame.draw.line(screen,BLACK,(self.x,(self.y + width)),(self.x,self.y),1) # left

    def checkNeighbors(self):
        #print("Top; y: " + str(int(self.y / width)) + ", y - 1: " + str(int(self.y / width) - 1))
        if int(self.y / width) - 1 >= 0:
            self.top = grid[int(self.y / width) - 1][int(self.x / width)]
        #print("Right; x: " + str(int(self.x / width)) + ", x + 1: " + str(int(self.x / width) + 1))
        if int(self.x / width) + 1 <= cols - 1:
            self.right = grid[int(self.y / width)][int(self.x / width) + 1]
        #print("Bottom; y: " + str(int(self.y / width)) + ", y + 1: " + str(int(self.y / width) + 1))
        if int(self.y / width) + 1 <= rows - 1:
            self.bottom = grid[int(self.y / width) + 1][int(self.x / width)]
        #print("Left; x: " + str(int(self.x / width)) + ", x - 1: " + str(int(self.x / width) - 1))
        if int(self.x / width) - 1 >= 0:
            self.left = grid[int(self.y / width)][int(self.x / width) - 1]
        #print("--------------------")

        if self.top != 0:
            if self.top.visited == False:
                self.neighbors.append(self.top)
        if self.right != 0:
            if self.right.visited == False:
                self.neighbors.append(self.right)
        if self.bottom != 0:
            if self.bottom.visited == False:
                self.neighbors.append(self.bottom)
        if self.left != 0:
            if self.left.visited == False:
                self.neighbors.append(self.left)

        if len(self.neighbors) > 0:
            self.next_cell = self.neighbors[random.randrange(0,len(self.neighbors))]
            return self.next_cell
        else:
            return False

def removeWalls(current_cell,next_cell):
    x = int(current_cell.x / width) - int(next_cell.x / width)
    y = int(current_cell.y / width) - int(next_cell.y / width)
    if x == -1: # right of current
        current_cell.walls[1] = False
        next_cell.walls[3] = False
    elif x == 1: # left of current
        current_cell.walls[3] = False
        next_cell.walls[1] = False
    elif y == -1: # bottom of current
        current_cell.walls[2] = False
        next_cell.walls[0] = False
    elif y == 1: # top of current
        current_cell.walls[0] = False
        next_cell.walls[2] = False

grid = []

for y in range(rows):
    grid.append([])
    for x in range(cols):
        grid[y].append(Cell(x,y))

current_cell = grid[0][0]
next_cell = 0

# -------- Main Program Loop -----------
def main():
    while not done:
        # --- Main event loop
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

        global current_cell
        play = False
        current_cell.visited = True
        current_cell.current = True

        for y in range(rows):
            for x in range(cols):
                grid[y][x].draw()

        next_cell = current_cell.checkNeighbors()

        if next_cell != False:
            current_cell.neighbors = []

            stack.append(current_cell)

            removeWalls(current_cell,next_cell)

            current_cell.current = False

            current_cell = next_cell

        elif len(stack) > 0:
            current_cell.current = False
            current_cell = stack.pop()
            play = True 

        """    
        elif len(stack) == 0:
            grid = []

            for y in range(rows):
                grid.append([])
                for x in range(cols):
                    grid[y].append(Cell(x,y))

            current_cell = grid[0][0]
            next_cell = 0
        """
        if play == True:
            pygame.init()
            screen_rect = screen.get_rect()

            clock = pygame.time.Clock()
            sprites = pygame.sprite.Group()

            player = None
            initialized = False
            current_maze = None
            dt = 0

            while True:
                events = pygame.event.get()

                for e in events:
                    if e.type == pygame.QUIT:
                        return

                if not initialized:
                    #current_maze = 0
                    background = load_background
                    player = load_player(background)
                    sprites.add(player)
                    initialized = True

                player_x = player.pos[0]
                player_y = player.pos[1]

                if player_x >= 780 and 275 < player_y < 375:
                    current_maze += 1

                    # reset to first maze if all mazes were done
                    if current_maze >= mazes_len:
                        current_maze = 0

                    background = load_background(mazes[current_maze])
                    sprites.empty()
                    player = load_player(background)
                    sprites.add(player)

                sprites.update(events, dt)

                screen.fill(pygame.Color('grey'))
                screen.blit(background, (0, 0))

                sprites.draw(screen)
                pygame.display.flip()
                dt = clock.tick(60)

        pygame.display.flip()


main()
pygame.quit()

如果有人可以帮助我找出实际问题所在,那就太棒了生成迷宫程序。

【问题讨论】:

  • 我们能看到错误吗?
  • “当前”错误是这样的:new_rect.clamp_ip(self.background.get_rect()) AttributeError: 'function' object has no attribute 'get_rect'

标签: python pygame


【解决方案1】:

The issue is the assignment of the function objectload_backgroundtobackground` 在主循环中:

background = load_background

你必须调用函数load_background并将返回值赋给background

background = load_background()

我建议给函数load_background的参数添加一个默认参数值:

def load_background(filename=None):
    name = filename if filename else "background.jpg"
    background = pygame.image.load(name)
    background = pygame.transform.rotate(background, -90)
    background = pygame.transform.scale(background, (800,600))
    return background

如果你想选择性地丢弃背景,那么设置

background = None

并在绘制或访问背景之前检查背景是否存在:

if background:
    screen.fill(pygame.Color('grey'))
    screen.blit(background, (0, 0)) 
class Player(pygame.sprite.Sprite):

    # [...]

    def update(self, events, dt):

        # [...]

        if self.background:

            new_rect.clamp_ip(self.background.get_rect())
            new_pos = new_rect.center

            hit_box = self.background.subsurface(new_rect)
            for x in range(new_rect.width):
                for y in range(new_rect.height):
                    if sum(hit_box.get_at((x, y))) < 500:
                        return

避免主循环内的额外循环。应用程序应该在一个循环中运行。在主循环旁边应该有一个事件循环。

变量play为状态,表示迷宫是否已搭建好或游戏是否处于运行状态:

# initilization
# [...]

while not done:

    # event loop
    for event in pygame.event.get():

        # [...]

    if play:

        # play 
        # [...]

    else:

        # create maze
        # [...]

stack 为空时必须设置状态play

        if next_cell != False:
            current_cell.neighbors = []
            stack.append(current_cell)
            removeWalls(current_cell,next_cell)
            current_cell.current = False
            current_cell = next_cell
        elif len(stack) > 0:
            current_cell.current = False
            current_cell = stack.pop()
        else:
            play = True

main 函数可能如下所示:

def main():

    global current_cell

    player = None
    initialized = False
    current_maze = None
    dt = 0  
    screen_rect = screen.get_rect()
    clock = pygame.time.Clock()
    sprites = pygame.sprite.Group()

    if not initialized:
        #current_maze = 0
        background = load_background()
        background = None
        player = load_player(background)
        sprites.add(player)
        initialized = True

    play = False
    while not done:
        # --- Main event loop
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

        for y in range(rows):
            for x in range(cols):
                grid[y][x].draw()

        if play:

            # [...]

            sprites.update(None, dt)

            # [...]

            sprites.draw(screen)
            pygame.display.flip()
            dt = clock.tick(60)

        else:
            current_cell.visited = True
            current_cell.current = True

            next_cell = current_cell.checkNeighbors()
            if next_cell != False:
                current_cell.neighbors = []
                stack.append(current_cell)
                removeWalls(current_cell,next_cell)
                current_cell.current = False
                current_cell = next_cell
            elif len(stack) > 0:
                current_cell.current = False
                current_cell = stack.pop()
            else:
                play = True

        pygame.display.flip()

最后玩家不会移动,因为self.pos 永远不会改变,self.rect 永远不会设置。
Player.update中设置self.rect

def update(self, events, dt):
    pressed = pygame.key.get_pressed()
    move = pygame.Vector2((0, 0))
    if pressed[pygame.K_w]: move += (0, -1)
    if pressed[pygame.K_a]: move += (-1, 0)
    if pressed[pygame.K_s]: move += (0, 1)
    if pressed[pygame.K_d]: move += (1, 0)

    self.pos = self.pos + move*(dt/5)
    self.rect.center = self.pos 

【讨论】:

  • 我如何将整个图片背景功能一起删除,因为运行时背景会出现在生成的实际迷宫上
  • 最后一个问题。添加精灵时,我将如何检查红色块的位置,以便程序知道在整个迷宫生成后运行精灵函数
  • colision 如何在这里工作,精灵直接穿过墙壁
  • @KallumHancox 是的,我知道,但是对于这个问题,您发布了一个新问题:Adding collision to maze walls。我正在研究新问题的答案。请耐心等待。
  • 是的,我知道,但是对于那个问题,你已经发布了一个新问题,(Adding collision to maze walls),我现在已经回答了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
相关资源
最近更新 更多