碰撞时如何摧毁防护墙周边方块?求邻接方块坐标获取方案
解决防护墙邻接矩形摧毁问题
核心思路
要实现碰撞时摧毁目标矩形及其左右、下方邻接块,关键是给每个防护墙矩形标记网格坐标(即生成时的i列索引和j行索引),通过坐标快速定位邻接块后统一删除。
步骤1:给Boden类添加网格坐标属性
生成防护墙时,每个矩形是按i(列)、j(行)循环创建的,把这两个索引作为实例属性存下来,方便后续定位邻接块。
快速修改方式:直接给实例加属性
for j in range(int(bodenebenen)): for i in range(int(bodenspalten)): m = Boden(int(i)*bodenbreite, int(j)*bodenhoehe, int(bodenbreite), int(bodenhoehe), 620, schutzcolor[random.randint(0, len(schutzcolor)-1)]) # 标记当前矩形的网格坐标 m.grid_i = i m.grid_j = j protectivewall.add(m) alle_sprites.add(m)
规范修改方式:调整Boden类初始化
class Boden(pygame.sprite.Sprite): def __init__(self, x, y, width, height, param, color, grid_i, grid_j): super().__init__() # 原有初始化逻辑(比如创建rect、设置颜色等) self.rect = pygame.Rect(x, y, width, height) self.color = color # 新增网格坐标属性 self.grid_i = grid_i self.grid_j = grid_j # 创建防护墙时传入网格坐标 for j in range(int(bodenebenen)): for i in range(int(bodenspalten)): m = Boden(int(i)*bodenbreite, int(j)*bodenhoehe, int(bodenbreite), int(bodenhoehe), 620, schutzcolor[random.randint(0, len(schutzcolor)-1)], i, j) protectivewall.add(m) alle_sprites.add(m)
步骤2:捕获碰撞并处理邻接块
不要直接用groupcollide的True,True参数立即删除对象,先收集所有要摧毁的矩形,再批量删除:
# 获取碰撞关系,暂不删除任何对象 hits = pygame.sprite.groupcollide(bombs, protectivewall, False, False) # 用集合存储待删除矩形(避免重复) to_remove = set() for bomb, collided_blocks in hits.items(): # 先把碰撞的矩形加入待删除集合 to_remove.update(collided_blocks) for block in collided_blocks: # 定义邻接网格坐标:左(i-1,j)、右(i+1,j)、下(i,j+1) adjacent_grids = [ (block.grid_i - 1, block.grid_j), (block.grid_i + 1, block.grid_j), (block.grid_i, block.grid_j + 1) ] # 遍历防护墙,匹配邻接坐标的矩形 for candidate in protectivewall: if (candidate.grid_i, candidate.grid_j) in adjacent_grids: to_remove.add(candidate) # 摧毁当前炸弹 bomb.kill() # 批量删除所有待摧毁的防护墙矩形 for block in to_remove: block.kill()
优化:用字典加速邻接块查找
如果防护墙数量较多,遍历全部块找邻接会影响性能,可以提前构建网格坐标到矩形实例的映射字典:
# 创建防护墙时同时构建坐标映射字典 grid_map = {} for j in range(int(bodenebenen)): for i in range(int(bodenspalten)): m = Boden(int(i)*bodenbreite, int(j)*bodenhoehe, int(bodenbreite), int(bodenhoehe), 620, schutzcolor[random.randint(0, len(schutzcolor)-1)], i, j) protectivewall.add(m) alle_sprites.add(m) grid_map[(i, j)] = m # 处理碰撞时直接通过字典查找邻接块 hits = pygame.sprite.groupcollide(bombs, protectivewall, False, False) to_remove = set() for bomb, collided_blocks in hits.items(): to_remove.update(collided_blocks) for block in collided_blocks: adjacent_grids = [ (block.grid_i - 1, block.grid_j), (block.grid_i + 1, block.grid_j), (block.grid_i, block.grid_j + 1) ] # 直接从字典取邻接块,无需遍历全部防护墙 for grid in adjacent_grids: if grid in grid_map: to_remove.add(grid_map[grid]) bomb.kill() for block in to_remove: block.kill()
内容的提问来源于stack exchange,提问作者Joachim
相关产品推荐
相关产品推荐

