为迷宫墙添加碰撞

2023-12-09

有人可以帮我向我的精灵添加碰撞点吗?我过去有一个代码,我在图像上分层了位图,但相同的代码不能很好地集成用于物理绘制线条,而不是检测图像上黑色/灰色的位置

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

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

        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

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

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():
    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 == True:
            pygame.init()

            while not done:
                events = pygame.event.get()

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

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

                sprites.update(None, dt)

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

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


main()
pygame.quit()

如果有人能帮助我或为我指明正确的方向,我会很高兴。


    end_rect = pygame.draw.rect(screen, RED, (800-width, 600-width, width, width))
    if player.rect.colliderect(end_rect):
                    screen.fill(BLACK)
                    end = True

确保Player对象位于单元格的中心grid。例如计算一个随机位置player:

def load_player(background):
    pimg = pygame.Surface((10, 10))
    pimg.fill((200, 20, 20))
    
    px = random.randint(0, rows-1) * width + width//2
    py = random.randint(0, cols-1) * width + width//2
    return Player(pimg, (px, py), background)

要跟踪玩家,但突出显示玩家位置,在更新并重新绘制玩家之前,必须将当前玩家位置着色为不同的颜色:

pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)

对于碰撞测试:

  • 玩家当前的位置grid必须被识别。
  • 必须确定取决于运动的球员的新的可能的新位置。
  • 如果从当前位置到新位置的轨道上有墙,则必须跳过该移动
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))

        # calculate maximum movement and current cell position  
        testdist = dt // 5 + 2
        cellx = self.rect.centerx // width
        celly = self.rect.centery // width
        minx = self.rect.left // width
        maxx = self.rect.right // width
        miny = self.rect.top // width
        maxy = self.rect.bottom // width
        
        # test move up
        if minx == maxx and pressed[pygame.K_w]:
            nexty = (self.rect.top-testdist) // width
            if celly == nexty or (nexty >= 0 and not grid[celly][cellx].walls[0]):
                move += (0, -1)

        # test move right
        elif miny == maxy and pressed[pygame.K_d]:
            nextx = (self.rect.right+testdist) // width
            if cellx == nextx or (nextx < cols and not grid[celly][cellx].walls[1]):
                move += (1, 0)
               
        # test move down
        elif minx == maxx and pressed[pygame.K_s]:
            nexty = (self.rect.bottom+testdist) // width
            if celly == nexty or (nexty < rows and not grid[celly][cellx].walls[2]):
                move += (0, 1)            

        # test move left
        elif miny == maxy and pressed[pygame.K_a]:
            nextx = (self.rect.left-testdist) // width
            if cellx == nextx or (nextx >= 0 and not grid[celly][cellx].walls[3]):
                move += (-1, 0)
        
        self.pos = self.pos + move*(dt/5)
        self.rect.center = self.pos        


如果你想重新开始迷宫,你必须摆脱嵌套的游戏循环。使用 1 个游戏循环和一个条件,该条件表明游戏是否处于play状态或初始化迷宫。

要检查玩家是否已达到目标,可以通过以下方式完成pygame.Rect.colliderect():

finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)

要重新启动,您必须重置grid:

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

将玩家设置为新的随机位置:

px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)

清除背景并重置状态play:

screen.fill(0)
play = False

Full main code:

def main():
    global current_cell, grid

    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

        if play == True:
            
            pygame.draw.rect(screen, (255, 164, 164), player.rect)
            sprites.update(None, dt)
            sprites.draw(screen)

            dt = clock.tick(60)

            finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
            if finished:
                # init new grid
                grid = []
                for y in range(rows):
                    grid.append([])
                    for x in range(cols):
                        grid[y].append(Cell(x,y))
                current_cell = grid[0][0]
                # create new random player positon
                px = random.randint(0, rows-1) * width + width//2
                py = random.randint(0, cols-1) * width + width//2
                player.pos = pygame.Vector2(px, py)
                player.rect = player.image.get_rect(center=player.pos)
                # clear screen
                screen.fill(0)
                play = False

        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

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

        pygame.display.flip()

