Pygame相邻Tile点击时Sprite消失的Bug修复咨询
问题与解决方案:Pygame Tile点击Bug修复
问题现象
- 点击相邻两个Tile的中间位置时,一个Tile正常响应,另一个会莫名从屏幕消失
tileGroup中的Sprite数量从3变为2,但记录占用位置的taken列表仍显示有3个位置被占用- 点击消失Tile对应的空位,可重新触发该Tile显示
问题根源
核心问题出在cursor.destroyTile()方法里的pygame.sprite.spritecollide调用:
- 当鼠标点击相邻Tile中间时,光标Sprite的矩形会同时和两个Tile的矩形发生碰撞
spritecollide的第三个参数设为True,会删除所有碰撞到的Sprite,导致误删了未被点击的Tile- 后续
handleTiles()只从taken列表移除了一个位置,造成taken计数和实际Sprite数量不匹配
修复方案
- 替换碰撞检测逻辑:不再用光标Sprite做碰撞判断,直接根据鼠标点击位置计算对应的Tile坐标,精准删除目标Tile
- 确保
taken列表和tileGroup的状态完全同步
修改后的完整代码
import pygame import random import sys # 所有Tile的可能位置 grid = [[0,0], [0,150], [0,300], [0,450], [0,600], [150,0],[150,150],[150,300],[150,450],[150,600], [300,0],[300,150],[300,300],[300,450],[300,600], [450,0],[450,150],[450,300],[450,450],[450,600], [600,0],[600,150],[600,300],[600,450],[600,600]] taken = [] # 类定义 class Cursor(pygame.sprite.Sprite): def __init__(self, pic): super().__init__() self.image = pygame.image.load(pic).convert_alpha() self.image = pygame.transform.scale(self.image, (50,50)) self.rect = self.image.get_rect() def update(self): self.rect.topleft = pygame.mouse.get_pos() class Tiles(pygame.sprite.Sprite): def __init__(self, tileSize, color, x, y): super().__init__() self.image = pygame.Surface((tileSize, tileSize)) self.image.fill(color) self.rect = self.image.get_rect() self.rect.topleft = (x, y) # 记录Tile的坐标,方便后续精准匹配 self.pos = (x, y) def drawTiles(): while len(taken) != 3: m = random.randint(0,24) pos = grid[m] if pos not in taken: blackTile = Tiles(150, black, pos[0], pos[1]) blackTile.add(tileGroup) taken.append(pos) def handleTiles(clicked_pos): taken.remove(clicked_pos) drawTiles() # 颜色定义 white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) blue = (0, 0, 255) grey = (46, 46, 46) # 初始化Pygame pygame.init() clock = pygame.time.Clock() # 屏幕设置 screenWidth = 750 screenHeight = 900 screen = pygame.display.set_mode((screenWidth, screenHeight)) pygame.display.set_caption("Tiles Game") whiteSurface = pygame.Surface((750, 750)) whiteSurface.fill(white) pygame.mouse.set_visible(False) # 蓝色分隔线 line = pygame.Surface((750, 10)) line.fill(blue) # 精灵组 tileGroup = pygame.sprite.Group() cursor = Cursor("cursor.png") cursorGroup = pygame.sprite.Group() cursorGroup.add(cursor) score = 0 drawTiles() while True: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: score += 1 print(score) print(taken) print(tileGroup) # 计算点击的Tile坐标(仅处理网格内的点击) mx, my = pygame.mouse.get_pos() if mx < 750 and my <750: x = (mx // 150) * 150 y = (my // 150) * 150 clicked_pos = [x, y] # 精准删除对应位置的Tile for tile in tileGroup: if tile.pos == tuple(clicked_pos): tile.kill() break handleTiles(clicked_pos) # 绘制背景 screen.fill(grey) screen.blit(whiteSurface, (0,0)) screen.blit(line, (0,750)) tileGroup.draw(screen) cursorGroup.draw(screen) cursorGroup.update() pygame.display.update()
关键修改说明
- 给
Tiles类添加self.pos属性,存储Tile的坐标,用于后续精准匹配 - 删除了
Cursor类中的destroyTile方法,改用点击坐标直接定位目标Tile - 点击事件中用整数除法
//计算网格坐标,避免取模带来的边界判断问题 - 遍历
tileGroup找到对应坐标的Tile并删除,确保只移除被点击的那个Tile - 简化
drawTiles函数的逻辑,直接用len(taken)判断是否需要生成新Tile
内容的提问来源于stack exchange,提问作者fev31
相关产品推荐
相关产品推荐

