Merge branch 'master' into opengl
This commit is contained in:
commit
c2992ebbbf
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,4 +7,4 @@ release/
|
||||
__pycache__/
|
||||
*/__pycache__/
|
||||
# 忽略测试文件
|
||||
test.py
|
||||
test*.py
|
||||
|
||||
@ -33,9 +33,10 @@
|
||||
* 支持自定义游戏速度倍率
|
||||
* 保存在游戏存档文件中,可以通过修改`game rate`值更改速度倍率
|
||||
* 游戏完成成就显示
|
||||
* 冒险模式全部完成显示银向日葵奖杯
|
||||
* 任意一游戏模式全部完成显示银向日葵奖杯
|
||||
* 所有模式全部完成显示金向日葵奖杯
|
||||
* 光标移动到向日葵奖杯上是显示当前各个模式通关次数
|
||||
* 含有游戏帮助界面 QwQ
|
||||
|
||||
## 环境要求
|
||||
|
||||
@ -312,6 +313,8 @@ pyinstaller -F pypvz.py `
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 关于日志与反馈
|
||||
|
||||
|
||||
BIN
demo/demo22.webp
Normal file
BIN
demo/demo22.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
BIN
demo/demo23.webp
Normal file
BIN
demo/demo23.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
1
pypvz.py
1
pypvz.py
@ -32,6 +32,7 @@ if __name__=="__main__":
|
||||
c.GAME_LOSE: screen.GameLoseScreen(),
|
||||
c.LEVEL: level.Level(),
|
||||
c.AWARD_SCREEN: screen.AwardScreen(),
|
||||
c.HELP_SCREEN: screen.HelpScreen(),
|
||||
}
|
||||
game.setup_states(state_dict, c.MAIN_MENU)
|
||||
game.run()
|
||||
|
||||
BIN
resources/graphics/Screen/HelpScreen.png
Normal file
BIN
resources/graphics/Screen/HelpScreen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@ -9,27 +9,27 @@ class Map():
|
||||
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
|
||||
self.width = c.GRID_POOL_X_LEN
|
||||
self.height = c.GRID_POOL_Y_LEN
|
||||
self.gridHeightSize = c.GRID_POOL_Y_SIZE
|
||||
self.grid_height_size = c.GRID_POOL_Y_SIZE
|
||||
self.map = [[(self.initMapGrid(c.MAP_GRASS), self.initMapGrid(c.MAP_WATER))[y in {2, 3}] for x in range(self.width)] for y in range(self.height)]
|
||||
elif self.background_type in c.ON_ROOF_BACKGROUNDS:
|
||||
self.width = c.GRID_ROOF_X_LEN
|
||||
self.height = c.GRID_ROOF_Y_LEN
|
||||
self.gridHeightSize = c.GRID_ROOF_Y_SIZE
|
||||
self.grid_height_size = c.GRID_ROOF_Y_SIZE
|
||||
self.map = [[self.initMapGrid(c.MAP_TILE) for x in range(self.width)] for y in range(self.height)]
|
||||
elif self.background_type == c.BACKGROUND_SINGLE:
|
||||
self.width = c.GRID_X_LEN
|
||||
self.height = c.GRID_Y_LEN
|
||||
self.gridHeightSize = c.GRID_Y_SIZE
|
||||
self.grid_height_size = c.GRID_Y_SIZE
|
||||
self.map = [[(self.initMapGrid(c.MAP_UNAVAILABLE), self.initMapGrid(c.MAP_GRASS))[y == 2] for x in range(self.width)] for y in range(self.height)]
|
||||
elif self.background_type == c.BACKGROUND_TRIPLE:
|
||||
self.width = c.GRID_X_LEN
|
||||
self.height = c.GRID_Y_LEN
|
||||
self.gridHeightSize = c.GRID_Y_SIZE
|
||||
self.grid_height_size = c.GRID_Y_SIZE
|
||||
self.map = [[(self.initMapGrid(c.MAP_UNAVAILABLE), self.initMapGrid(c.MAP_GRASS))[y in {1, 2, 3}] for x in range(self.width)] for y in range(self.height)]
|
||||
else:
|
||||
self.width = c.GRID_X_LEN
|
||||
self.height = c.GRID_Y_LEN
|
||||
self.gridHeightSize = c.GRID_Y_SIZE
|
||||
self.grid_height_size = c.GRID_Y_SIZE
|
||||
self.map = [[self.initMapGrid(c.MAP_GRASS) for x in range(self.width)] for y in range(self.height)]
|
||||
|
||||
def isValid(self, map_x, map_y):
|
||||
@ -47,14 +47,14 @@ class Map():
|
||||
# 判断位置是否可用
|
||||
# 暂时没有写紫卡植物的判断方法
|
||||
# 由于紫卡植物需要移除以前的植物,所以可用另外定义一个函数
|
||||
def isAvailable(self, map_x, map_y, plantName):
|
||||
def isAvailable(self, map_x, map_y, plant_name):
|
||||
# 咖啡豆和墓碑吞噬者的判别最为特殊
|
||||
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]):
|
||||
if plant_name == c.COFFEEBEAN:
|
||||
if self.map[map_y][map_x][c.MAP_SLEEP] and (plant_name not in self.map[map_y][map_x][c.MAP_PLANT]):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
if plantName == c.GRAVEBUSTER:
|
||||
if plant_name == c.GRAVEBUSTER:
|
||||
if (c.GRAVE in self.map[map_y][map_x][c.MAP_PLANT]):
|
||||
return True
|
||||
else:
|
||||
@ -64,13 +64,13 @@ class Map():
|
||||
return False
|
||||
if self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_GRASS: # 草地
|
||||
# 首先需要判断植物是否是水生植物,水生植物不能种植在陆地上
|
||||
if plantName not in c.WATER_PLANTS:
|
||||
if plant_name not in c.WATER_PLANTS:
|
||||
if not self.map[map_y][map_x][c.MAP_PLANT]: # 没有植物肯定可以种植
|
||||
return True
|
||||
elif (all((i in {"花盆(未实现)", c.PUMPKINHEAD}) for i in self.map[map_y][map_x][c.MAP_PLANT])
|
||||
and (plantName not in self.map[map_y][map_x][c.MAP_PLANT])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植
|
||||
and (plant_name not in self.map[map_y][map_x][c.MAP_PLANT])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植
|
||||
return True
|
||||
elif (plantName == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 没有南瓜头就能种南瓜头
|
||||
elif (plant_name == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 没有南瓜头就能种南瓜头
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@ -78,26 +78,26 @@ class Map():
|
||||
return False
|
||||
elif self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_TILE: # 屋顶
|
||||
# 首先需要判断植物是否是水生植物,水生植物不能种植在陆地上
|
||||
if plantName not in c.WATER_PLANTS:
|
||||
if plant_name not in c.WATER_PLANTS:
|
||||
if "花盆(未实现)" in self.map[map_y][map_x][c.MAP_PLANT]:
|
||||
if (all((i in {"花盆(未实现)", c.PUMPKINHEAD}) for i in self.map[map_y][map_x][c.MAP_PLANT])
|
||||
and (plantName not in self.map[map_y][map_x][c.MAP_PLANT])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植
|
||||
if plantName in {c.SPIKEWEED}: # 不能在花盆上种植的植物
|
||||
and (plant_name not in self.map[map_y][map_x][c.MAP_PLANT])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植
|
||||
if plant_name in {c.SPIKEWEED}: # 不能在花盆上种植的植物
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif (plantName == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 有花盆且没有南瓜头就能种南瓜头
|
||||
elif (plant_name == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 有花盆且没有南瓜头就能种南瓜头
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
elif plantName == "花盆(未实现)": # 这一格本来没有花盆而且新来的植物是花盆,可以种
|
||||
elif plant_name == "花盆(未实现)": # 这一格本来没有花盆而且新来的植物是花盆,可以种
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
elif self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_WATER: # 水里
|
||||
if plantName in c.WATER_PLANTS: # 是水生植物
|
||||
if plant_name in c.WATER_PLANTS: # 是水生植物
|
||||
if not self.map[map_y][map_x][c.MAP_PLANT]: # 只有无植物时才能在水里种植水生植物
|
||||
return True
|
||||
else:
|
||||
@ -105,12 +105,12 @@ class Map():
|
||||
else: # 非水生植物,依赖睡莲
|
||||
if c.LILYPAD in self.map[map_y][map_x][c.MAP_PLANT]:
|
||||
if (all((i in {c.LILYPAD, c.PUMPKINHEAD}) for i in self.map[map_y][map_x][c.MAP_PLANT])
|
||||
and (plantName not in self.map[map_y][map_x][c.MAP_PLANT])):
|
||||
if plantName in {c.SPIKEWEED, c.POTATOMINE, "花盆(未实现)"}: # 不能在睡莲上种植的植物
|
||||
and (plant_name not in self.map[map_y][map_x][c.MAP_PLANT])):
|
||||
if plant_name in {c.SPIKEWEED, c.POTATOMINE, "花盆(未实现)"}: # 不能在睡莲上种植的植物
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif (plantName == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 在睡莲上且没有南瓜头就能种南瓜头
|
||||
elif (plant_name == c.PUMPKINHEAD) and (c.PUMPKINHEAD not in self.map[map_y][map_x][c.MAP_PLANT]): # 在睡莲上且没有南瓜头就能种南瓜头
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@ -152,22 +152,22 @@ class Map():
|
||||
def setMapGridType(self, map_x, map_y, plot_type):
|
||||
self.map[map_y][map_x][c.MAP_PLOT_TYPE] = plot_type
|
||||
|
||||
def addMapPlant(self, map_x, map_y, plantName, sleep=False):
|
||||
self.map[map_y][map_x][c.MAP_PLANT].add(plantName)
|
||||
def addMapPlant(self, map_x, map_y, plant_name, sleep=False):
|
||||
self.map[map_y][map_x][c.MAP_PLANT].add(plant_name)
|
||||
self.map[map_y][map_x][c.MAP_SLEEP] = sleep
|
||||
|
||||
def removeMapPlant(self, map_x, map_y, plantName):
|
||||
self.map[map_y][map_x][c.MAP_PLANT].discard(plantName)
|
||||
def removeMapPlant(self, map_x, map_y, plant_name):
|
||||
self.map[map_y][map_x][c.MAP_PLANT].discard(plant_name)
|
||||
|
||||
def getRandomMapIndex(self):
|
||||
map_x = random.randint(0, self.width-1)
|
||||
map_y = random.randint(0, self.height-1)
|
||||
return (map_x, map_y)
|
||||
|
||||
def checkPlantToSeed(self, x, y, plantName):
|
||||
def checkPlantToSeed(self, x, y, plant_name):
|
||||
pos = None
|
||||
map_x, map_y = self.getMapIndex(x, y)
|
||||
if self.isValid(map_x, map_y) and self.isAvailable(map_x, map_y, plantName):
|
||||
if self.isValid(map_x, map_y) and self.isAvailable(map_x, map_y, plant_name):
|
||||
pos = self.getMapGridPos(map_x, map_y)
|
||||
return pos
|
||||
|
||||
@ -212,7 +212,7 @@ LEVEL_MAP_DATA = (
|
||||
# 第2关:三行草皮
|
||||
{
|
||||
c.BACKGROUND_TYPE: 8,
|
||||
c.INIT_SUN_NAME: 150,
|
||||
c.INIT_SUN_NAME: 50,
|
||||
c.SHOVEL: 1,
|
||||
c.SPAWN_ZOMBIES:c.SPAWN_ZOMBIES_AUTO,
|
||||
c.INCLUDED_ZOMBIES:(c.NORMAL_ZOMBIE,),
|
||||
@ -412,7 +412,7 @@ LITTLE_GAME_MAP_DATA = (
|
||||
c.SPIKEWEED: 100,
|
||||
c.SQUASH: 100,
|
||||
c.JALAPENO: 50,
|
||||
c.THREEPEASHOOTER: 400,}
|
||||
c.THREEPEASHOOTER: 300,}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -37,7 +37,9 @@ class Car(pg.sprite.Sprite):
|
||||
|
||||
# 豌豆及孢子类普通子弹
|
||||
class Bullet(pg.sprite.Sprite):
|
||||
def __init__(self, x, start_y, dest_y, name, damage, effect=None, passedTorchWood=None, damageType=c.ZOMBIE_DEAFULT_DAMAGE):
|
||||
def __init__( self, x, start_y, dest_y, name, damage,
|
||||
effect=None, passed_torchwood_x=None,
|
||||
damageType=c.ZOMBIE_DEAFULT_DAMAGE):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
self.name = name
|
||||
@ -60,7 +62,7 @@ class Bullet(pg.sprite.Sprite):
|
||||
self.current_time = 0
|
||||
self.animate_timer = 0
|
||||
self.animate_interval = 70
|
||||
self.passedTorchWood = passedTorchWood # 记录最近通过的火炬树横坐标,如果没有缺省为None
|
||||
self.passed_torchwood_x = passed_torchwood_x # 记录最近通过的火炬树横坐标,如果没有缺省为None
|
||||
|
||||
def loadFrames(self, frames, name):
|
||||
frame_list = tool.GFX[name]
|
||||
@ -104,7 +106,7 @@ class Bullet(pg.sprite.Sprite):
|
||||
if self.y_vel * (self.dest_y - self.rect.y) < 0:
|
||||
self.rect.y = self.dest_y
|
||||
self.rect.x += self.x_vel
|
||||
if self.rect.x >= c.SCREEN_WIDTH + 60:
|
||||
if self.rect.x >= c.SCREEN_WIDTH + 20:
|
||||
self.kill()
|
||||
elif self.state == c.EXPLODE:
|
||||
if (self.current_time - self.explode_timer) > 250:
|
||||
@ -206,7 +208,7 @@ class StarBullet(Bullet):
|
||||
else:
|
||||
self.rect.x -= 10
|
||||
self.handleMapYPosition()
|
||||
if ((self.rect.x > c.SCREEN_WIDTH + 60) or (self.rect.x < -60)
|
||||
if ((self.rect.x > c.SCREEN_WIDTH + 20) or (self.rect.right < -20)
|
||||
or (self.rect.y > c.SCREEN_HEIGHT) or (self.rect.y < 0)):
|
||||
self.kill()
|
||||
elif self.state == c.EXPLODE:
|
||||
@ -248,7 +250,7 @@ class Plant(pg.sprite.Sprite):
|
||||
self.animate_interval = 70 # 帧播放间隔
|
||||
self.hit_timer = 0
|
||||
# 被铲子指向时间
|
||||
self.highlightTime = 0
|
||||
self.highlight_time = 0
|
||||
|
||||
def loadFrames(self, frames, name, scale=1, color=c.BLACK):
|
||||
frame_list = tool.GFX[name]
|
||||
@ -267,7 +269,7 @@ class Plant(pg.sprite.Sprite):
|
||||
self.loadFrames(self.frames, name, scale)
|
||||
|
||||
def changeFrames(self, frames):
|
||||
"""change image frames and modify rect position"""
|
||||
# change image frames and modify rect position
|
||||
self.frames = frames
|
||||
self.frame_num = len(self.frames)
|
||||
self.frame_index = 0
|
||||
@ -311,7 +313,7 @@ class Plant(pg.sprite.Sprite):
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -322,7 +324,7 @@ class Plant(pg.sprite.Sprite):
|
||||
if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames):
|
||||
return False
|
||||
if (self.state != c.SLEEP and zombie.state != c.DIE and
|
||||
self.rect.x <= zombie.rect.right and zombie.rect.left <= c.SCREEN_WIDTH):
|
||||
self.rect.x <= zombie.rect.right and zombie.rect.x <= c.SCREEN_WIDTH - 24):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -338,7 +340,7 @@ class Plant(pg.sprite.Sprite):
|
||||
self.changeFrames(self.sleep_frames)
|
||||
|
||||
def setDamage(self, damage, zombie):
|
||||
if not zombie.lostHead:
|
||||
if not zombie.losthead:
|
||||
self.health -= damage
|
||||
self.hit_timer = self.current_time
|
||||
if ((self.name == c.HYPNOSHROOM) and
|
||||
@ -429,20 +431,20 @@ class RepeaterPea(Plant):
|
||||
self.shoot_timer = 0
|
||||
|
||||
# 是否发射第一颗
|
||||
self.firstShot = False
|
||||
self.first_shot = False
|
||||
|
||||
def attacking(self):
|
||||
if self.shoot_timer == 0:
|
||||
self.shoot_timer = self.current_time - 700
|
||||
elif (self.current_time - self.shoot_timer >= 1400):
|
||||
self.firstShot = True
|
||||
self.first_shot = True
|
||||
self.bullet_group.add(Bullet(self.rect.right - 15, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=None))
|
||||
self.shoot_timer = self.current_time
|
||||
# 播放发射音效
|
||||
c.SOUND_SHOOT.play()
|
||||
elif self.firstShot and (self.current_time - self.shoot_timer) > 100:
|
||||
self.firstShot = False
|
||||
elif self.first_shot and (self.current_time - self.shoot_timer) > 100:
|
||||
self.first_shot = False
|
||||
self.bullet_group.add(Bullet(self.rect.right - 15, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=None))
|
||||
# 播放发射音效
|
||||
@ -580,7 +582,7 @@ class CherryBomb(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -596,7 +598,7 @@ class Chomper(Plant):
|
||||
self.digest_interval = 15000
|
||||
self.attack_zombie = None
|
||||
self.zombie_group = None
|
||||
self.shouldDiggest = False
|
||||
self.should_diggest = False
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
@ -624,7 +626,7 @@ class Chomper(Plant):
|
||||
if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames):
|
||||
return False
|
||||
elif (self.state == c.IDLE and zombie.state != c.DIGEST and
|
||||
self.rect.x <= zombie.rect.centerx and (not zombie.lostHead) and
|
||||
self.rect.x <= zombie.rect.centerx and (not zombie.losthead) and
|
||||
(self.rect.x + c.GRID_X_SIZE*2.7 >= zombie.rect.centerx)):
|
||||
return True
|
||||
return False
|
||||
@ -648,12 +650,12 @@ class Chomper(Plant):
|
||||
# 播放吞的音效
|
||||
c.SOUND_BIGCHOMP.play()
|
||||
if self.attack_zombie.alive():
|
||||
self.shouldDiggest = True
|
||||
self.should_diggest = True
|
||||
self.attack_zombie.kill()
|
||||
if (self.frame_index + 1) == self.frame_num:
|
||||
if self.shouldDiggest:
|
||||
if self.should_diggest:
|
||||
self.setDigest()
|
||||
self.shouldDiggest = False
|
||||
self.should_diggest = False
|
||||
else:
|
||||
self.setIdle()
|
||||
|
||||
@ -751,7 +753,7 @@ class PotatoMine(Plant):
|
||||
return False
|
||||
# 这里碰撞应当比碰撞一般更容易,就设置成圆形或矩形模式,不宜采用mask
|
||||
elif (pg.sprite.collide_circle_ratio(0.7)(zombie, self) and
|
||||
(not self.is_init) and (not zombie.lostHead)):
|
||||
(not self.is_init) and (not zombie.losthead)):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -767,12 +769,12 @@ class PotatoMine(Plant):
|
||||
|
||||
|
||||
class Squash(Plant):
|
||||
def __init__(self, x, y, mapPlantsSet):
|
||||
def __init__(self, x, y, map_plant_set):
|
||||
Plant.__init__(self, x, y, c.SQUASH, c.PLANT_HEALTH, None)
|
||||
self.orig_pos = (x, y)
|
||||
self.aim_timer = 0
|
||||
self.start_boom = False # 和灰烬等植物统一变量名,在这里表示倭瓜是否跳起
|
||||
self.mapPlantsSet = mapPlantsSet
|
||||
self.map_plant_set = map_plant_set
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
@ -816,7 +818,7 @@ class Squash(Plant):
|
||||
if self.canAttack(zombie):
|
||||
zombie.setDamage(1800, damageType=c.ZOMBIE_RANGE_DAMAGE)
|
||||
self.health = 0 # 避免僵尸在原位啃食
|
||||
self.mapPlantsSet.remove(c.SQUASH)
|
||||
self.map_plant_set.remove(c.SQUASH)
|
||||
self.kill()
|
||||
# 播放碾压音效
|
||||
c.SOUND_SQUASHING.play()
|
||||
@ -870,7 +872,7 @@ class Spikeweed(Plant):
|
||||
if self.canAttack(zombie):
|
||||
# 有车的僵尸
|
||||
if zombie.name in {c.ZOMBONI}:
|
||||
zombie.health = zombie.lostHeadHealth
|
||||
zombie.health = zombie.losthead_health
|
||||
killSelf = True
|
||||
else:
|
||||
zombie.setDamage(20, damageType=c.ZOMBIE_COMMON_DAMAGE)
|
||||
@ -924,7 +926,7 @@ class Jalapeno(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -1091,7 +1093,7 @@ class IceShroom(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -1288,16 +1290,16 @@ class TorchWood(Plant):
|
||||
def idling(self):
|
||||
for i in self.bullet_group:
|
||||
if i.name == c.BULLET_PEA:
|
||||
if i.passedTorchWood != self.rect.centerx:
|
||||
if i.passed_torchwood_x != self.rect.centerx:
|
||||
if abs(i.rect.centerx - self.rect.centerx) <= 20:
|
||||
self.bullet_group.add(Bullet(i.rect.x, i.rect.y, i.dest_y,
|
||||
c.BULLET_FIREBALL, c.BULLET_DAMAGE_FIREBALL_BODY, effect=c.BULLET_EFFECT_UNICE, passedTorchWood=self.rect.centerx))
|
||||
c.BULLET_FIREBALL, c.BULLET_DAMAGE_FIREBALL_BODY, effect=c.BULLET_EFFECT_UNICE, passed_torchwood_x=self.rect.centerx))
|
||||
i.kill()
|
||||
elif i.name == c.BULLET_PEA_ICE:
|
||||
if i.passedTorchWood != self.rect.centerx:
|
||||
if i.passed_torchwood_x != self.rect.centerx:
|
||||
if abs(i.rect.centerx - self.rect.centerx) <= 20:
|
||||
self.bullet_group.add(Bullet(i.rect.x, i.rect.y, i.dest_y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=None, passedTorchWood=self.rect.centerx))
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=None, passed_torchwood_x=self.rect.centerx))
|
||||
i.kill()
|
||||
|
||||
class StarFruit(Plant):
|
||||
@ -1311,8 +1313,8 @@ class StarFruit(Plant):
|
||||
if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames):
|
||||
return False
|
||||
if zombie.state != c.DIE:
|
||||
zombieMapY = self.level.map.getMapIndex(zombie.rect.centerx, zombie.rect.bottom)[1]
|
||||
if (self.rect.x >= zombie.rect.x) and (self.map_y == zombieMapY): # 对于同行且在杨桃后的僵尸
|
||||
zombie_map_y = self.level.map.getMapIndex(zombie.rect.centerx, zombie.rect.bottom)[1]
|
||||
if (self.rect.x >= zombie.rect.x) and (self.map_y == zombie_map_y): # 对于同行且在杨桃后的僵尸
|
||||
return True
|
||||
# 斜向上,理想直线方程为:f(zombie.rect.x) = -0.75*(zombie.rect.x - (self.rect.right - 5)) + self.rect.y - 10
|
||||
# 注意实际上为射线
|
||||
@ -1348,10 +1350,10 @@ class StarFruit(Plant):
|
||||
|
||||
|
||||
class CoffeeBean(Plant):
|
||||
def __init__(self, x, y, plant_group, mapContent, map, map_x):
|
||||
def __init__(self, x, y, plant_group, map_content, map, map_x):
|
||||
Plant.__init__(self, x, y, c.COFFEEBEAN, c.PLANT_HEALTH, None)
|
||||
self.plant_group = plant_group
|
||||
self.mapContent = mapContent
|
||||
self.map_content = map_content
|
||||
self.map = map
|
||||
self.map_x = map_x
|
||||
|
||||
@ -1360,7 +1362,7 @@ class CoffeeBean(Plant):
|
||||
self.frame_index += 1
|
||||
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.mapContent[c.MAP_SLEEP] = False
|
||||
self.map_content[c.MAP_SLEEP] = False
|
||||
for plant in self.plant_group:
|
||||
if plant.can_sleep:
|
||||
if plant.state == c.SLEEP:
|
||||
@ -1371,7 +1373,7 @@ class CoffeeBean(Plant):
|
||||
plant.changeFrames(plant.idle_frames)
|
||||
# 播放唤醒音效
|
||||
c.SOUND_MUSHROOM_WAKEUP.play()
|
||||
self.mapContent[c.MAP_PLANT].remove(self.name)
|
||||
self.map_content[c.MAP_PLANT].remove(self.name)
|
||||
self.kill()
|
||||
self.frame_index = self.frame_num - 1
|
||||
|
||||
@ -1379,7 +1381,7 @@ class CoffeeBean(Plant):
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -1480,7 +1482,7 @@ class TangleKlep(Plant):
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if zombie.state != c.DIE and (not zombie.lostHead):
|
||||
if zombie.state != c.DIE and (not zombie.losthead):
|
||||
# 这里碰撞应当比碰撞一般更容易,就设置成圆形或矩形模式,不宜采用mask
|
||||
if pg.sprite.collide_circle_ratio(0.7)(zombie, self):
|
||||
return True
|
||||
@ -1510,17 +1512,17 @@ class TangleKlep(Plant):
|
||||
# 坑形态的毁灭菇同地刺一样不可以被啃食
|
||||
# 爆炸时杀死同一格的所有植物
|
||||
class DoomShroom(Plant):
|
||||
def __init__(self, x, y, mapPlantsSet, explode_y_range):
|
||||
def __init__(self, x, y, map_plant_set, explode_y_range):
|
||||
Plant.__init__(self, x, y, c.DOOMSHROOM, c.PLANT_HEALTH, None)
|
||||
self.can_sleep = True
|
||||
self.mapPlantSet = mapPlantsSet
|
||||
self.map_plant_set = map_plant_set
|
||||
self.bomb_timer = 0
|
||||
self.explode_y_range = explode_y_range
|
||||
self.explode_x_range = 250
|
||||
self.start_boom = False
|
||||
self.boomed = False
|
||||
self.originalX = x
|
||||
self.originalY = y
|
||||
self.original_x = x
|
||||
self.original_y = y
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
@ -1556,7 +1558,7 @@ class DoomShroom(Plant):
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.health = 0
|
||||
self.frame_index = self.frame_num - 1
|
||||
self.mapPlantSet.add(c.HOLE)
|
||||
self.map_plant_set.add(c.HOLE)
|
||||
# 睡觉状态
|
||||
elif self.state == c.SLEEP:
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
@ -1576,7 +1578,7 @@ class DoomShroom(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -1668,8 +1670,8 @@ class GraveBuster(Plant):
|
||||
self.frame_index = self.frame_num - 1
|
||||
for item in self.plant_group:
|
||||
if item.name == c.GRAVE:
|
||||
itemMapX, _ = self.map.getMapIndex(item.rect.centerx, item.rect.bottom)
|
||||
if itemMapX == self.map_x:
|
||||
item_map_x, _ = self.map.getMapIndex(item.rect.centerx, item.rect.bottom)
|
||||
if item_map_x == self.map_x:
|
||||
item.health = 0
|
||||
self.health = 0
|
||||
self.animate_timer = self.current_time
|
||||
@ -1677,7 +1679,7 @@ class GraveBuster(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
@ -1689,7 +1691,7 @@ class FumeShroom(Plant):
|
||||
Plant.__init__(self, x, y, c.FUMESHROOM, c.PLANT_HEALTH, bullet_group)
|
||||
self.can_sleep = True
|
||||
self.shoot_timer = 0
|
||||
self.showAttackFrames = True
|
||||
self.show_attack_frames = True
|
||||
self.zombie_group = zombie_group
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
@ -1726,18 +1728,18 @@ class FumeShroom(Plant):
|
||||
if self.shoot_timer == 0:
|
||||
self.shoot_timer = self.current_time - 700
|
||||
elif self.current_time - self.shoot_timer >= 1100:
|
||||
if self.showAttackFrames:
|
||||
self.showAttackFrames = False
|
||||
if self.show_attack_frames:
|
||||
self.show_attack_frames = False
|
||||
self.changeFrames(self.attack_frames)
|
||||
|
||||
if self.current_time - self.shoot_timer >= 1400:
|
||||
self.bullet_group.add(Fume(self.rect.right - 35, self.rect.y))
|
||||
# 烟雾只是个动画,实际伤害由本身完成
|
||||
for targetZombie in self.zombie_group:
|
||||
if self.canAttack(targetZombie):
|
||||
targetZombie.setDamage(c.BULLET_DAMAGE_NORMAL, damageType=c.ZOMBIE_RANGE_DAMAGE)
|
||||
for target_zombie in self.zombie_group:
|
||||
if self.canAttack(target_zombie):
|
||||
target_zombie.setDamage(c.BULLET_DAMAGE_NORMAL, damageType=c.ZOMBIE_RANGE_DAMAGE)
|
||||
self.shoot_timer = self.current_time
|
||||
self.showAttackFrames = True
|
||||
self.show_attack_frames = True
|
||||
# 播放发射音效
|
||||
c.SOUND_FUME.play()
|
||||
|
||||
@ -1754,7 +1756,7 @@ class FumeShroom(Plant):
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
if (self.current_time - self.highlightTime < 100):
|
||||
if (self.current_time - self.highlight_time < 100):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
self.image.set_alpha(192)
|
||||
|
||||
@ -5,7 +5,10 @@ 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):
|
||||
def __init__( self, x, y, name, head_group=None,
|
||||
helmet_health=0, helmet_type2_health=0,
|
||||
body_health=c.NORMAL_HEALTH, losthead_health=c.LOSTHEAD_HEALTH,
|
||||
damage=c.ZOMBIE_ATTACK_DAMAGE, can_swim=False):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
self.name = name
|
||||
@ -15,26 +18,26 @@ class Zombie(pg.sprite.Sprite):
|
||||
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.mask = pg.mask.from_surface(self.image)
|
||||
self.rect.x = x
|
||||
self.rect.bottom = y
|
||||
# 大蒜换行移动像素值,< 0时向上,= 0时不变,> 0时向上
|
||||
self.targetYChange = 0
|
||||
self.originalY = y
|
||||
self.toChangeGroup = False
|
||||
self.target_y_change = 0
|
||||
self.original_y = y
|
||||
self.to_change_group = False
|
||||
|
||||
self.helmetHealth = helmetHealth
|
||||
self.helmetType2Health = helmetType2Health
|
||||
self.health = bodyHealth + lostHeadHealth
|
||||
self.lostHeadHealth = lostHeadHealth
|
||||
self.helmet_health = helmet_health
|
||||
self.helmet_type2_health = helmet_type2_health
|
||||
self.health = body_health + losthead_health
|
||||
self.losthead_health = losthead_health
|
||||
self.damage = damage
|
||||
self.dead = False
|
||||
self.lostHead = False
|
||||
self.canSwim = canSwim
|
||||
self.losthead = False
|
||||
self.can_swim = can_swim
|
||||
self.swimming = False
|
||||
self.helmet = (self.helmetHealth > 0)
|
||||
self.helmetType2 = (self.helmetType2Health > 0)
|
||||
self.helmet = (self.helmet_health > 0)
|
||||
self.helmet_type2 = (self.helmet_type2_health > 0)
|
||||
self.head_group = head_group
|
||||
|
||||
self.walk_timer = 0
|
||||
@ -44,7 +47,7 @@ class Zombie(pg.sprite.Sprite):
|
||||
self.animate_interval = 150
|
||||
self.walk_animate_interval = 180
|
||||
self.attack_animate_interval = 100
|
||||
self.lostHead_animate_interval = 180
|
||||
self.losthead_animate_interval = 180
|
||||
self.die_animate_interval = 50
|
||||
self.boomDie_animate_interval = 100
|
||||
self.ice_slow_ratio = 1
|
||||
@ -88,8 +91,8 @@ class Zombie(pg.sprite.Sprite):
|
||||
if self.health <= 0:
|
||||
self.setDie()
|
||||
return True
|
||||
elif self.health <= self.lostHeadHealth:
|
||||
if not self.lostHead:
|
||||
elif self.health <= self.losthead_health:
|
||||
if not self.losthead:
|
||||
self.changeFrames(framesKind)
|
||||
self.setLostHead()
|
||||
return True
|
||||
@ -105,7 +108,7 @@ class Zombie(pg.sprite.Sprite):
|
||||
return
|
||||
|
||||
# 能游泳的僵尸
|
||||
if self.canSwim:
|
||||
if self.can_swim:
|
||||
# 在水池范围内
|
||||
# 在右侧岸左
|
||||
if self.rect.right <= c.MAP_POOL_FRONT_X:
|
||||
@ -119,25 +122,25 @@ class Zombie(pg.sprite.Sprite):
|
||||
c.SOUND_ZOMBIE_ENTERING_WATER.play()
|
||||
# 同样没有兼容双防具
|
||||
if self.helmet:
|
||||
if self.helmetHealth <= 0:
|
||||
if self.helmet_health <= 0:
|
||||
self.helmet = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_swim_frames)
|
||||
if self.helmetType2:
|
||||
if self.helmetType2Health <= 0:
|
||||
self.helmetType2 = False
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.helmet_type2 = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_swim_frames)
|
||||
# 已经进入游泳状态
|
||||
else:
|
||||
if self.helmet:
|
||||
if self.helmetHealth <= 0:
|
||||
if self.helmet_health <= 0:
|
||||
self.changeFrames(self.swim_frames)
|
||||
self.helmet = False
|
||||
if self.helmetType2:
|
||||
if self.helmetType2Health <= 0:
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.changeFrames(self.swim_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
# 水生僵尸已经接近家门口并且上岸
|
||||
else:
|
||||
if self.swimming:
|
||||
@ -145,55 +148,55 @@ class Zombie(pg.sprite.Sprite):
|
||||
self.swimming = False
|
||||
# 同样没有兼容双防具
|
||||
if self.helmet:
|
||||
if self.helmetHealth <= 0:
|
||||
if self.helmet_health <= 0:
|
||||
self.helmet = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_walk_frames)
|
||||
if self.helmetType2:
|
||||
if self.helmetType2Health <= 0:
|
||||
self.helmetType2 = False
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.helmet_type2 = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_walk_frames)
|
||||
if self.helmet:
|
||||
if self.helmetHealth <= 0:
|
||||
if self.helmet_health <= 0:
|
||||
self.helmet = False
|
||||
self.changeFrames(self.walk_frames)
|
||||
if self.helmetType2:
|
||||
if self.helmetType2Health <= 0:
|
||||
self.helmetType2 = False
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.helmet_type2 = 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:
|
||||
if self.helmet_health <= 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:
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
elif self.swimming: # 游泳状态需要改为步行
|
||||
self.changeFrames(self.helmet_walk_frames)
|
||||
self.swimming = False
|
||||
# 尚未进入水池
|
||||
else:
|
||||
if self.helmetHealth <= 0 and self.helmet:
|
||||
if self.helmet_health <= 0 and self.helmet:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmet = False
|
||||
if self.helmetType2Health <= 0 and self.helmetType2:
|
||||
if self.helmet_type2_health <= 0 and self.helmet_type2:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
# 不能游泳的一般僵尸
|
||||
else:
|
||||
if self.helmetHealth <= 0 and self.helmet:
|
||||
if self.helmet_health <= 0 and self.helmet:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmet = False
|
||||
if self.helmetType2Health <= 0 and self.helmetType2:
|
||||
if self.helmet_type2_health <= 0 and self.helmet_type2:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
|
||||
if (self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio()):
|
||||
self.handleGarlicYChange()
|
||||
@ -204,48 +207,48 @@ class Zombie(pg.sprite.Sprite):
|
||||
self.rect.x -= 1
|
||||
|
||||
def handleGarlicYChange(self):
|
||||
if self.targetYChange < 0:
|
||||
if self.rect.bottom > self.originalY + self.targetYChange: # 注意这里加的是负数
|
||||
if self.target_y_change < 0:
|
||||
if self.rect.bottom > self.original_y + self.target_y_change: # 注意这里加的是负数
|
||||
self.rect.bottom -= 3
|
||||
# 过半时换行
|
||||
if ((self.toChangeGroup) and
|
||||
(self.rect.bottom >= self.originalY + 0.5*self.targetYChange)):
|
||||
self.level.zombie_groups[self.mapY].remove(self)
|
||||
self.level.zombie_groups[self.targetMapY].add(self)
|
||||
self.toChangeGroup = False
|
||||
if ((self.to_change_group) and
|
||||
(self.rect.bottom >= self.original_y + 0.5*self.target_y_change)):
|
||||
self.level.zombie_groups[self.map_y].remove(self)
|
||||
self.level.zombie_groups[self.target_map_y].add(self)
|
||||
self.to_change_group = False
|
||||
else:
|
||||
self.rect.bottom = self.originalY + self.targetYChange
|
||||
self.originalY = self.rect.bottom
|
||||
self.targetYChange = 0
|
||||
elif self.targetYChange > 0:
|
||||
if self.rect.bottom < self.originalY + self.targetYChange: # 注意这里加的是负数
|
||||
self.rect.bottom = self.original_y + self.target_y_change
|
||||
self.original_y = self.rect.bottom
|
||||
self.target_y_change = 0
|
||||
elif self.target_y_change > 0:
|
||||
if self.rect.bottom < self.original_y + self.target_y_change: # 注意这里加的是负数
|
||||
self.rect.bottom += 3
|
||||
# 过半时换行
|
||||
if ((self.toChangeGroup) and
|
||||
(self.rect.bottom <= self.originalY + 0.5*self.targetYChange)):
|
||||
self.level.zombie_groups[self.mapY].remove(self)
|
||||
self.level.zombie_groups[self.targetMapY].add(self)
|
||||
self.toChangeGroup = False
|
||||
if ((self.to_change_group) and
|
||||
(self.rect.bottom <= self.original_y + 0.5*self.target_y_change)):
|
||||
self.level.zombie_groups[self.map_y].remove(self)
|
||||
self.level.zombie_groups[self.target_map_y].add(self)
|
||||
self.to_change_group = False
|
||||
else:
|
||||
self.rect.bottom = self.originalY + self.targetYChange
|
||||
self.originalY = self.rect.bottom
|
||||
self.targetYChange = 0
|
||||
self.rect.bottom = self.original_y + self.target_y_change
|
||||
self.original_y = self.rect.bottom
|
||||
self.target_y_change = 0
|
||||
|
||||
def attacking(self):
|
||||
if self.checkToDie(self.losthead_attack_frames):
|
||||
return
|
||||
|
||||
if self.helmetHealth <= 0 and self.helmet:
|
||||
if self.helmet_health <= 0 and self.helmet:
|
||||
self.changeFrames(self.attack_frames)
|
||||
self.helmet = False
|
||||
if self.helmetType2Health <= 0 and self.helmetType2:
|
||||
if self.helmet_type2_health <= 0 and self.helmet_type2:
|
||||
self.changeFrames(self.attack_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
if self.name == c.NEWSPAPER_ZOMBIE:
|
||||
self.speed = 2.65
|
||||
self.walk_animate_interval = 300
|
||||
if (((self.current_time - self.attack_timer) > (c.ATTACK_INTERVAL * self.getAttackTimeRatio()))
|
||||
and (not self.lostHead)):
|
||||
and (not self.losthead)):
|
||||
if self.prey.health > 0:
|
||||
if self.prey_is_plant:
|
||||
self.prey.setDamage(self.damage, self)
|
||||
@ -281,8 +284,8 @@ class Zombie(pg.sprite.Sprite):
|
||||
|
||||
def setLostHead(self):
|
||||
self.losthead_timer = self.current_time
|
||||
self.lostHead = True
|
||||
self.animate_interval = self.lostHead_animate_interval
|
||||
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))
|
||||
|
||||
@ -347,87 +350,87 @@ class Zombie(pg.sprite.Sprite):
|
||||
# 冰冻减速效果
|
||||
if effect == c.BULLET_EFFECT_ICE:
|
||||
if damageType == c.ZOMBIE_DEAFULT_DAMAGE: # 寒冰射手不能穿透二类防具进行减速
|
||||
if not self.helmetType2:
|
||||
if not self.helmet_type2:
|
||||
self.setIceSlow()
|
||||
else:
|
||||
self.setIceSlow()
|
||||
# 解冻
|
||||
elif effect == c.BULLET_EFFECT_UNICE:
|
||||
if damageType == c.ZOMBIE_DEAFULT_DAMAGE: # 寒冰射手不能穿透二类防具进行减速
|
||||
if not self.helmetType2:
|
||||
if not self.helmet_type2:
|
||||
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_type2:
|
||||
self.helmet_type2_health -= damage
|
||||
if self.helmet_type2_health <= 0:
|
||||
if self.helmet:
|
||||
self.helmetHealth += self.helmetType2Health # 注意self.helmetType2Health已经带有正负
|
||||
self.helmetType2Health = 0 # 注意合并后清零
|
||||
if self.helmetHealth <= 0:
|
||||
self.health += self.helmetHealth
|
||||
self.helmetHealth = 0 # 注意合并后清零
|
||||
self.helmet_health += self.helmet_type2_health # 注意self.helmet_type2_health已经带有正负
|
||||
self.helmet_type2_health = 0 # 注意合并后清零
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 0 # 注意合并后清零
|
||||
else:
|
||||
self.health += self.helmetType2Health
|
||||
self.helmetType2Health = 0
|
||||
self.health += self.helmet_type2_health
|
||||
self.helmet_type2_health = 0
|
||||
elif self.helmet: # 不存在二类防具,但是存在一类防具
|
||||
self.helmetHealth -= damage
|
||||
if self.helmetHealth <= 0:
|
||||
self.health += self.helmetHealth
|
||||
self.helmetHealth = 0 # 注意合并后清零
|
||||
self.helmet_health -= damage
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 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 # 注意合并后清零
|
||||
self.helmet_health -= damage
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 0 # 注意合并后清零
|
||||
else: # 没有一类防具
|
||||
self.health -= damage
|
||||
elif damageType == c.ZOMBIE_RANGE_DAMAGE:
|
||||
# 从第二类防具开始逐级传递
|
||||
if self.helmetType2:
|
||||
self.helmetType2Health -= damage
|
||||
if self.helmetType2Health <= 0:
|
||||
if self.helmet_type2:
|
||||
self.helmet_type2_health -= damage
|
||||
if self.helmet_type2_health <= 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 # 注意合并后清零
|
||||
self.helmet_health -= damage # 注意范围伤害中这里还有一个攻击
|
||||
self.helmet_health += self.helmet_type2_health # 注意self.helmet_type2_health已经带有正负
|
||||
self.helmet_type2_health = 0 # 注意合并后清零
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 0 # 注意合并后清零
|
||||
else:
|
||||
self.health -= damage # 注意范围伤害中这里还有一个攻击
|
||||
self.health += self.helmetType2Health
|
||||
self.helmetType2Health = 0
|
||||
self.health += self.helmet_type2_health
|
||||
self.helmet_type2_health = 0
|
||||
else:
|
||||
if self.helmet:
|
||||
self.helmetHealth -= damage
|
||||
if self.helmetHealth <= 0:
|
||||
self.health += self.helmetHealth
|
||||
self.helmetHealth = 0 # 注意合并后清零
|
||||
self.helmet_health -= damage
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 0 # 注意合并后清零
|
||||
else:
|
||||
self.health -= damage
|
||||
elif self.helmet: # 不存在二类防具,但是存在一类防具
|
||||
self.helmetHealth -= damage
|
||||
if self.helmetHealth <= 0:
|
||||
self.health += self.helmetHealth
|
||||
self.helmetHealth = 0 # 注意合并后清零
|
||||
self.helmet_health -= damage
|
||||
if self.helmet_health <= 0:
|
||||
self.health += self.helmet_health
|
||||
self.helmet_health = 0 # 注意合并后清零
|
||||
else: # 没有防具
|
||||
self.health -= damage
|
||||
elif damageType == c.ZOMBIE_ASH_DAMAGE:
|
||||
self.health -= damage # 无视任何防具
|
||||
elif damageType == c.ZOMBIE_WALLNUT_BOWLING_DANMAGE:
|
||||
# 逻辑:对防具的多余伤害不传递
|
||||
if self.helmetType2:
|
||||
if self.helmet_type2:
|
||||
# 对二类防具伤害较一般情况低,拟合铁门需要砸3次的设定
|
||||
self.helmetType2Health -= int(damage * 0.8)
|
||||
self.helmet_type2_health -= int(damage * 0.8)
|
||||
elif self.helmet: # 不存在二类防具,但是存在一类防具
|
||||
self.helmetHealth -= damage
|
||||
self.helmet_health -= damage
|
||||
else: # 没有防具
|
||||
self.health -= damage
|
||||
else:
|
||||
@ -441,28 +444,28 @@ class Zombie(pg.sprite.Sprite):
|
||||
self.state = c.WALK
|
||||
self.animate_interval = self.walk_animate_interval
|
||||
|
||||
if self.helmet or self.helmetType2: # 这里暂时没有考虑同时有两种防具的僵尸
|
||||
if self.helmet or self.helmet_type2: # 这里暂时没有考虑同时有两种防具的僵尸
|
||||
self.changeFrames(self.helmet_walk_frames)
|
||||
elif self.lostHead:
|
||||
elif self.losthead:
|
||||
self.changeFrames(self.losthead_walk_frames)
|
||||
else:
|
||||
self.changeFrames(self.walk_frames)
|
||||
|
||||
if self.canSwim:
|
||||
if self.can_swim:
|
||||
if self.rect.right <= c.MAP_POOL_FRONT_X:
|
||||
self.swimming = True
|
||||
self.changeFrames(self.swim_frames)
|
||||
# 同样没有兼容双防具
|
||||
if self.helmet:
|
||||
if self.helmetHealth <= 0:
|
||||
if self.helmet_health <= 0:
|
||||
self.changeFrames(self.swim_frames)
|
||||
self.helmet = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_swim_frames)
|
||||
if self.helmetType2:
|
||||
if self.helmetType2Health <= 0:
|
||||
if self.helmet_type2:
|
||||
if self.helmet_type2_health <= 0:
|
||||
self.changeFrames(self.swim_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
else:
|
||||
self.changeFrames(self.helmet_swim_frames)
|
||||
|
||||
@ -473,9 +476,9 @@ class Zombie(pg.sprite.Sprite):
|
||||
self.attack_timer = self.current_time
|
||||
self.animate_interval = self.attack_animate_interval
|
||||
|
||||
if self.helmet or self.helmetType2: # 这里暂时没有考虑同时有两种防具的僵尸
|
||||
if self.helmet or self.helmet_type2: # 这里暂时没有考虑同时有两种防具的僵尸
|
||||
self.changeFrames(self.helmet_attack_frames)
|
||||
elif self.lostHead:
|
||||
elif self.losthead:
|
||||
self.changeFrames(self.losthead_attack_frames)
|
||||
else:
|
||||
self.changeFrames(self.attack_frames)
|
||||
@ -558,7 +561,7 @@ class NormalZombie(Zombie):
|
||||
# 路障僵尸
|
||||
class ConeHeadZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, head_group, helmetHealth=c.CONEHEAD_HEALTH)
|
||||
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, head_group, helmet_health=c.CONEHEAD_HEALTH)
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -594,7 +597,7 @@ class ConeHeadZombie(Zombie):
|
||||
|
||||
class BucketHeadZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.BUCKETHEAD_ZOMBIE, head_group, helmetHealth=c.BUCKETHEAD_HEALTH)
|
||||
Zombie.__init__(self, x, y, c.BUCKETHEAD_ZOMBIE, head_group, helmet_health=c.BUCKETHEAD_HEALTH)
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -661,8 +664,8 @@ class FlagZombie(Zombie):
|
||||
|
||||
class NewspaperZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.NEWSPAPER_ZOMBIE, head_group, helmetType2Health=c.NEWSPAPER_HEALTH)
|
||||
self.speedUp = False
|
||||
Zombie.__init__(self, x, y, c.NEWSPAPER_ZOMBIE, head_group, helmet_type2_health=c.NEWSPAPER_HEALTH)
|
||||
self.speed_up = False
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -707,9 +710,9 @@ class NewspaperZombie(Zombie):
|
||||
if self.checkToDie(self.losthead_walk_frames):
|
||||
return
|
||||
|
||||
if self.helmetType2Health <= 0 and self.helmetType2:
|
||||
if self.helmet_type2_health <= 0 and self.helmet_type2:
|
||||
self.changeFrames(self.lostnewspaper_frames)
|
||||
self.helmetType2 = False
|
||||
self.helmet_type2 = False
|
||||
# 触发报纸撕裂音效
|
||||
c.SOUND_NEWSPAPER_RIP.play()
|
||||
if ((self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio())):
|
||||
@ -733,9 +736,9 @@ class NewspaperZombie(Zombie):
|
||||
if self.state == c.DIE:
|
||||
self.kill()
|
||||
return
|
||||
elif self.frames == self.lostnewspaper_frames and (not self.speedUp):
|
||||
elif self.frames == self.lostnewspaper_frames and (not self.speed_up):
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.speedUp = True
|
||||
self.speed_up = True
|
||||
self.speed = 2.65
|
||||
self.walk_animate_interval = 300
|
||||
# 触发报纸僵尸暴走音效
|
||||
@ -755,12 +758,12 @@ class NewspaperZombie(Zombie):
|
||||
|
||||
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)
|
||||
Zombie.__init__(self, x, y, c.FOOTBALL_ZOMBIE, head_group, helmet_health=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.losthead_animate_interval = 180
|
||||
self.die_animate_interval = 150
|
||||
|
||||
def loadImages(self):
|
||||
@ -796,7 +799,7 @@ class FootballZombie(Zombie):
|
||||
|
||||
class DuckyTubeZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.DUCKY_TUBE_ZOMBIE, head_group, canSwim=True)
|
||||
Zombie.__init__(self, x, y, c.DUCKY_TUBE_ZOMBIE, head_group, can_swim=True)
|
||||
|
||||
def loadImages(self):
|
||||
self.walk_frames = []
|
||||
@ -827,7 +830,7 @@ class DuckyTubeZombie(Zombie):
|
||||
|
||||
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)
|
||||
Zombie.__init__(self, x, y, c.CONEHEAD_DUCKY_TUBE_ZOMBIE, head_group, helmet_health=c.CONEHEAD_HEALTH ,can_swim=True)
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -865,7 +868,7 @@ class ConeHeadDuckyTubeZombie(Zombie):
|
||||
|
||||
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)
|
||||
Zombie.__init__(self, x, y, c.BUCKETHEAD_DUCKY_TUBE_ZOMBIE, head_group, helmet_health=c.BUCKETHEAD_HEALTH ,can_swim=True)
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -903,7 +906,7 @@ class BucketHeadDuckyTubeZombie(Zombie):
|
||||
|
||||
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)
|
||||
Zombie.__init__(self, x, y, c.SCREEN_DOOR_ZOMBIE, head_group, helmet_type2_health=c.SCREEN_DOOR_HEALTH)
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -939,7 +942,7 @@ class ScreenDoorZombie(Zombie):
|
||||
|
||||
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)
|
||||
Zombie.__init__(self, x, y, c.POLE_VAULTING_ZOMBIE, head_group=head_group, body_health=c.POLE_VAULTING_HEALTH, losthead_health=c.POLE_VAULTING_LOSTHEAD_HEALTH)
|
||||
self.speed = 1.88
|
||||
self.jumped = False
|
||||
self.jumping = False
|
||||
@ -975,12 +978,12 @@ class PoleVaultingZombie(Zombie):
|
||||
|
||||
self.frames = self.walk_before_jump_frames
|
||||
|
||||
def setJump(self, successfullyJumped, jumpX):
|
||||
def setJump(self, successfullyJumped, jump_x):
|
||||
if not self.jumping:
|
||||
self.jumping = True
|
||||
self.changeFrames(self.jump_frames)
|
||||
self.successfullyJumped = successfullyJumped
|
||||
self.jumpX = jumpX
|
||||
self.jump_x = jump_x
|
||||
# 播放跳跃音效
|
||||
c.SOUND_POLEVAULT_JUMP.play()
|
||||
|
||||
@ -1005,7 +1008,7 @@ class PoleVaultingZombie(Zombie):
|
||||
if self.jumping and (not self.jumped):
|
||||
self.changeFrames(self.walk_frames)
|
||||
if self.successfullyJumped:
|
||||
self.rect.centerx = self.jumpX
|
||||
self.rect.centerx = self.jump_x
|
||||
self.jumped = True
|
||||
self.speed = 1.04
|
||||
self.animate_timer = self.current_time
|
||||
@ -1043,7 +1046,7 @@ class PoleVaultingZombie(Zombie):
|
||||
# 注意:冰车僵尸移动变速
|
||||
class Zomboni(Zombie):
|
||||
def __init__(self, x, y, plant_group, map, IceFrozenPlot):
|
||||
Zombie.__init__(self, x, y, c.ZOMBONI, bodyHealth=c.ZOMBONI_HEALTH)
|
||||
Zombie.__init__(self, x, y, c.ZOMBONI, body_health=c.ZOMBONI_HEALTH)
|
||||
self.plant_group = plant_group
|
||||
self.map = map
|
||||
self.IceFrozenPlot = IceFrozenPlot
|
||||
@ -1095,7 +1098,7 @@ class Zomboni(Zombie):
|
||||
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()) and (not self.lostHead):
|
||||
if (self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio()) and (not self.losthead):
|
||||
self.walk_timer = self.current_time
|
||||
if self.is_hypno:
|
||||
self.rect.x += 1
|
||||
@ -1111,14 +1114,14 @@ class Zomboni(Zombie):
|
||||
plant.health -= 8000
|
||||
|
||||
# 造冰
|
||||
mapX, mapY = self.map.getMapIndex(self.rect.right - 40, self.rect.bottom)
|
||||
if 0 <= mapX < c.GRID_X_LEN:
|
||||
if c.ICEFROZENPLOT not in self.map.map[mapY][mapX]:
|
||||
x, y = self.map.getMapGridPos(mapX, mapY)
|
||||
map_x, map_y = self.map.getMapIndex(self.rect.right - 40, self.rect.bottom)
|
||||
if 0 <= map_x < c.GRID_X_LEN:
|
||||
if c.ICEFROZENPLOT not in self.map.map[map_y][map_x]:
|
||||
x, y = self.map.getMapGridPos(map_x, map_y)
|
||||
self.plant_group.add(self.IceFrozenPlot(x, y))
|
||||
self.map.map[mapY][mapX][c.MAP_PLANT].add(c.ICEFROZENPLOT)
|
||||
self.map.map[map_y][map_x][c.MAP_PLANT].add(c.ICEFROZENPLOT)
|
||||
|
||||
self.speed = max(0.6, 1.5 - (c.GRID_X_LEN + 1 - mapX)*0.225)
|
||||
self.speed = max(0.6, 1.5 - (c.GRID_X_LEN + 1 - map_x)*0.225)
|
||||
|
||||
def setDie(self):
|
||||
self.state = c.DIE
|
||||
@ -1130,7 +1133,7 @@ class Zomboni(Zombie):
|
||||
|
||||
class SnorkelZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.SNORKELZOMBIE, canSwim=True)
|
||||
Zombie.__init__(self, x, y, c.SNORKELZOMBIE, can_swim=True)
|
||||
self.speed = 1.175
|
||||
self.walk_animate_interval = 60
|
||||
self.canSetAttack = True
|
||||
@ -1250,7 +1253,7 @@ class SnorkelZombie(Zombie):
|
||||
self.prey_is_plant = is_plant
|
||||
self.animate_interval = self.attack_animate_interval
|
||||
|
||||
if self.lostHead:
|
||||
if self.losthead:
|
||||
self.changeFrames(self.losthead_attack_frames)
|
||||
elif self.canSetAttack:
|
||||
self.changeFrames(self.float_frames)
|
||||
|
||||
@ -71,6 +71,7 @@ PARCHMENT_YELLOW = (207, 146, 83)
|
||||
|
||||
# 退出游戏按钮
|
||||
EXIT = "exit"
|
||||
HELP = "help"
|
||||
# 游戏界面可选的菜单
|
||||
LITTLE_MENU = "littleMenu"
|
||||
BIG_MENU = "bigMenu"
|
||||
@ -110,6 +111,7 @@ GAME_LOSE = "game lose"
|
||||
GAME_VICTORY = "game victory"
|
||||
LEVEL = "level"
|
||||
AWARD_SCREEN = "award screen"
|
||||
HELP_SCREEN = "help screen"
|
||||
|
||||
# 界面图片文件名
|
||||
MAIN_MENU_IMAGE = "MainMenu"
|
||||
@ -117,6 +119,7 @@ OPTION_ADVENTURE = "Adventure"
|
||||
GAME_LOSE_IMAGE = "GameLose"
|
||||
GAME_VICTORY_IMAGE = "GameVictory"
|
||||
AWARD_SCREEN_IMAGE = "AwardScreen"
|
||||
HELP_SCREEN_IMAGE = "HelpScreen"
|
||||
|
||||
# 地图相关内容
|
||||
BACKGROUND_NAME = "Background"
|
||||
@ -166,8 +169,8 @@ GRAVES_GRADE_INFO = (0, 4, 7, 11)
|
||||
|
||||
# 僵尸生成方式
|
||||
SPAWN_ZOMBIES = "spawn_zombies"
|
||||
SPAWN_ZOMBIES_AUTO = "auto"
|
||||
SPAWN_ZOMBIES_LIST = "list"
|
||||
SPAWN_ZOMBIES_AUTO = 1
|
||||
SPAWN_ZOMBIES_LIST = 0
|
||||
INCLUDED_ZOMBIES = "included_zombies"
|
||||
NUM_FLAGS = "num_flags"
|
||||
INEVITABLE_ZOMBIE_DICT = "inevitable_zombie_list"
|
||||
@ -302,7 +305,7 @@ PLANT_CARD_INFO = (# 元组 (植物名称, 卡片名称, 阳光, 冷却时间)
|
||||
50000),
|
||||
(DOOMSHROOM := "DoomShroom",
|
||||
CARD_DOOMSHROOM := "card_doomshroom",
|
||||
75,
|
||||
125,
|
||||
50000),
|
||||
(LILYPAD := "LilyPad",
|
||||
CARD_LILYPAD := "card_lilypad",
|
||||
@ -509,8 +512,7 @@ SNORKELZOMBIE = "SnorkelZombie"
|
||||
BOOMDIE = "BoomDie"
|
||||
|
||||
# 对僵尸的攻击类型设置
|
||||
ZOMBIE_DEAFULT_DAMAGE = "helmet2First"
|
||||
ZOMBIE_HELMET_2_FIRST = "helmet2First" # 优先攻击二类防具
|
||||
ZOMBIE_DEAFULT_DAMAGE = ZOMBIE_HELMET_2_FIRST = "helmet2First" # 优先攻击二类防具
|
||||
ZOMBIE_COMMON_DAMAGE = "commonDamage" # 优先攻击僵尸与一类防具的整体
|
||||
ZOMBIE_RANGE_DAMAGE = "rangeDamage" # 范围攻击,同时伤害二类防具与(僵尸与一类防具的整体)
|
||||
ZOMBIE_ASH_DAMAGE = "ashDamage" # 灰烬植物攻击,直接伤害本体
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -37,23 +37,27 @@ class Menu(tool.State):
|
||||
|
||||
def setupOptions(self):
|
||||
# 冒险模式
|
||||
self.adventure_frames = []
|
||||
frame_names = (f"{c.OPTION_ADVENTURE}_0", f"{c.OPTION_ADVENTURE}_1")
|
||||
frame_rect = (0, 0, 330, 144)
|
||||
for name in frame_names:
|
||||
self.adventure_frames.append(tool.get_image_menu(tool.GFX[name], *frame_rect, c.BLACK, 1))
|
||||
# 写成列表生成器方便IDE识别与自动补全
|
||||
self.adventure_frames = [tool.get_image_alpha(tool.GFX[f"{c.OPTION_ADVENTURE}_{i}"], *frame_rect) for i in range(2)]
|
||||
self.adventure_image = self.adventure_frames[0]
|
||||
self.adventure_rect = self.adventure_image.get_rect()
|
||||
self.adventure_rect.x = 400
|
||||
self.adventure_rect.y = 60
|
||||
self.adventure_highlight_time = 0
|
||||
|
||||
# 小游戏
|
||||
littleGame_frame_rect = (0, 7, 317, 135)
|
||||
self.littleGame_frames = [tool.get_image_alpha(tool.GFX[f"{c.LITTLEGAME_BUTTON}_{i}"], *littleGame_frame_rect) for i in range(2)]
|
||||
self.littleGame_image = self.littleGame_frames[0]
|
||||
self.littleGame_rect = self.littleGame_image.get_rect()
|
||||
self.littleGame_rect.x = 397
|
||||
self.littleGame_rect.y = 175
|
||||
self.littleGame_highlight_time = 0
|
||||
|
||||
# 退出按钮
|
||||
self.exit_frames = []
|
||||
exit_frame_names = (f"{c.EXIT}_0", f"{c.EXIT}_1")
|
||||
exit_frame_rect = (0, 0, 47, 27)
|
||||
for name in exit_frame_names:
|
||||
self.exit_frames.append(tool.get_image_menu(tool.GFX[name], *exit_frame_rect, c.BLACK, 1.1))
|
||||
self.exit_frames = [tool.get_image_alpha(tool.GFX[f"{c.EXIT}_{i}"], *exit_frame_rect, scale=1.1) for i in range(2)]
|
||||
self.exit_image = self.exit_frames[0]
|
||||
self.exit_rect = self.exit_image.get_rect()
|
||||
self.exit_rect.x = 730
|
||||
@ -61,29 +65,24 @@ class Menu(tool.State):
|
||||
self.exit_highlight_time = 0
|
||||
|
||||
# 选项按钮
|
||||
self.option_button_frames = []
|
||||
option_button_frame_names = (f"{c.OPTION_BUTTON}_0", f"{c.OPTION_BUTTON}_1")
|
||||
option_button_frame_rect = (0, 0, 81, 31)
|
||||
for name in option_button_frame_names:
|
||||
self.option_button_frames.append(tool.get_image_menu(tool.GFX[name], *option_button_frame_rect, c.BLACK))
|
||||
self.option_button_frames = [tool.get_image_alpha(tool.GFX[f"{c.OPTION_BUTTON}_{i}"], *option_button_frame_rect) for i in range(2)]
|
||||
self.option_button_image = self.option_button_frames[0]
|
||||
self.option_button_rect = self.option_button_image.get_rect()
|
||||
self.option_button_rect.x = 560
|
||||
self.option_button_rect.y = 490
|
||||
self.option_button_hightlight_time = 0
|
||||
self.option_button_highlight_time = 0
|
||||
|
||||
# 小游戏
|
||||
self.littleGame_frames = []
|
||||
littleGame_frame_names = (c.LITTLEGAME_BUTTON + "_0", c.LITTLEGAME_BUTTON + "_1")
|
||||
littleGame_frame_rect = (0, 7, 317, 135)
|
||||
for name in littleGame_frame_names:
|
||||
self.littleGame_frames.append(tool.get_image_menu(tool.GFX[name], *littleGame_frame_rect, c.BLACK, 1))
|
||||
self.littleGame_image = self.littleGame_frames[0]
|
||||
self.littleGame_rect = self.littleGame_image.get_rect()
|
||||
self.littleGame_rect.x = 397
|
||||
self.littleGame_rect.y = 175
|
||||
self.littleGame_highlight_time = 0
|
||||
# 帮助菜单
|
||||
help_frame_rect = (0, 0, 48, 22)
|
||||
self.help_frames = [tool.get_image_alpha(tool.GFX[f"{c.HELP}_{i}"], *help_frame_rect) for i in range(2)]
|
||||
self.help_image = self.help_frames[0]
|
||||
self.help_rect = self.help_image.get_rect()
|
||||
self.help_rect.x = 653
|
||||
self.help_rect.y = 520
|
||||
self.help_hilight_time = 0
|
||||
|
||||
# 计时器与点击信号记录器
|
||||
self.adventure_start = 0
|
||||
self.adventure_timer = 0
|
||||
self.adventure_clicked = False
|
||||
@ -93,21 +92,25 @@ class Menu(tool.State):
|
||||
# 高亮冒险模式按钮
|
||||
if self.inArea(self.adventure_rect, x, y):
|
||||
self.adventure_highlight_time = self.current_time
|
||||
# 高亮小游戏按钮
|
||||
elif self.inArea(self.littleGame_rect, x, y):
|
||||
self.littleGame_highlight_time = self.current_time
|
||||
# 高亮退出按钮
|
||||
elif self.inArea(self.exit_rect, x, y):
|
||||
self.exit_highlight_time = self.current_time
|
||||
# 高亮选项按钮
|
||||
elif self.inArea(self.option_button_rect, x, y):
|
||||
self.option_button_hightlight_time = self.current_time
|
||||
# 高亮小游戏按钮
|
||||
elif self.inArea(self.littleGame_rect, x, y):
|
||||
self.littleGame_highlight_time = self.current_time
|
||||
self.option_button_highlight_time = self.current_time
|
||||
# 高亮帮助按钮
|
||||
elif self.inArea(self.help_rect, x, y):
|
||||
self.help_hilight_time = self.current_time
|
||||
|
||||
# 处理按钮高亮情况
|
||||
self.adventure_image = self.chooseHilightImage(self.adventure_highlight_time, self.adventure_frames)
|
||||
self.exit_image = self.chooseHilightImage(self.exit_highlight_time, self.exit_frames)
|
||||
self.option_button_image = self.chooseHilightImage(self.option_button_hightlight_time, self.option_button_frames)
|
||||
self.option_button_image = self.chooseHilightImage(self.option_button_highlight_time, self.option_button_frames)
|
||||
self.littleGame_image = self.chooseHilightImage(self.littleGame_highlight_time, self.littleGame_frames)
|
||||
self.help_image = self.chooseHilightImage(self.help_hilight_time, self.help_frames)
|
||||
|
||||
def chooseHilightImage(self, hilightTime, frames):
|
||||
if (self.current_time - hilightTime) < 80:
|
||||
@ -116,9 +119,7 @@ class Menu(tool.State):
|
||||
index = 0
|
||||
return frames[index]
|
||||
|
||||
def checkAdventureClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if self.inArea(self.adventure_rect, x, y):
|
||||
def respondAdventureClick(self):
|
||||
self.adventure_clicked = True
|
||||
self.adventure_timer = self.adventure_start = self.current_time
|
||||
self.persist[c.GAME_MODE] = c.MODE_ADVENTURE
|
||||
@ -126,26 +127,27 @@ class Menu(tool.State):
|
||||
c.SOUND_EVILLAUGH.play()
|
||||
c.SOUND_LOSE.play()
|
||||
|
||||
# 点击到按钮,修改转态的done属性
|
||||
def checkExitClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if self.inArea(self.exit_rect, x, y):
|
||||
self.done = True
|
||||
self.next = c.EXIT
|
||||
|
||||
# 检查有没有按到小游戏
|
||||
def checkLittleGameClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if self.inArea(self.littleGame_rect, x, y):
|
||||
# 按到小游戏
|
||||
def respondLittleGameClick(self):
|
||||
self.done = True
|
||||
self.persist[c.GAME_MODE] = c.MODE_LITTLEGAME
|
||||
# 播放点击音效
|
||||
c.SOUND_BUTTON_CLICK.play()
|
||||
|
||||
# 点击到退出按钮,修改转态的done属性
|
||||
def respondExitClick(self):
|
||||
self.done = True
|
||||
self.next = c.EXIT
|
||||
|
||||
# 帮助按钮点击
|
||||
def respondHelpClick(self):
|
||||
self.done = True
|
||||
self.next = c.HELP_SCREEN
|
||||
|
||||
def setupOptionMenu(self):
|
||||
# 选项菜单框
|
||||
frame_rect = (0, 0, 500, 500)
|
||||
self.big_menu = tool.get_image_menu(tool.GFX[c.BIG_MENU], *frame_rect, c.BLACK, 1.1)
|
||||
self.big_menu = tool.get_image_alpha(tool.GFX[c.BIG_MENU], *frame_rect, c.BLACK, 1.1)
|
||||
self.big_menu_rect = self.big_menu.get_rect()
|
||||
self.big_menu_rect.x = 150
|
||||
self.big_menu_rect.y = 0
|
||||
@ -170,7 +172,7 @@ class Menu(tool.State):
|
||||
font = pg.font.Font(c.FONT_PATH, 35)
|
||||
font.bold = True
|
||||
# 音量+
|
||||
self.sound_volume_plus_button = tool.get_image_menu(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
self.sound_volume_plus_button = tool.get_image_alpha(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
sign = font.render("+", True, c.YELLOWGREEN)
|
||||
sign_rect = sign.get_rect()
|
||||
sign_rect.x = 8
|
||||
@ -179,7 +181,7 @@ class Menu(tool.State):
|
||||
self.sound_volume_plus_button_rect = self.sound_volume_plus_button.get_rect()
|
||||
self.sound_volume_plus_button_rect.x = 500
|
||||
# 音量-
|
||||
self.sound_volume_minus_button = tool.get_image_menu(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
self.sound_volume_minus_button = tool.get_image_alpha(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
sign = font.render("-", True, c.YELLOWGREEN)
|
||||
sign_rect = sign.get_rect()
|
||||
sign_rect.x = 12
|
||||
@ -197,7 +199,7 @@ class Menu(tool.State):
|
||||
frame_rect = (157, 0, 157, 269)
|
||||
else:
|
||||
frame_rect = (0, 0, 157, 269)
|
||||
self.sunflower_trophy = tool.get_image_menu(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, c.BLACK)
|
||||
self.sunflower_trophy = tool.get_image_alpha(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, c.BLACK)
|
||||
self.sunflower_trophy_rect = self.sunflower_trophy.get_rect()
|
||||
self.sunflower_trophy_rect.x = 0
|
||||
self.sunflower_trophy_rect.y = 280
|
||||
@ -216,13 +218,11 @@ class Menu(tool.State):
|
||||
infoText = f"目前您一共完成了:玩玩小游戏{self.game_info[c.LITTLEGAME_COMPLETIONS]}轮;完成其他所有游戏模式以获得金向日葵奖杯!"
|
||||
infoImg = font.render(infoText , True, c.BLACK, c.LIGHTYELLOW)
|
||||
infoImg_rect = infoImg.get_rect()
|
||||
infoImg_rect.x = x
|
||||
infoImg_rect.y = y
|
||||
infoImg_rect.x = self.sunflower_trophy_rect.x
|
||||
infoImg_rect.y = self.sunflower_trophy_rect.bottom - 14
|
||||
surface.blit(infoImg, infoImg_rect)
|
||||
|
||||
def checkOptionButtonClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if self.inArea(self.option_button_rect, x, y):
|
||||
def respondOptionButtonClick(self):
|
||||
self.option_button_clicked = True
|
||||
# 播放点击音效
|
||||
c.SOUND_BUTTON_CLICK.play()
|
||||
@ -241,9 +241,10 @@ class Menu(tool.State):
|
||||
|
||||
surface.blit(self.bg_image, self.bg_rect)
|
||||
surface.blit(self.adventure_image, self.adventure_rect)
|
||||
surface.blit(self.littleGame_image, self.littleGame_rect)
|
||||
surface.blit(self.exit_image, self.exit_rect)
|
||||
surface.blit(self.option_button_image, self.option_button_rect)
|
||||
surface.blit(self.littleGame_image, self.littleGame_rect)
|
||||
surface.blit(self.help_image, self.help_rect)
|
||||
if self.game_info[c.LEVEL_COMPLETIONS] or self.game_info[c.LITTLEGAME_COMPLETIONS]:
|
||||
surface.blit(self.sunflower_trophy, self.sunflower_trophy_rect)
|
||||
|
||||
@ -294,7 +295,13 @@ class Menu(tool.State):
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] or self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
self.checkSunflowerTrophyInfo(surface, x, y)
|
||||
if mouse_pos:
|
||||
self.checkExitClick(mouse_pos)
|
||||
self.checkOptionButtonClick(mouse_pos)
|
||||
self.checkLittleGameClick(mouse_pos)
|
||||
self.checkAdventureClick(mouse_pos)
|
||||
if self.inArea(self.adventure_rect, *mouse_pos):
|
||||
self.respondAdventureClick()
|
||||
elif self.inArea(self.littleGame_rect, *mouse_pos):
|
||||
self.respondLittleGameClick()
|
||||
elif self.inArea(self.option_button_rect, *mouse_pos):
|
||||
self.respondOptionButtonClick()
|
||||
elif self.inArea(self.exit_rect, *mouse_pos):
|
||||
self.respondExitClick()
|
||||
elif self.inArea(self.help_rect, *mouse_pos):
|
||||
self.respondHelpClick()
|
||||
|
||||
@ -20,7 +20,7 @@ class Screen(tool.State):
|
||||
# 按钮
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_menu(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 620
|
||||
### 主菜单按钮上的文字
|
||||
@ -29,7 +29,7 @@ class Screen(tool.State):
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
## 继续按钮
|
||||
self.next_button_image = tool.get_image_menu(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image_rect = self.next_button_image.get_rect()
|
||||
self.next_button_image_rect.x = 70
|
||||
### 继续按钮上的文字
|
||||
@ -116,7 +116,7 @@ class AwardScreen(tool.State):
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
if self.show_only_one_option:
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_menu(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 343
|
||||
self.main_menu_button_image_rect.y = 520
|
||||
@ -127,32 +127,7 @@ class AwardScreen(tool.State):
|
||||
main_menu_text_rect.x = 29
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
else:
|
||||
## 继续按钮
|
||||
self.next_button_image = tool.get_image_menu(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image_rect = self.next_button_image.get_rect()
|
||||
self.next_button_image_rect.x = 70
|
||||
### 继续按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
next_text = font.render("继续", True, c.NAVYBLUE)
|
||||
next_text_rect = next_text.get_rect()
|
||||
next_text_rect.x = 37
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_menu(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 620
|
||||
self.next_button_image_rect.y = self.main_menu_button_image_rect.y = 540
|
||||
### 主菜单按钮上的文字
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.next_button_image.blit(next_text, next_text_rect)
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.next_button_image, self.next_button_image_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
# 显示向日葵奖杯的情况
|
||||
if self.show_only_one_option:
|
||||
# 绘制向日葵奖杯
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] and self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
frame_rect = (157, 0, 157, 269)
|
||||
@ -165,7 +140,7 @@ class AwardScreen(tool.State):
|
||||
intro_content = "您已完成冒险模式,获得此奖励!"
|
||||
else:
|
||||
intro_content = "您已完成玩玩小游戏,获得此奖励!"
|
||||
sunflower_trophy_image = tool.get_image_menu(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, scale=0.7)
|
||||
sunflower_trophy_image = tool.get_image_alpha(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, scale=0.7)
|
||||
sunflower_trophy_rect = sunflower_trophy_image.get_rect()
|
||||
sunflower_trophy_rect.x = 348
|
||||
sunflower_trophy_rect.y = 108
|
||||
@ -186,7 +161,29 @@ class AwardScreen(tool.State):
|
||||
intro_content_rect.x = 290
|
||||
intro_content_rect.y = 370
|
||||
self.image.blit(intro_content_img, intro_content_rect)
|
||||
|
||||
else:
|
||||
## 继续按钮
|
||||
self.next_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image_rect = self.next_button_image.get_rect()
|
||||
self.next_button_image_rect.x = 70
|
||||
### 继续按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
next_text = font.render("继续", True, c.NAVYBLUE)
|
||||
next_text_rect = next_text.get_rect()
|
||||
next_text_rect.x = 37
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 620
|
||||
self.next_button_image_rect.y = self.main_menu_button_image_rect.y = 540
|
||||
### 主菜单按钮上的文字
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.next_button_image.blit(next_text, next_text_rect)
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.next_button_image, self.next_button_image_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
@ -214,3 +211,46 @@ class AwardScreen(tool.State):
|
||||
if self.inArea(self.next_button_image_rect, *mouse_pos):
|
||||
self.next = c.LEVEL
|
||||
self.done = True
|
||||
|
||||
class HelpScreen(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
self.setupImage()
|
||||
pg.display.set_caption("pypvz: 帮助")
|
||||
pg.mixer.music.stop()
|
||||
|
||||
def setupImage(self):
|
||||
# 主体
|
||||
frame_rect = (-100, -50, 800, 600)
|
||||
self.image = tool.get_image(tool.GFX[c.HELP_SCREEN_IMAGE], *frame_rect, colorkey=(0, 255, 255))
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
|
||||
# 主菜单按钮
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 343
|
||||
self.main_menu_button_image_rect.y = 500
|
||||
### 主菜单按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
surface.fill(c.BLACK)
|
||||
surface.blit(self.image, self.rect)
|
||||
if mouse_pos:
|
||||
# 检查主菜单点击
|
||||
if self.inArea(self.main_menu_button_image_rect, *mouse_pos):
|
||||
self.next = c.MAIN_MENU
|
||||
self.done = True
|
||||
|
||||
@ -5,7 +5,7 @@ import pygame as pg
|
||||
from pygame.locals import *
|
||||
from . import constants as c
|
||||
|
||||
# an abstract class, one state of automata
|
||||
# 状态机 抽象基类
|
||||
class State():
|
||||
def __init__(self):
|
||||
self.start_time = 0
|
||||
@ -17,7 +17,7 @@ class State():
|
||||
# 当从其他状态进入这个状态时,需要进行的初始化操作
|
||||
@abstractmethod
|
||||
def startup(self, current_time, persist):
|
||||
# abstract method
|
||||
# 前面加了@abstractmethod表示抽象基类中必须要重新定义的method(method是对象和函数的结合)
|
||||
pass
|
||||
# 当从这个状态退出时,需要进行的清除操作
|
||||
def cleanup(self):
|
||||
@ -26,7 +26,7 @@ class State():
|
||||
# 在这个状态运行时进行的更新操作
|
||||
@abstractmethod
|
||||
def update(self, surface, keys, current_time):
|
||||
# abstract method
|
||||
# 前面加了@abstractmethod表示抽象基类中必须要重新定义的method
|
||||
pass
|
||||
|
||||
# 工具:范围判断函数,用于判断点击
|
||||
@ -47,7 +47,7 @@ class State():
|
||||
data_to_save = json.dumps(userdata, sort_keys=True, indent=4)
|
||||
f.write(data_to_save)
|
||||
|
||||
# control this game. do event loops
|
||||
# 进行游戏控制 循环 事件响应
|
||||
class Control():
|
||||
def __init__(self):
|
||||
self.screen = pg.display.get_surface()
|
||||
@ -100,7 +100,7 @@ class Control():
|
||||
self.state.startup(self.current_time, self.game_info)
|
||||
|
||||
def update(self):
|
||||
# 返回自 pygame_init() 调用以来的毫秒数 * 游戏速度倍率
|
||||
# 自 pygame_init() 调用以来的毫秒数 * 游戏速度倍率,即游戏时间
|
||||
self.current_time = pg.time.get_ticks() * self.game_info[c.GAME_RATE]
|
||||
|
||||
if self.state.done:
|
||||
@ -116,7 +116,6 @@ class Control():
|
||||
if self.state.next == c.EXIT:
|
||||
pg.quit()
|
||||
os._exit(0)
|
||||
# previous, self.state_name = self.state_name, self.state.next
|
||||
self.state_name = self.state.next
|
||||
persist = self.state.cleanup()
|
||||
self.state = self.state_dict[self.state_name]
|
||||
@ -162,7 +161,7 @@ def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
||||
int(rect.height*scale)))
|
||||
return image
|
||||
|
||||
def get_image_menu(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
||||
def get_image_alpha(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
||||
# 保留alpha通道的图片导入
|
||||
image = pg.Surface([width, height], SRCALPHA)
|
||||
rect = image.get_rect()
|
||||
@ -198,7 +197,7 @@ def load_image_frames(directory, image_name, colorkey, accept):
|
||||
return frame_list
|
||||
|
||||
# colorkeys 是设置图像中的某个颜色值为透明,这里用来消除白边
|
||||
def load_all_gfx(directory, colorkey=c.WHITE, accept=(".png", ".jpg", ".bmp", ".gif", "webp")):
|
||||
def load_all_gfx(directory, colorkey=c.WHITE, accept=(".png", ".jpg", ".bmp", ".gif", ".webp")):
|
||||
graphics = {}
|
||||
for name1 in os.listdir(directory):
|
||||
# subfolders under the folder resources\graphics
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user