也可以看看如何防止玩家穿过迷宫中的墙壁?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为迷宫墙添加碰撞 的相关文章

  • 将 JSON 发布到 Python CGI

    我已经安装了 Apache2 并且 Python 可以工作 但我有一个问题 我有两页 一个是 Python 页面 另一个是带有 JQuery 的 Html 页面 有人可以告诉我如何让我的 ajax 帖子正常工作吗
  • 为什么 Python 在导入脚本时只保存脚本的字节码?

    既然执行Python字节码会比运行原始源代码更快 因为Python不需要重新编译 为什么Python在导入脚本时只保存编译后的字节码呢 为每个执行的脚本保存 pyc 文件不是更好吗 无论如何 Python 解释器的启动时间都需要时间 即使您
  • 如何在 Debian 上的 virtualenv 中安装 numpy?

    注 参见这另一篇文章 https stackoverflow com questions 6442754 how to install h5py numpylibhdf5 as non root on a debian linux syst
  • 如何使用一个模型中间层的输出作为另一个模型的输入?

    我训练一个模型A并尝试使用中间层的输出name layer x 作为模型的附加输入B 我尝试像 Keras 文档一样使用中间层的输出https keras io getting started faq how can i obtain th
  • 为什么在连接两个字符串时 Python 比 C 更快?

    目前我想比较 Python 和 C 用来处理字符串的速度 我认为 C 应该比 Python 提供更好的性能 然而 我得到了完全相反的结果 这是 C 程序 include
  • 雅虎财务请求功能出现 404 客户端错误

    yahoo Financials的请求功能出现404 Client Error 直接点击以下网址没有问题 https finance yahoo com quote AAPL financials p AAPL https finance
  • 将 Python Pandas DataFrame 写入 Word 文档

    我正在努力创建一个使用 Pandas DataFrames 的 Python 生成的报告 目前我正在使用DataFrame to string 方法 但是 这会作为字符串写入文件 有没有办法让我实现这一目标 同时将其保留为表格 以便我可以使
  • 使用 NumPy 编写一个函数来计算具有特定公差的积分

    我想编写一个自定义函数来以特定容差对表达式 python 或 lambda 函数 进行数字积分 我知道与scipy integrate quad人们可以简单地改变epsabs但我想使用 numpy 自己编写该函数 From 这篇博文 htt
  • 使用pathlib获取主目录

    翻看新的pathlib在 Python 3 4 中 我注意到没有任何简单的方法来获取用户的主目录 我能想到的获取用户主目录的唯一方法是使用旧的os path像这样的库 import pathlib from os import path p
  • 设置高亮大括号的 vim 颜色主题

    如何更改突出显示大括号的 vim 配色方案 我希望实际编辑 vim 主题文件以使更改永久生效 问候 克雷格 匹配括号的自动高亮颜色称为MatchParen 您可以通过执行以下操作来更改 vimrc 中的颜色 highlight MatchP
  • 查找与另一列 Pandas 中的唯一值关联的列中的值的交集

    如果我有一个像这样的数据框 非常小的例子 col1 col2 0 a 1 1 a 2 2 b 1 3 b 2 4 b 4 5 c 1 6 c 2 7 c 3 我想要所有的交集col2当价值观与其独特性相关时col1值 因此在这种情况下 交集
  • 在请求中设置端口

    我正在尝试利用cgminer使用 Python 的 API 我对利用requests图书馆 我了解如何做基本的事情requests but cgminer想要更具体一点 我想缩小 import socket import json sock
  • 为什么将模块级代码放入函数中然后调用该函数在Python中速度更快?

    在亚历克斯 马尔泰利的回应中使 Python 脚本面向对象 https stackoverflow com questions 1813117 making a python script object oriented 他提到在 Pyth
  • python Recipe:列出最接近等于值的项[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 考虑像这样的列表 0 3 7 10 12 15 19 21 我想获得最接近任何值的最近的最小数字 所以如果我通过4 我会得到3 如果我
  • Seaborn 中没有线性拟合的散点图

    我想知道是否有办法关闭seaborn中的线性拟合lmplot或者是否有一个等效函数可以生成散点图 当然 我也可以使用 matplotlib 但是 我发现 seaborn 中的语法和美学非常吸引人 例如 我想绘制以下情节 import sea
  • 为什么 Collections.counter 这么慢?

    我正在尝试解决罗莎琳德的基本问题 即计算给定序列中的核苷酸 并在列表中返回结果 对于那些不熟悉生物信息学的人来说 它只是计算字符串中 4 个不同字符 A C G T 出现的次数 我期望collections Counter是最快的方法 首先
  • 是否可以在Python中将日+月(不是年)与当前日+月进行比较?

    我正在获取 5 月 10 日 格式的数据 我试图弄清楚它是今年还是明年 该日期仅一年 因此 5 月 10 日表示 2015 年 5 月 10 日 而 5 月 20 日表示 2014 年 5 月 20 日 为此 我想将字符串转换为日期格式并进
  • 从 wxPython 事件处理程序中调用函数

    我正在努力寻找一种在 wxPython 事件处理函数中使用函数的方法 假设我有一个按钮 单击该按钮时 它会使用事件处理程序运行一个名为 OnRun 的函数 但是 用户忘记单击 OnRun 按钮之前的 RadionButton 我想弹出一个
  • 两种 ODE 求解器之间的差异

    我想知道 两者之间有什么区别ODEINT and solve ivp用于求解微分方程 它们之间有什么优点和缺点 f1 solve ivp f 0 1 y0 y0 is the initial point f2 odeint f y0 0 1
  • 使用 pandas 单元格中列表的长度选择行[重复]

    这个问题在这里已经有答案了 我有一张表 df a b c 1 x y x 2 x z c d 3 x t e f g 只是想知道如何使用 c 列的长度选择行 such as df loc len df c gt 1 我知道这是不对的 正确的

随机推荐

  • Android项目结构不正确;只有一个 build.gradle

    我的项目结构不正确 我需要一个顶级的 build gradle 以及一个包含其自己的同一级别的模块build gradle 请参阅它现在的组织方式的图片 你看到的几乎是两个不同的层次合并成一个 ebuild gradle这是项目中唯一的一个
  • jQuery 原型冲突

    我使用prototype和script aculo us的组合在我的asp net页面中实现灯箱效果 我的页面中还包含jquery 我的页面中有几个DIV标签 但是在将prototype文件包含在我的页面头部 我无法使用 jquery 读取
  • 使用 DocuSign REST API 获取/设置模板字段

    我在 DocuSign 沙箱中创建了一个测试模板 为与另一个系统进行一些自动化做准备 我正在尝试填充这些自定义字段 因为需要包含动态输入的数据 到目前为止 我在身份验证 创建基于模板的 信封 或分配角色方面没有遇到任何问题 我可以毫无问题地
  • 在 Domino Java 代理中使用枚举单例编码模式

    这是我尝试运行的非常简化的 Lotus Domino Java 代理代码 import lotus domino enum SingletonTest INSTANCE public void helloWorld System out p
  • Class#getClassLoader 什么时候返回 null?

    假设我有一些 Java 代码 public class Widget whatever 以及一些类加载的代码Widget ClassLoader widgetLoader Widget class getClassLoader Can wi
  • Angular2 使用对象数组排序管道

    如何使用对象数组在 angular2 中制作排序管道 原始问题 我有一个 TODO 列表 Todo 我想在每次进行一些更改时对其进行排序 我希望已完成的待办事项显示在列表底部 Todo 对象有一个名为 completed 的属性 它存储一个
  • 如何在 vbscript 中解压受密码保护的文件?

    我对 VBScript 还很陌生 我对我想要实现的目标做了一些广泛的研究 甚至找到了该怎么做的例子 但无法让它正常工作 在我的完美世界中 我需要解压缩从第三方供应商发送到文件夹的所有压缩文件 将解压缩的文件导入到不同的文件夹中 然后删除压缩
  • 读取缓冲的二进制文件(带查找)

    假设我需要读取巨大的整数二进制文件 一个方便的方法是 FileInputStream fi new FileInputStream file BufferedInputStream bi new BufferedInputStream fi
  • 查找当前 EntityManagerFactory 的当前持久化单元

    我注意到打电话createEntityManagerFactory null 将使用配置文件中的默认持久性单元 PU 有时 类路径在部署时真的很混乱 我真的很想查看给定 EntityManagerFactory 的当前 PU 的名称 有什么
  • 使用discord.py 让机器人响应图像

    使用discord py 进行机器人编码的新手 正如标题所示 我希望有人能告诉我如何让机器人响应某人发送的图像 无论是从互联网粘贴还是从计算机上传 当然 您可以使用 attachments client event async def on
  • 我需要一个正则表达式将美国电话号码转换为链接

    基本上 输入字段只是一个字符串 人们以各种格式输入电话号码 我需要一个正则表达式来查找这些数字并将其转换为链接 输入示例 201 555 1212 201 555 1212 201 555 1212 555 1212 这就是我想要的 a h
  • socket.error: [Errno 48] 地址已在使用中

    我正在尝试从 mac 终端使用 python 设置服务器 我导航到文件夹位置并使用 python m SimpleHTTPServer 但这给了我错误 socket error Errno 48 Address already in use
  • 使用 Gspread 在文件夹中创建电子表格

    我无法找到有关如何使用 Gspread 在某个 Google Drive 目录中创建 GSheet 的任何文档 我检查了文档并查看了一些后端代码 我目前正在使用下面的代码来创建电子表格 worksheet sh add worksheet
  • 如何将Asterisk服务器与外部关系数据库(例如mysql)集成?

    我的目标 客户端 SIP电话 我使用3CX电话 拨号到asterisk服务器 asterisk然后连接外部关系数据库 与asterisk服务器不在同一位置 如果数据库响应某些内容 asterisk服务器播放语音文件 预定义的 gsm 文件
  • 传递 URL 中包含“%”的参数?

    例如 在传递我的网址时something 8000 something jsp param1 update param2 1000 param3 SearchString param4 3 我收到以下错误 Bad Request Your
  • 将每个组中的行替换为第一行值。熊猫集团

    这是一个数据框 df pd DataFrame A foo foo bar bar bar B 1 2 2 4 1 下面是我想要的样子 这就是我的尝试和失败的方法 groups df groupby A groups apply lambd
  • 使用 jQuery 滚动到某个元素

    我有这个input元素
  • 如何从 C++ 更改 Windows shell (cmd.exe) 环境变量?

    我想编写一个程序 在调用它的 shell cmd exe 实例中设置环境变量 我的想法是 我可以在这个变量中存储一些状态 然后在后续调用中再次使用它 我知道有像 SetEnvironmentVariable 这样的命令 但我的理解是这些命令
  • 在 msi 自定义操作中执行时,MsiOpenDatabaseW 引发访问冲突

    我有一个代码可以修改cached 不是正在安装的 msi 安装程序数据库工作正常在独立 exe 中执行时 但是当它从 msi 自定义操作中运行时 我遇到了非常奇怪的访问冲突 const auto msiProductCode GetProd
  • 为迷宫墙添加碰撞

    有人可以帮我向我的精灵添加碰撞点吗 我过去有一个代码 我在图像上分层了位图 但相同的代码不能很好地集成用于物理绘制线条 而不是检测图像上黑色 灰色的位置 import random import pygame pygame init WHI