加入毁灭菇
BIN
resources/graphics/Cards/card_doomshroom.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_0.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_1.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_2.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_3.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_4.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_5.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_6.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_7.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_8.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
resources/graphics/Plants/DoomShroom/DoomShroom/DoomShroom_9.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
BIN
resources/graphics/Plants/Hole/Hole/Hole_0.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
resources/graphics/Plants/Hole/HoleRoof/HoleRoof_0.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
BIN
resources/graphics/Plants/Hole/HoleShallow/HoleShallow_0.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
resources/graphics/Plants/Hole/HoleWater/HoleWater_0.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
BIN
resources/sound/doomshroom.ogg
Normal file
@ -42,6 +42,8 @@ class Map():
|
||||
# 注意咖啡豆生效后需要同时将植物的睡眠状态和格子的睡眠记录改变
|
||||
def isAvailable(self, map_x, map_y, plantName):
|
||||
# 咖啡豆的判别最为特殊
|
||||
if (c.HOLE in self.map[map_y][map_x][c.MAP_PLANT]) or (c.ICE_FROZEN_PLOT in self.map[map_y][map_x][c.MAP_PLANT]):
|
||||
return False
|
||||
if plantName == c.COFFEEBEAN:
|
||||
if self.map[map_y][map_x][c.MAP_SLEEP] and (plantName not in self.map[map_y][map_x][c.MAP_PLANT]):
|
||||
return True
|
||||
|
||||
@ -57,6 +57,10 @@ plantInfo = (# 元组 (植物名称, 卡片名称, 阳光, 冷却时间)
|
||||
c.CARD_ICESHROOM,
|
||||
75,
|
||||
50000),
|
||||
(c.DOOMSHROOM,
|
||||
c.CARD_DOOMSHROOM,
|
||||
75,
|
||||
50000),
|
||||
(c.LILYPAD,
|
||||
c.CARD_LILYPAD,
|
||||
25,
|
||||
|
||||
@ -446,7 +446,7 @@ class WallNut(Plant):
|
||||
|
||||
class CherryBomb(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.CHERRYBOMB, c.WALLNUT_HEALTH, None)
|
||||
Plant.__init__(self, x, y, c.CHERRYBOMB, c.INF, None)
|
||||
self.state = c.ATTACK
|
||||
self.start_boom = False
|
||||
self.bomb_timer = 0
|
||||
@ -680,7 +680,7 @@ class Squash(Plant):
|
||||
self.zombie_group = zombie_group
|
||||
self.state = c.ATTACK
|
||||
# 攻击状态下生命值无敌
|
||||
self.health = float('inf')
|
||||
self.health = c.INF
|
||||
|
||||
def attacking(self):
|
||||
if self.squashing:
|
||||
@ -742,7 +742,7 @@ class Spikeweed(Plant):
|
||||
|
||||
class Jalapeno(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.JALAPENO, c.PLANT_HEALTH, None)
|
||||
Plant.__init__(self, x, y, c.JALAPENO, c.INF, None)
|
||||
self.orig_pos = (x, y)
|
||||
self.state = c.ATTACK
|
||||
self.start_explode = False
|
||||
@ -1171,17 +1171,23 @@ class StarFruit(Plant):
|
||||
|
||||
|
||||
class CoffeeBean(Plant):
|
||||
def __init__(self, x, y, plant_group, mapContent):
|
||||
def __init__(self, x, y, plant_group, mapContent, map, map_x):
|
||||
Plant.__init__(self, x, y, c.COFFEEBEAN, c.PLANT_HEALTH, None)
|
||||
self.plant_group = plant_group
|
||||
self.mapContent = mapContent
|
||||
self.map = map
|
||||
self.map_x = map_x
|
||||
|
||||
def idling(self):
|
||||
if (self.frame_index + 1) == self.frame_num:
|
||||
self.mapContent[c.MAP_SLEEP] = False
|
||||
# 注意:这里有bug —— 未判断本行的睡眠蘑菇是否在这一格
|
||||
for plant in self.plant_group:
|
||||
if plant.can_sleep:
|
||||
if plant.state == c.SLEEP:
|
||||
plantMapX, _ = self.map.getMapIndex(plant.rect.centerx, plant.rect.bottom)
|
||||
print(plantMapX, self.map_x)
|
||||
if plantMapX == self.map_x:
|
||||
plant.state = c.IDLE
|
||||
plant.setIdle()
|
||||
plant.changeFrames(plant.idle_frames)
|
||||
@ -1297,3 +1303,135 @@ class TangleKlep(Plant):
|
||||
# 这里必须用elif排除尚未进入splash阶段,以免误触
|
||||
elif (self.frame_index + 1) >= self.frame_num:
|
||||
self.health = 0
|
||||
|
||||
|
||||
# 毁灭菇的处理办法:
|
||||
# 爆炸后留下的坑看作另一种形态的毁灭菇
|
||||
# 当存在这种形态的毁灭菇时不可以种植物
|
||||
# 坑形态的毁灭菇存在时不可种植物
|
||||
# 坑形态的毁灭菇同地刺一样不可以被啃食
|
||||
# 爆炸时杀死同一格的所有植物
|
||||
class DoomShroom(Plant):
|
||||
def __init__(self, x, y, plant_group, mapContent):
|
||||
Plant.__init__(self, x, y, c.DOOMSHROOM, c.PLANT_HEALTH, None)
|
||||
self.can_sleep = True
|
||||
self.mapContent = mapContent
|
||||
self.bomb_timer = 0
|
||||
# 不同场景由于格子的长不同,范围有变化
|
||||
if mapContent[c.MAP_PLOT_TYPE] == c.MAP_GRASS:
|
||||
self.explode_y_range = 2
|
||||
else:
|
||||
self.explode_y_range = 2
|
||||
self.explode_x_range = c.GRID_X_SIZE * 2.5
|
||||
self.start_boom = False
|
||||
self.plant_group = plant_group
|
||||
self.originalX = x
|
||||
self.originalY = y
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.sleep_frames = []
|
||||
self.boom_frames = []
|
||||
|
||||
idle_name = name
|
||||
sleep_name = name + 'Sleep'
|
||||
boom_name = name + 'Boom'
|
||||
|
||||
frame_list = [self.idle_frames, self.sleep_frames, self.boom_frames]
|
||||
name_list = [idle_name, sleep_name, boom_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def setBoom(self):
|
||||
self.changeFrames(self.boom_frames)
|
||||
self.start_boom = True
|
||||
|
||||
def animation(self):
|
||||
# 发生了爆炸
|
||||
if self.start_boom:
|
||||
if self.frame_index == 1:
|
||||
self.rect.x -= 80
|
||||
self.rect.y += 30
|
||||
# 播放爆炸音效
|
||||
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "doomshroom.ogg")).play()
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.health = 0
|
||||
self.frame_index = self.frame_num - 1
|
||||
self.mapContent[c.MAP_PLANT].add(c.HOLE)
|
||||
# 睡觉状态
|
||||
elif self.state == c.SLEEP:
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.frame_index = 0
|
||||
self.animate_timer = self.current_time
|
||||
# 正常状态
|
||||
else:
|
||||
self.health = c.INF
|
||||
if (self.current_time - self.animate_timer) > 100:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.setBoom()
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
# 用于描述毁灭菇的坑
|
||||
class Hole(Plant):
|
||||
def __init__(self, x, y, plotType):
|
||||
# 指定区域类型这一句必须放在前面,否则加载图片判断将会失败
|
||||
self.plotType = plotType
|
||||
Plant.__init__(self, x, y, c.HOLE, c.INF, None)
|
||||
self.timer = 0
|
||||
self.shallow = False
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.idle2_frames = []
|
||||
self.water_frames = []
|
||||
self.water2_frames = []
|
||||
self.roof_frames = []
|
||||
self.roof2_frames = []
|
||||
|
||||
idle_name = name
|
||||
idle2_name = name + 'Shallow'
|
||||
water_name = name + 'Water'
|
||||
water2_name = name + 'WaterShallow'
|
||||
roof_name = name + 'Roof'
|
||||
roof2_name = name + 'RoofShallow'
|
||||
|
||||
frame_list = [ self.idle_frames, self.idle2_frames,
|
||||
self.water_frames, self.water2_frames,
|
||||
self.roof_frames, self.roof2_frames]
|
||||
name_list = [ idle_name, idle2_name,
|
||||
water_name, water2_name,
|
||||
roof_name, roof2_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1)
|
||||
|
||||
if self.plotType == c.MAP_TILE:
|
||||
self.frames = self.roof_frames
|
||||
elif self.plotType == c.MAP_WATER:
|
||||
self.frames = self.water_frames
|
||||
else:
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def idling(self):
|
||||
if self.timer == 0:
|
||||
self.timer = self.current_time
|
||||
elif (not self.shallow) and (self.current_time - self.timer >= 90000):
|
||||
if self.plotType == c.MAP_TILE:
|
||||
self.frames = self.roof2_frames
|
||||
elif self.plotType == c.MAP_WATER:
|
||||
self.frames = self.water2_frames
|
||||
else:
|
||||
self.frames = self.idle2_frames
|
||||
self.shallow = True
|
||||
elif self.current_time - self.timer >= 180000:
|
||||
self.health = 0
|
||||
@ -123,9 +123,6 @@ MAP_GRASS = 'grass'
|
||||
MAP_WATER = 'water'
|
||||
MAP_TILE = 'tile' # 指屋顶上的瓦片
|
||||
MAP_UNAVAILABLE = 'unavailable' # 指完全不能种植物的地方,包括无草皮的荒地和坚果保龄球等红线右侧
|
||||
# 特殊的:冰车冰路(自动消除、辣椒消除)、毁灭菇坑(自动消除),由于这些只能在关卡中产生而不能初始化产生,所以只有区域类型没有初始状态
|
||||
MAP_FROZEN = 'frozen'
|
||||
MAP_HOLE = 'hole'
|
||||
# 地图单元格状态
|
||||
MAP_STATE_EMPTY = {MAP_PLANT:set(), MAP_SLEEP:False, MAP_PLOT_TYPE:MAP_GRASS} # 由于同一格显然不可能种两个相同的植物,所以用集合
|
||||
MAP_STATE_WATER = {MAP_PLANT:set(), MAP_SLEEP:False, MAP_PLOT_TYPE:MAP_WATER}
|
||||
@ -207,6 +204,9 @@ COFFEEBEAN = 'CoffeeBean'
|
||||
SEASHROOM = 'SeaShroom'
|
||||
TALLNUT = 'TallNut'
|
||||
TANGLEKLEP = 'TangleKlep'
|
||||
DOOMSHROOM = 'DoomShroom'
|
||||
ICE_FROZEN_PLOT = 'IceFrozenPlot'
|
||||
HOLE = 'Hole'
|
||||
|
||||
# 植物生命值
|
||||
PLANT_HEALTH = 300
|
||||
@ -256,6 +256,7 @@ CARD_COFFEEBEAN = 'card_coffeebean'
|
||||
CARD_SEASHROOM = 'card_seashroom'
|
||||
CARD_TALLNUT = 'card_tallnut'
|
||||
CARD_TANGLEKLEP = 'card_tangleklep'
|
||||
CARD_DOOMSHROOM = 'card_doomshroom'
|
||||
|
||||
# 子弹信息
|
||||
# 子弹类型
|
||||
@ -343,3 +344,6 @@ SLEEP = 'sleep'
|
||||
# 关卡状态
|
||||
CHOOSE = 'choose'
|
||||
PLAY = 'play'
|
||||
|
||||
# 无穷大常量
|
||||
INF = float('inf')
|
||||
@ -783,13 +783,16 @@ class Level(tool.State):
|
||||
elif self.plant_name == c.STARFRUIT:
|
||||
new_plant = plant.StarFruit(x, y, self.bullet_groups[map_y], self)
|
||||
elif self.plant_name == c.COFFEEBEAN:
|
||||
new_plant = plant.CoffeeBean(x, y, self.plant_groups[map_y], self.map.map[map_y][map_x])
|
||||
new_plant = plant.CoffeeBean(x, y, self.plant_groups[map_y], self.map.map[map_y][map_x], self.map, map_x)
|
||||
elif self.plant_name == c.SEASHROOM:
|
||||
new_plant = plant.SeaShroom(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.TALLNUT:
|
||||
new_plant = plant.TallNut(x, y)
|
||||
elif self.plant_name == c.TANGLEKLEP:
|
||||
new_plant = plant.TangleKlep(x, y)
|
||||
elif self.plant_name == c.DOOMSHROOM:
|
||||
new_plant = plant.DoomShroom(x, y, self.plant_groups[map_y], self.map.map[map_y][map_x])
|
||||
|
||||
|
||||
if new_plant.can_sleep and self.background_type in {c.BACKGROUND_DAY, c.BACKGROUND_POOL, c.BACKGROUND_ROOF, c.BACKGROUND_WALLNUTBOWLING, c.BACKGROUND_SINGLE, c.BACKGROUND_TRIPLE}:
|
||||
new_plant.setSleep()
|
||||
@ -882,9 +885,10 @@ class Level(tool.State):
|
||||
else:
|
||||
collided_func = pg.sprite.collide_circle_ratio(0.7)
|
||||
if bullet.state == c.FLY:
|
||||
zombie = pg.sprite.spritecollideany(bullet, self.zombie_groups[i], collided_func)
|
||||
if zombie and zombie.state != c.DIE:
|
||||
# 这里生效代表已经发生了碰撞
|
||||
# 利用循环而非内建精灵组碰撞判断函数,处理更加灵活,可排除已死亡僵尸
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if collided_func(zombie, bullet):
|
||||
if zombie.state != c.DIE:
|
||||
zombie.setDamage(bullet.damage, effect=bullet.effect, damageType=c.ZOMBIE_DEAFULT_DAMAGE)
|
||||
bullet.setExplode()
|
||||
# 火球有溅射伤害
|
||||
@ -892,6 +896,8 @@ class Level(tool.State):
|
||||
for rangeZombie in self.zombie_groups[i]:
|
||||
if abs(rangeZombie.rect.x - bullet.rect.x) <= (c.GRID_X_SIZE // 2):
|
||||
rangeZombie.setDamage(c.BULLET_DAMAGE_FIREBALL_RANGE, effect=False, damageType=c.ZOMBIE_DEAFULT_DAMAGE)
|
||||
break
|
||||
|
||||
|
||||
def checkZombieCollisions(self):
|
||||
if self.bar_type == c.CHOSSEBAR_BOWLING:
|
||||
@ -909,36 +915,59 @@ class Level(tool.State):
|
||||
continue
|
||||
if zombie.canSwim and (not zombie.swimming):
|
||||
continue
|
||||
plant = pg.sprite.spritecollideany(zombie, self.plant_groups[i], collided_func)
|
||||
if plant:
|
||||
if plant.name == c.WALLNUTBOWLING:
|
||||
if plant.canHit(i):
|
||||
zombie.setDamage(c.WALLNUT_BOWLING_DAMAGE, damageType=c.ZOMBIE_WALLNUT_BOWLING_DANMAGE)
|
||||
# 注意:以上语句为通用处理,以后加入了铁门僵尸需要单独设置直接冲撞就直接杀死
|
||||
# 可以给坚果保龄球设置attacked属性,如果attacked就秒杀(setDamage的攻击类型此时设置为COMMMON)铁门
|
||||
plant.changeDirection(i)
|
||||
# 播放撞击音效
|
||||
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "bowlingimpact.ogg")).play()
|
||||
elif plant.name == c.REDWALLNUTBOWLING:
|
||||
if plant.state == c.IDLE:
|
||||
plant.setAttack()
|
||||
elif plant.name == c.SPIKEWEED:
|
||||
continue
|
||||
# 在睡莲、花盆上有植物时应当优先攻击其上的植物
|
||||
elif plant.name in {c.LILYPAD, '花盆(未实现)'}:
|
||||
map_x, map_y = self.map.getMapIndex(plant.rect.centerx, plant.rect.bottom)
|
||||
|
||||
# 以下代码为了实现各个功能,极其凌乱,尚未优化性能
|
||||
attackableCommonPlants = []
|
||||
attackableBackupPlant = []
|
||||
# 利用更加精细的循环判断啃咬优先顺序
|
||||
for plant in self.plant_groups[i]:
|
||||
if collided_func(plant, zombie):
|
||||
if plant.name in {"南瓜头(未实现)"}:
|
||||
targetPlant = plant
|
||||
break
|
||||
elif plant.name in {c.LILYPAD, "花盆(未实现)"}:
|
||||
attackableBackupPlant.append(plant)
|
||||
# 注意要剔除掉两个“假植物”
|
||||
elif plant.name not in {c.HOLE, c.ICE_FROZEN_PLOT}:
|
||||
attackableCommonPlants.append(plant)
|
||||
else:
|
||||
if attackableCommonPlants:
|
||||
# 默认为列表中最后一个
|
||||
targetPlant = attackableCommonPlants[-1]
|
||||
elif attackableBackupPlant:
|
||||
targetPlant = attackableBackupPlant[-1]
|
||||
map_x, map_y = self.map.getMapIndex(targetPlant.rect.centerx, targetPlant.rect.bottom)
|
||||
if len(self.map.map[map_y][map_x][c.MAP_PLANT]) >= 2:
|
||||
# 这里暂时没有南瓜头优先攻击逻辑,这整个模块都没有对南瓜头的设计
|
||||
for actualTargetPlant in self.plant_groups[i]:
|
||||
# 检测同一格的其他植物
|
||||
if self.map.getMapIndex(actualTargetPlant.rect.centerx, actualTargetPlant.rect.bottom) == (map_x, map_y):
|
||||
if actualTargetPlant.name != plant.name:
|
||||
zombie.setAttack(actualTargetPlant)
|
||||
if actualTargetPlant.name in {"南瓜头(未实现)"}:
|
||||
targetPlant = actualTargetPlant
|
||||
break
|
||||
elif actualTargetPlant.name not in {c.LILYPAD, "花盆(未实现)"}:
|
||||
attackableCommonPlants.append(actualTargetPlant)
|
||||
else:
|
||||
zombie.setAttack(plant)
|
||||
if attackableCommonPlants:
|
||||
targetPlant = attackableCommonPlants[-1]
|
||||
else:
|
||||
zombie.setAttack(plant)
|
||||
targetPlant = None
|
||||
|
||||
if targetPlant:
|
||||
if targetPlant.name == c.WALLNUTBOWLING:
|
||||
if targetPlant.canHit(i):
|
||||
zombie.setDamage(c.WALLNUT_BOWLING_DAMAGE, damageType=c.ZOMBIE_WALLNUT_BOWLING_DANMAGE)
|
||||
# 注意:以上语句为通用处理,以后加入了铁门僵尸需要单独设置直接冲撞就直接杀死
|
||||
# 可以给坚果保龄球设置attacked属性,如果attacked就秒杀(setDamage的攻击类型此时设置为COMMMON)铁门
|
||||
targetPlant.changeDirection(i)
|
||||
# 播放撞击音效
|
||||
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "bowlingimpact.ogg")).play()
|
||||
elif targetPlant.name == c.REDWALLNUTBOWLING:
|
||||
if targetPlant.state == c.IDLE:
|
||||
targetPlant.setAttack()
|
||||
elif targetPlant.name in {c.SPIKEWEED}:
|
||||
continue
|
||||
else:
|
||||
zombie.setAttack(targetPlant)
|
||||
|
||||
for hypno_zombie in self.hypno_zombie_groups[i]:
|
||||
if hypno_zombie.health <= 0:
|
||||
@ -990,49 +1019,63 @@ class Level(tool.State):
|
||||
zombie.setFreeze(plant.trap_frames[0])
|
||||
zombie.setDamage(20, damageType=c.ZOMBIE_RANGE_DAMAGE) # 寒冰菇还有全场20的伤害
|
||||
|
||||
def killPlant(self, plant, shovel=False):
|
||||
x, y = plant.getPosition()
|
||||
def killPlant(self, targetPlant, shovel=False):
|
||||
x, y = targetPlant.getPosition()
|
||||
map_x, map_y = self.map.getMapIndex(x, y)
|
||||
if self.bar_type != c.CHOSSEBAR_BOWLING:
|
||||
try: # 避免炸弹等本身就不在集合里面的问题
|
||||
self.map.removeMapPlant(map_x, map_y, plant.name)
|
||||
except KeyError:
|
||||
pass
|
||||
# 将睡眠植物移除后更新睡眠状态
|
||||
if plant.state == c.SLEEP:
|
||||
self.map.map[map_y][map_x][c.MAP_SLEEP] = False
|
||||
|
||||
# 用铲子铲不用触发植物功能
|
||||
if not shovel:
|
||||
if plant.name in {c.CHERRYBOMB, c.REDWALLNUTBOWLING}:
|
||||
self.boomZombies(plant.rect.centerx, map_y, plant.explode_y_range,
|
||||
plant.explode_x_range)
|
||||
elif plant.name == c.JALAPENO:
|
||||
self.boomZombies(plant.rect.centerx, map_y, plant.explode_y_range,
|
||||
plant.explode_x_range, effect=c.BULLET_EFFECT_UNICE)
|
||||
elif plant.name == c.ICESHROOM and plant.state != c.SLEEP:
|
||||
if targetPlant.name in {c.CHERRYBOMB, c.REDWALLNUTBOWLING}:
|
||||
self.boomZombies(targetPlant.rect.centerx, map_y, targetPlant.explode_y_range,
|
||||
targetPlant.explode_x_range)
|
||||
elif (targetPlant.name == c.DOOMSHROOM) and (targetPlant.state != c.SLEEP):
|
||||
x, y = targetPlant.originalX, targetPlant.originalY
|
||||
map_x, map_y = self.map.getMapIndex(x, y)
|
||||
self.boomZombies(targetPlant.rect.centerx, map_y, targetPlant.explode_y_range,
|
||||
targetPlant.explode_x_range)
|
||||
for i in self.plant_groups[map_y]:
|
||||
checkMapX, _ = self.map.getMapIndex(i.rect.centerx, i.rect.bottom)
|
||||
if map_x == checkMapX:
|
||||
i.health = 0
|
||||
self.plant_groups[map_y].add(plant.Hole(x, y, self.map.map[map_y][map_x][c.MAP_PLOT_TYPE]))
|
||||
self.map.map[map_y][map_x][c.MAP_PLANT].add(c.HOLE)
|
||||
elif targetPlant.name == c.JALAPENO:
|
||||
self.boomZombies(targetPlant.rect.centerx, map_y, targetPlant.explode_y_range,
|
||||
targetPlant.explode_x_range, effect=c.BULLET_EFFECT_UNICE)
|
||||
elif targetPlant.name == c.ICESHROOM and targetPlant.state != c.SLEEP:
|
||||
self.freezeZombies(plant)
|
||||
elif plant.name == c.HYPNOSHROOM and plant.state != c.SLEEP:
|
||||
zombie = plant.kill_zombie
|
||||
elif targetPlant.name == c.HYPNOSHROOM and targetPlant.state != c.SLEEP:
|
||||
zombie = targetPlant.kill_zombie
|
||||
zombie.setHypno()
|
||||
_, map_y = self.map.getMapIndex(zombie.rect.centerx, zombie.rect.bottom)
|
||||
self.zombie_groups[map_y].remove(zombie)
|
||||
self.hypno_zombie_groups[map_y].add(zombie)
|
||||
elif (plant.name == c.POTATOMINE and not plant.is_init): # 土豆雷不是灰烬植物,不能用Boom
|
||||
elif (targetPlant.name == c.POTATOMINE and not targetPlant.is_init): # 土豆雷不是灰烬植物,不能用Boom
|
||||
for zombie in self.zombie_groups[map_y]:
|
||||
# 双判断:发生碰撞或在攻击范围内
|
||||
if ((pg.sprite.collide_circle_ratio(0.6)(zombie, plant)) or
|
||||
(abs(zombie.rect.centerx - x) <= plant.explode_x_range)):
|
||||
if ((pg.sprite.collide_circle_ratio(0.6)(zombie, targetPlant)) or
|
||||
(abs(zombie.rect.centerx - x) <= targetPlant.explode_x_range)):
|
||||
zombie.setDamage(1800, damageType=c.ZOMBIE_RANGE_DAMAGE)
|
||||
elif plant.name not in {c.WALLNUTBOWLING, c.TANGLEKLEP}:
|
||||
elif targetPlant.name not in {c.WALLNUTBOWLING, c.TANGLEKLEP}:
|
||||
# 触发植物死亡音效
|
||||
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "plantDie.ogg")).play()
|
||||
else:
|
||||
# 用铲子移除植物时播放音效
|
||||
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "plant.ogg")).play()
|
||||
|
||||
# 整理地图信息
|
||||
if self.bar_type != c.CHOSSEBAR_BOWLING:
|
||||
try: # 避免炸弹等本身就不在集合里面的问题
|
||||
self.map.removeMapPlant(map_x, map_y, targetPlant.name)
|
||||
except KeyError:
|
||||
pass
|
||||
# 将睡眠植物移除后更新睡眠状态
|
||||
if targetPlant.state == c.SLEEP:
|
||||
self.map.map[map_y][map_x][c.MAP_SLEEP] = False
|
||||
|
||||
# 避免僵尸在用铲子移除植物后还在原位啃食
|
||||
plant.health = 0
|
||||
plant.kill()
|
||||
targetPlant.health = 0
|
||||
targetPlant.kill()
|
||||
|
||||
def checkPlant(self, plant, i):
|
||||
zombie_len = len(self.zombie_groups[i])
|
||||
|
||||
@ -168,7 +168,7 @@ class Menu(tool.State):
|
||||
self.adventure_frame_index = 0
|
||||
self.adventure_timer = self.current_time
|
||||
self.adventure_image = self.adventure_frames[self.adventure_frame_index]
|
||||
if(self.current_time - self.adventure_start) > 1300:
|
||||
if(self.current_time - self.adventure_start) > 3200:
|
||||
self.done = True
|
||||
|
||||
|
||||
|
||||