赞
踩
迁移 EasyDemo至 EasyDemo2,优化各项代码、理清逻辑,准备进入毕设第二阶段——完成网络部分
截至23.4.8,最近忙于学业外各种事的安排,今天终于清闲下来,正好把这几天调整的代码优化整理好了,接下来进入毕设1.5阶段——论文初稿撰写
最大的改动是对僵尸表和豌豆表的数据结构调整,之前僵尸表是用列表实现的队列,豌豆表是集合,我发现这样设定的话,检查僵尸和豌豆的碰撞将比较繁琐:要对每一个僵尸检测,对每一个豌豆检测是否碰撞,这是个双重for循环,时间复杂度很高。
然而可以发现,僵尸总是在右侧生成,豌豆总是在左侧生成,左边的豌豆若是与左边的僵尸碰撞,就代表不用再检测右边的僵尸,我考虑之后,发现对僵尸和豌豆的碰撞检测,其实是对两个链表的遍历,如果把僵尸表和豌豆表设置成链表,不仅检测碰撞可以一for而就,在检测的同时还可以绘图、实现相关方法(如扣血、删除对象),这将大大地降低遍历次数,从而使游戏流畅。
# 管理一行的僵尸 class ZbQue: grave = True class ZbNode: def __init__(self, aZB: Zombie): self.data: Zombie = aZB self.next = None self.prev = None def x(self) -> int | float: return self.data.pos.x def __init__(self, arow): zuizuo = ZB_normal((-2000, 0)) self.headN = self.ZbNode(zuizuo) # 头指针指向的结点才是真头 zuiyou = ZB_normal((20000, 0)) self.tailN = self.ZbNode(zuiyou) # 尾指针本身就代表是尾 self.headN.next = self.tailN self.tailN.prev = self.headN self.size = 0 self.row = arow self.pos = [Map_bottomright[0], 100 + (arow + 1) * Cell_size[1]] self.oppoPlRow = None self.scr = pygame.display.get_surface() # 队尾添加僵尸 def append(self, aZB): # 准备工作 newNode = self.ZbNode(aZB(self.pos)) # 双向调整插入 newNode.prev = self.tailN.prev newNode.next = self.tailN newNode.prev.next = newNode newNode.next.prev = newNode self.size += 1 def delete(self, aNode: ZbNode): aNode.prev.next = aNode.next aNode.next.prev = aNode.prev self.size -= 1 # 访问队首僵尸 def headZB(self) -> Zombie: if self.size > 0: return self.headN.next.data else: print('没僵尸,无法访问!') # 访问队尾僵尸 def tailZB(self) -> Zombie: if self.size > 0: return self.tailN.prev.data else: print('没僵尸,无法访问!') # 管理僵尸对植物的碰撞 def collision_ZB_PL(self, aZB): # 由该僵尸的位置定位到格子id,再判断该格左中右三格的碰撞 i = int((aZB.pos.x - Map_topleft[0]) // Cell_size[0]) def func(acol: int) -> bool: if not 0 <= acol <= 8: return False aPL = self.oppoPlRow.PLs[acol] if aPL is None: aZB.status = 'walk' return False elif pygame.sprite.collide_circle(aPL, aZB): aZB.status = 'eat' aPL.HP -= aZB.ATK return True if 0 <= i <= 8: for delta in [-1, 0, 1]: if func(i - delta): break # 管理游戏失败判断 def collision_ZB_Mapleft(self): # 游戏失败判断 if self.size > 0 \ and self.headZB().pos.x < Map_topleft[0]: if self.oppoPlRow.car.status == 'ready': self.oppoPlRow.car.status = 'run' elif self.headZB().rect.right < Map_topleft[0]: GameData['status'] = 'self.gamelose' # 管理一行的豌豆 class PeaChain: class PeaNode: def __init__(self, aPea: Pea): self.data = aPea self.next = None self.prev = None def x(self) -> int | float: return self.data.pos.x def __init__(self, arow): zuizuo = Pea((-1000, 0)) self.headN = self.PeaNode(zuizuo) # 头指针指向的结点才是真头 zuiyou = Pea((10000, 0)) self.tailN = self.PeaNode(zuiyou) # 尾指针本身就代表是尾 self.headN.next = self.tailN self.tailN.prev = self.headN self.size = 0 self.row = arow def collision_Pea_MapRight(self, aPeaN: PeaNode): if aPeaN.data.pos.x > Map_bottomright[0]: self.delete(aPeaN) def insert(self, aPea): newNode = self.PeaNode(aPea) pNode = self.headN # 按规则,新豌豆应当插在自己右边第一个豌豆左边 # 若指针豌豆在新豌豆左边,则不是理想插入点 while pNode.data.pos.x < newNode.data.pos.x: pNode = pNode.next # 一定可以找到合适插入点 else: newNode.prev = pNode.prev newNode.next = pNode pNode.prev.next = newNode pNode.prev = newNode self.size += 1 def delete(self, aNode: PeaNode): aNode.prev.next = aNode.next aNode.next.prev = aNode.prev self.size -= 1 # 豌豆表的尾豌豆是最右的有效豌豆 def tailPea(self) -> Pea: if self.size > 0: return self.tailN.prev.data
植物大战僵尸 简单ai-成功
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。