pypvz/source/component/zombie.py
2022-05-14 13:47:01 +08:00

1015 lines
41 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pygame as pg
import os
from random import randint
from .. import tool
from .. import constants as c
class Zombie(pg.sprite.Sprite):
def __init__(self, x, y, name, head_group=None, helmetHealth=0, helmetType2Health=0, bodyHealth=c.NORMAL_HEALTH, lostHeadHealth=c.LOSTHEAD_HEALTH, damage=c.ZOMBIE_ATTACK_DAMAGE, canSwim=False):
pg.sprite.Sprite.__init__(self)
self.name = name
self.frames = []
self.frame_index = 0
self.loadImages()
self.frame_num = len(self.frames)
self.image = self.frames[self.frame_index]
self.mask = pg.mask.from_surface(self.image)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.helmetHealth = helmetHealth
self.helmetType2Health = helmetType2Health
self.health = bodyHealth + lostHeadHealth
self.lostHeadHealth = lostHeadHealth
self.damage = damage
self.dead = False
self.lostHead = False
self.canSwim = canSwim
self.swimming = False
self.helmet = (self.helmetHealth > 0)
self.helmetType2 = (self.helmetType2Health > 0)
self.head_group = head_group
self.walk_timer = 0
self.animate_timer = 0
self.attack_timer = 0
self.state = c.WALK
self.animate_interval = 150
self.walk_animate_interval = 180
self.attack_animate_interval = 100
self.lostHead_animate_interval = 180
self.die_animate_interval = 50
self.boomDie_animate_interval = 100
self.ice_slow_ratio = 1
self.ice_slow_timer = 0
self.hit_timer = 0
self.speed = 1
self.freeze_timer = 0
self.losthead_timer = 0
self.is_hypno = False # the zombie is hypo and attack other zombies when it ate a HypnoShroom
def loadFrames(self, frames, name, colorkey=c.BLACK):
frame_list = tool.GFX[name]
rect = frame_list[0].get_rect()
width, height = rect.w, rect.h
if name in tool.ZOMBIE_RECT:
data = tool.ZOMBIE_RECT[name]
x, width = data['x'], data['width']
else:
x = 0
for frame in frame_list:
frames.append(tool.get_image(frame, x, 0, width, height, colorkey))
def update(self, game_info):
self.current_time = game_info[c.CURRENT_TIME]
self.handleState()
self.updateIceSlow()
self.animation()
def handleState(self):
if self.state == c.WALK:
self.walking()
elif self.state == c.ATTACK:
self.attacking()
elif self.state == c.DIE:
self.dying()
elif self.state == c.FREEZE:
self.freezing()
# 濒死状态用函数
def checkToDie(self, framesKind):
if self.health <= 0:
self.setDie()
return True
elif self.health <= self.lostHeadHealth:
if not self.lostHead:
self.changeFrames(framesKind)
self.setLostHead()
return True
else:
self.health -= (self.current_time - self.losthead_timer) / 40
self.losthead_timer = self.current_time
return False
else:
return False
def walking(self):
if self.checkToDie(self.losthead_walk_frames):
return
# 能游泳的僵尸
if self.canSwim:
# 在水池范围内
# 在右侧岸左
if self.rect.right <= c.MAP_POOL_FRONT_X:
# 在左侧岸右,左侧岸位置为预估
if self.rect.right - 25 >= c.MAP_POOL_OFFSET_X:
# 还未进入游泳状态
if not self.swimming:
self.swimming = True
self.changeFrames(self.swim_frames)
# 播放入水音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "zombieEnteringWater.ogg")).play()
# 同样没有兼容双防具
if self.helmet:
if self.helmetHealth <= 0:
self.helmet = False
else:
self.changeFrames(self.helmet_swim_frames)
if self.helmetType2:
if self.helmetType2Health <= 0:
self.helmetType2 = False
else:
self.changeFrames(self.helmet_swim_frames)
# 已经进入游泳状态
else:
if self.helmet:
if self.helmetHealth <= 0:
self.changeFrames(self.swim_frames)
self.helmet = False
if self.helmetType2:
if self.helmetType2Health <= 0:
self.changeFrames(self.swim_frames)
self.helmetType2 = False
# 水生僵尸已经接近家门口并且上岸
else:
if self.swimming:
self.changeFrames(self.walk_frames)
self.swimming = False
# 同样没有兼容双防具
if self.helmet:
if self.helmetHealth <= 0:
self.helmet = False
else:
self.changeFrames(self.helmet_walk_frames)
if self.helmetType2:
if self.helmetType2Health <= 0:
self.helmetType2 = False
else:
self.changeFrames(self.helmet_walk_frames)
if self.helmet:
if self.helmetHealth <= 0:
self.helmet = False
self.changeFrames(self.walk_frames)
if self.helmetType2:
if self.helmetType2Health <= 0:
self.helmetType2 = False
self.changeFrames(self.walk_frames)
elif self.is_hypno and self.rect.right > c.MAP_POOL_FRONT_X + 55: # 常数拟合暂时缺乏检验
if self.swimming:
self.changeFrames(self.walk_frames)
if self.helmet:
if self.helmetHealth <= 0:
self.changeFrames(self.walk_frames)
self.helmet = False
elif self.swimming: # 游泳状态需要改为步行
self.changeFrames(self.helmet_walk_frames)
if self.helmetType2:
if self.helmetType2Health <= 0:
self.changeFrames(self.walk_frames)
self.helmetType2 = False
elif self.swimming: # 游泳状态需要改为步行
self.changeFrames(self.helmet_walk_frames)
self.swimming = False
# 尚未进入水池
else:
if self.helmetHealth <= 0 and self.helmet:
self.changeFrames(self.walk_frames)
self.helmet = False
if self.helmetType2Health <= 0 and self.helmetType2:
self.changeFrames(self.walk_frames)
self.helmetType2 = False
# 不能游泳的一般僵尸
else:
if self.helmetHealth <= 0 and self.helmet:
self.changeFrames(self.walk_frames)
self.helmet = False
if self.helmetType2Health <= 0 and self.helmetType2:
self.changeFrames(self.walk_frames)
self.helmetType2 = False
if self.name == c.NEWSPAPER_ZOMBIE:
self.speed = 2.5
# 触发报纸僵尸暴走音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "newspaperZombieAngry.ogg")).play()
if (self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio()):
self.walk_timer = self.current_time
if self.is_hypno:
self.rect.x += 1
else:
self.rect.x -= 1
def attacking(self):
if self.checkToDie(self.losthead_attack_frames):
return
if self.helmetHealth <= 0 and self.helmet:
self.changeFrames(self.attack_frames)
self.helmet = False
if self.helmetType2Health <= 0 and self.helmetType2:
self.changeFrames(self.attack_frames)
self.helmetType2 = False
if self.name == c.NEWSPAPER_ZOMBIE:
self.speed = 2.5
if ((self.current_time - self.attack_timer) > (c.ATTACK_INTERVAL * self.getAttackTimeRatio())) and (not self.lostHead):
if self.prey.health > 0:
if self.prey_is_plant:
self.prey.setDamage(self.damage, self)
else:
self.prey.setDamage(self.damage)
# 播放啃咬音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "zombieAttack.ogg")).play()
self.attack_timer = self.current_time
if self.prey.health <= 0:
self.prey = None
self.setWalk()
def dying(self):
pass
def freezing(self):
if self.old_state == c.WALK:
if self.checkToDie(self.losthead_walk_frames):
return
else:
if self.checkToDie(self.losthead_attack_frames):
return
if (self.current_time - self.freeze_timer) >= c.MIN_FREEZE_TIME + randint(0, 2000):
self.setWalk()
# 注意寒冰菇解冻后还有减速
self.ice_slow_timer = self.freeze_timer + 10000 # 每次冰冻冻结 + 减速时间为20 s而减速有10 s计时故这里+10 s
self.ice_slow_ratio = 2
def setLostHead(self):
self.losthead_timer = self.current_time
self.lostHead = True
self.animate_interval = self.lostHead_animate_interval
if self.head_group is not None:
self.head_group.add(ZombieHead(self.rect.centerx, self.rect.bottom))
def changeFrames(self, frames):
'''change image frames and modify rect position'''
self.frames = frames
self.frame_num = len(self.frames)
self.frame_index = 0
bottom = self.rect.bottom
centerx = self.rect.centerx
self.image = self.frames[self.frame_index]
self.mask = pg.mask.from_surface(self.image)
self.rect = self.image.get_rect()
self.rect.bottom = bottom
self.rect.centerx = centerx
def animation(self):
if self.state == c.FREEZE:
self.image.set_alpha(192)
return
if (self.current_time - self.animate_timer) > (self.animate_interval * self.getTimeRatio()):
self.frame_index += 1
if self.frame_index >= self.frame_num:
if self.state == c.DIE:
self.kill()
return
self.frame_index = 0
self.animate_timer = self.current_time
self.image = self.frames[self.frame_index]
if self.is_hypno:
self.image = pg.transform.flip(self.image, True, False)
self.mask = pg.mask.from_surface(self.image)
if (self.current_time - self.hit_timer) >= 200:
self.image.set_alpha(255)
else:
self.image.set_alpha(192)
def getTimeRatio(self):
return (self.ice_slow_ratio / self.speed) # 目前的机制为:冰冻减速状态与自身速度共同决定行走的时间间隔
def getAttackTimeRatio(self):
return self.ice_slow_ratio # 攻击速度只取决于冰冻状态
def setIceSlow(self):
# 在转入冰冻减速状态时播放冰冻音效
if self.ice_slow_ratio == 1:
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "freeze.ogg")).play()
# when get a ice bullet damage, slow the attack or walk speed of the zombie
self.ice_slow_timer = self.current_time
self.ice_slow_ratio = 2
def updateIceSlow(self):
if self.ice_slow_ratio > 1:
if (self.current_time - self.ice_slow_timer) > c.ICE_SLOW_TIME:
self.ice_slow_ratio = 1
def setDamage(self, damage, effect=None, damageType=c.ZOMBIE_COMMON_DAMAGE):
# 冰冻减速效果
if effect == c.BULLET_EFFECT_ICE:
if damageType == c.ZOMBIE_DEAFULT_DAMAGE: # 寒冰射手不能穿透二类防具进行减速
if not self.helmetType2:
self.setIceSlow()
else:
self.setIceSlow()
# 解冻
elif effect == c.BULLET_EFFECT_UNICE:
if damageType == c.ZOMBIE_DEAFULT_DAMAGE: # 寒冰射手不能穿透二类防具进行减速
if not self.helmetType2:
self.ice_slow_ratio = 1
else:
self.ice_slow_ratio = 1
if damageType == c.ZOMBIE_DEAFULT_DAMAGE: # 不穿透二类防具的攻击
# 从第二类防具开始逐级传递
if self.helmetType2:
self.helmetType2Health -= damage
if self.helmetType2Health <= 0:
if self.helmet:
self.helmetHealth += self.helmetType2Health # 注意self.helmetType2Health已经带有正负
self.helmetType2Health = 0 # 注意合并后清零
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else:
self.health += self.helmetType2Health
self.helmetType2Health = 0
elif self.helmet: # 不存在二类防具,但是存在一类防具
self.helmetHealth -= damage
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else: # 没有防具
self.health -= damage
elif damageType == c.ZOMBIE_COMMON_DAMAGE: # 无视二类防具,将攻击一类防具与本体视为整体的攻击
if self.helmet: # 存在一类防具
self.helmetHealth -= damage
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else: # 没有一类防具
self.health -= damage
elif damageType == c.ZOMBIE_RANGE_DAMAGE:
# 从第二类防具开始逐级传递
if self.helmetType2:
self.helmetType2Health -= damage
if self.helmetType2Health <= 0:
if self.helmet:
self.helmetHealth -= damage # 注意范围伤害中这里还有一个攻击
self.helmetHealth += self.helmetType2Health # 注意self.helmetType2Health已经带有正负
self.helmetType2Health = 0 # 注意合并后清零
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else:
self.health -= damage # 注意范围伤害中这里还有一个攻击
self.health += self.helmetType2Health
self.helmetType2Health = 0
else:
if self.helmet:
self.helmetHealth -= damage
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else:
self.health -= damage
elif self.helmet: # 不存在二类防具,但是存在一类防具
self.helmetHealth -= damage
if self.helmetHealth <= 0:
self.health += self.helmetHealth
self.helmetHealth = 0 # 注意合并后清零
else: # 没有防具
self.health -= damage
elif damageType == c.ZOMBIE_ASH_DAMAGE:
self.health -= damage # 无视任何防具
elif damageType == c.ZOMBIE_WALLNUT_BOWLING_DANMAGE:
# 逻辑:对防具的多余伤害不传递
# 以后增设铁门后可能需要设置侧面冲撞特殊性
if self.helmetType2:
self.helmetType2Health -= damage
elif self.helmet: # 不存在二类防具,但是存在一类防具
self.helmetHealth -= damage
else: # 没有防具
self.health -= damage
else:
print('警告:植物攻击类型错误,现在默认进行类豌豆射手型攻击')
setDamage(damage, effect=effect, damageType=c.ZOMBIE_DEAFULT_DAMAGE)
# 记录攻击时间
self.hit_timer = self.current_time
def setWalk(self):
self.state = c.WALK
self.animate_interval = self.walk_animate_interval
if self.helmet or self.helmetType2: # 这里暂时没有考虑同时有两种防具的僵尸
self.changeFrames(self.helmet_walk_frames)
elif self.lostHead:
self.changeFrames(self.losthead_walk_frames)
else:
self.changeFrames(self.walk_frames)
if self.canSwim:
if self.rect.right <= c.MAP_POOL_FRONT_X:
self.swimming = True
self.changeFrames(self.swim_frames)
# 同样没有兼容双防具
if self.helmet:
if self.helmetHealth <= 0:
self.changeFrames(self.swim_frames)
self.helmet = False
else:
self.changeFrames(self.helmet_swim_frames)
if self.helmetType2:
if self.helmetType2Health <= 0:
self.changeFrames(self.swim_frames)
self.helmetType2 = False
else:
self.changeFrames(self.helmet_swim_frames)
def setAttack(self, prey, is_plant=True):
self.prey = prey # prey can be plant or other zombies
self.prey_is_plant = is_plant
self.state = c.ATTACK
self.attack_timer = self.current_time
self.animate_interval = self.attack_animate_interval
if self.helmet or self.helmetType2: # 这里暂时没有考虑同时有两种防具的僵尸
self.changeFrames(self.helmet_attack_frames)
elif self.lostHead:
self.changeFrames(self.losthead_attack_frames)
else:
self.changeFrames(self.attack_frames)
def setDie(self):
self.state = c.DIE
self.animate_interval = self.die_animate_interval
self.changeFrames(self.die_frames)
def setBoomDie(self):
self.health = 0
self.state = c.DIE
self.animate_interval = self.boomDie_animate_interval
self.changeFrames(self.boomdie_frames)
def setFreeze(self, ice_trap_image):
self.old_state = self.state
self.state = c.FREEZE
self.freeze_timer = self.current_time
self.ice_trap_image = ice_trap_image
self.ice_trap_rect = ice_trap_image.get_rect()
self.ice_trap_rect.centerx = self.rect.centerx
self.ice_trap_rect.bottom = self.rect.bottom
def drawFreezeTrap(self, surface):
if self.state == c.FREEZE:
surface.blit(self.ice_trap_image, self.ice_trap_rect)
def setHypno(self):
self.is_hypno = True
self.setWalk()
# 播放魅惑音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "hypnoed.ogg")).play()
class ZombieHead(Zombie):
def __init__(self, x, y):
Zombie.__init__(self, x, y, c.ZOMBIE_HEAD, 0)
self.state = c.DIE
def loadImages(self):
self.die_frames = []
die_name = self.name
self.loadFrames(self.die_frames, die_name)
self.frames = self.die_frames
def setWalk(self):
self.animate_interval = 100
class NormalZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.NORMAL_ZOMBIE, head_group)
def loadImages(self):
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
walk_name = self.name
attack_name = self.name + 'Attack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHeadAttack'
die_name = self.name + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.walk_frames
# 路障僵尸
class ConeHeadZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, head_group, helmetHealth=c.CONEHEAD_HEALTH)
def loadImages(self):
self.helmet_walk_frames = []
self.helmet_attack_frames = []
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_attack_name = self.name + 'Attack'
walk_name = c.NORMAL_ZOMBIE
attack_name = c.NORMAL_ZOMBIE + 'Attack'
losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'
losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'
die_name = c.NORMAL_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_attack_name,
walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class BucketHeadZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.BUCKETHEAD_ZOMBIE, head_group, helmetHealth=c.BUCKETHEAD_HEALTH)
def loadImages(self):
self.helmet_walk_frames = []
self.helmet_attack_frames = []
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_attack_name = self.name + 'Attack'
walk_name = c.NORMAL_ZOMBIE
attack_name = c.NORMAL_ZOMBIE + 'Attack'
losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'
losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'
die_name = c.NORMAL_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_attack_name,
walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class FlagZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.FLAG_ZOMBIE, head_group)
self.speed = 1.25
def loadImages(self):
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
walk_name = self.name
attack_name = self.name + 'Attack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHeadAttack'
die_name = c.NORMAL_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.walk_frames
class NewspaperZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.NEWSPAPER_ZOMBIE, head_group, helmetType2Health=c.NEWSPAPER_HEALTH)
def loadImages(self):
self.helmet_walk_frames = []
self.helmet_attack_frames = []
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_attack_name = self.name + 'Attack'
walk_name = self.name + 'NoPaper'
attack_name = self.name + 'NoPaperAttack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHeadAttack'
die_name = self.name + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_attack_name,
walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
if name == c.BOOMDIE:
color = c.BLACK
else:
color = c.WHITE
self.loadFrames(frame_list[i], name, color)
self.frames = self.helmet_walk_frames
class FootballZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.FOOTBALL_ZOMBIE, head_group, helmetHealth=c.FOOTBALL_HELMET_HEALTH)
self.speed = 1.88
self.animate_interval = 50
self.walk_animate_interval = 50
self.attack_animate_interval = 60
self.lostHead_animate_interval = 180
self.die_animate_interval = 150
def loadImages(self):
self.helmet_walk_frames = []
self.helmet_attack_frames = []
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_attack_name = self.name + 'Attack'
walk_name = self.name + 'LostHelmet'
attack_name = self.name + 'LostHelmetAttack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHeadAttack'
die_name = self.name + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_attack_name,
walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class DuckyTubeZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.DUCKY_TUBE_ZOMBIE, head_group, canSwim=True)
def loadImages(self):
self.walk_frames = []
self.swim_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
walk_name = self.name
swim_name = self.name + 'Swim'
attack_name = self.name + 'Attack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHead'
die_name = self.name + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.walk_frames, self.swim_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [walk_name, swim_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.walk_frames
class ConeHeadDuckyTubeZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.CONEHEAD_DUCKY_TUBE_ZOMBIE, head_group, helmetHealth=c.CONEHEAD_HEALTH ,canSwim=True)
def loadImages(self):
self.helmet_walk_frames = []
self.walk_frames = []
self.helmet_swim_frames = []
self.swim_frames = []
self.helmet_attack_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_swim_name = self.name + 'Swim'
helmet_attack_name = self.name + 'Attack'
walk_name = c.DUCKY_TUBE_ZOMBIE
swim_name = c.DUCKY_TUBE_ZOMBIE + 'Swim'
attack_name = c.DUCKY_TUBE_ZOMBIE + 'Attack'
losthead_walk_name = c.DUCKY_TUBE_ZOMBIE + 'LostHead'
losthead_attack_name = c.DUCKY_TUBE_ZOMBIE + 'LostHead'
die_name = c.DUCKY_TUBE_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_swim_frames, self.helmet_attack_frames, self.walk_frames, self.swim_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_swim_name, helmet_attack_name, walk_name, swim_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class BucketHeadDuckyTubeZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.BUCKETHEAD_DUCKY_TUBE_ZOMBIE, head_group, helmetHealth=c.BUCKETHEAD_HEALTH ,canSwim=True)
def loadImages(self):
self.helmet_walk_frames = []
self.walk_frames = []
self.helmet_swim_frames = []
self.swim_frames = []
self.helmet_attack_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_swim_name = self.name + 'Swim'
helmet_attack_name = self.name + 'Attack'
walk_name = c.DUCKY_TUBE_ZOMBIE
swim_name = c.DUCKY_TUBE_ZOMBIE + 'Swim'
attack_name = c.DUCKY_TUBE_ZOMBIE + 'Attack'
losthead_walk_name = c.DUCKY_TUBE_ZOMBIE + 'LostHead'
losthead_attack_name = c.DUCKY_TUBE_ZOMBIE + 'LostHead'
die_name = c.DUCKY_TUBE_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_swim_frames, self.helmet_attack_frames, self.walk_frames, self.swim_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_swim_name, helmet_attack_name, walk_name, swim_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class ScreenDoorZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.SCREEN_DOOR_ZOMBIE, head_group, helmetType2Health=c.SCREEN_DOOR_HEALTH)
def loadImages(self):
self.helmet_walk_frames = []
self.helmet_attack_frames = []
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
helmet_walk_name = self.name
helmet_attack_name = self.name + 'Attack'
walk_name = c.NORMAL_ZOMBIE
attack_name = c.NORMAL_ZOMBIE + 'Attack'
losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'
losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'
die_name = c.NORMAL_ZOMBIE + 'Die'
boomdie_name = c.BOOMDIE
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
name_list = [helmet_walk_name, helmet_attack_name,
walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.helmet_walk_frames
class PoleVaultingZombie(Zombie):
def __init__(self, x, y, head_group):
Zombie.__init__(self, x, y, c.POLE_VAULTING_ZOMBIE, head_group=head_group, bodyHealth=c.POLE_VAULTING_HEALTH, lostHeadHealth=c.POLE_VAULTING_LOSTHEAD_HEALTH)
self.speed = 1.88
self.jumped = False
self.jumping = False
def loadImages(self):
self.walk_frames = []
self.attack_frames = []
self.losthead_walk_frames = []
self.losthead_attack_frames = []
self.die_frames = []
self.boomdie_frames = []
self.walk_before_jump_frames = []
self.jump_frames = []
walk_name = self.name + 'WalkAfterJump'
attack_name = self.name + 'Attack'
losthead_walk_name = self.name + 'LostHead'
losthead_attack_name = self.name + 'LostHeadAttack'
die_name = self.name + 'Die'
boomdie_name = c.BOOMDIE
walk_before_jump_name = self.name
jump_name = self.name + 'Jump'
frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
self.losthead_attack_frames, self.die_frames, self.boomdie_frames,
self.walk_before_jump_frames, self.jump_frames]
name_list = [walk_name, attack_name, losthead_walk_name,
losthead_attack_name, die_name, boomdie_name,
walk_before_jump_name, jump_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.walk_before_jump_frames
def setJump(self, successfullyJumped, jumpX):
if not self.jumping:
self.jumping = True
self.changeFrames(self.jump_frames)
self.successfullyJumped = successfullyJumped
self.jumpX = jumpX
# 播放跳跃音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "polevaultjump.ogg")).play()
def animation(self):
if self.state == c.FREEZE:
self.image.set_alpha(192)
return
if (self.current_time - self.animate_timer) > (self.animate_interval * self.getTimeRatio()):
self.frame_index += 1
if self.state == c.WALK:
if self.jumping and (not self.jumped):
if self.successfullyJumped:
self.rect.x -= 5
else:
self.rect.x -= 1
if self.frame_index >= self.frame_num:
if self.state == c.DIE:
self.kill()
return
self.frame_index = 0
if self.jumping and (not self.jumped):
self.changeFrames(self.walk_frames)
if self.successfullyJumped:
self.rect.centerx = self.jumpX
self.jumped = True
self.speed = 1.04
self.animate_timer = self.current_time
self.image = self.frames[self.frame_index]
if self.is_hypno:
self.image = pg.transform.flip(self.image, True, False)
self.mask = pg.mask.from_surface(self.image)
if (self.current_time - self.hit_timer) >= 200:
self.image.set_alpha(255)
else:
self.image.set_alpha(192)
# 注意:冰车僵尸移动变速
class Zomboni(Zombie):
def __init__(self, x, y, plant_group, map, IceFrozenPlot):
Zombie.__init__(self, x, y, c.ZOMBONI, bodyHealth=c.ZOMBONI_HEALTH)
self.plant_group = plant_group
self.map = map
self.IceFrozenPlot = IceFrozenPlot
self.die_animate_interval = 100
self.boomDie_animate_interval = 150
# 播放冰车生成音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "zomboni.ogg")).play()
def loadImages(self):
self.walk_frames = []
self.walk_damaged1_frames = []
self.walk_damaged2_frames = []
self.losthead_walk_frames = []
self.die_frames = []
self.boomdie_frames = []
walk_name = self.name
walk_damaged1_name = self.name + 'Damaged1'
walk_damaged2_name = self.name + 'Damaged2'
losthead_walk_name = self.name + 'Damaged2'
die_name = self.name + 'Die'
boomdie_name = self.name + 'BoomDie'
frame_list = [ self.walk_frames, self.walk_damaged1_frames,
self.walk_damaged2_frames, self.losthead_walk_frames,
self.die_frames, self.boomdie_frames]
name_list = [ walk_name, walk_damaged1_name,
walk_damaged2_name, losthead_walk_name,
die_name, boomdie_name]
for i, name in enumerate(name_list):
self.loadFrames(frame_list[i], name)
self.frames = self.walk_frames
def updateIceSlow(self):
# 冰车僵尸不可冰冻
self.ice_slow_ratio = 1
def freezing(self):
# 冰车僵尸不可冰冻
pass
def walking(self):
if self.checkToDie(self.losthead_walk_frames):
return
if self.health <= c.ZOMBONI_DAMAGED2_HEALTH:
self.changeFrames(self.walk_damaged2_frames)
elif self.health <= c.ZOMBONI_DAMAGED1_HEALTH:
self.changeFrames(self.walk_damaged1_frames)
if (self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio()):
self.walk_timer = self.current_time
if self.is_hypno:
self.rect.x += 1
else:
self.rect.x -= 1
# 行进时碾压
for plant in self.plant_group:
# 地刺和地刺王不用检验
if ((plant.name not in {c.SPIKEWEED})
and (self.rect.centerx <= plant.rect.right <= self.rect.right)):
# 扣除生命值为可能的最大有限生命值
plant.setDamage(8000, self)
# 造冰
mapX, mapY = self.map.getMapIndex(self.rect.right - 20, self.rect.bottom)
if 0 <= mapX < c.GRID_X_LEN:
if c.ICE_FROZEN_PLOT not in self.map.map[mapY][mapX]:
x, y = self.map.getMapGridPos(mapX, mapY)
self.plant_group.add(self.IceFrozenPlot(x, y))
self.map.map[mapY][mapX][c.MAP_PLANT].add(c.ICE_FROZEN_PLOT)
self.speed = max(0.6, 1.5 - (c.GRID_X_LEN - mapX)*0.225)