维护清理

This commit is contained in:
星外之神 2022-05-15 14:15:48 +08:00
parent 25bf28e4f4
commit cd32e142e0
4 changed files with 99 additions and 63 deletions

View File

@ -9,11 +9,11 @@ class Map():
self.background_type = background_type
# 注意从0开始编号
# 集合内容需要deepcopy
if self.background_type in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
self.width = c.GRID_POOL_X_LEN
self.height = c.GRID_POOL_Y_LEN
self.map = [[(deepcopy(c.MAP_STATE_EMPTY), deepcopy(c.MAP_STATE_WATER))[y in {2, 3}] for x in range(self.width)] for y in range(self.height)]
elif self.background_type in {c.BACKGROUND_ROOF, c.BACKGROUND_ROOFNIGHT}:
elif self.background_type in c.ON_ROOF_BACKGROUNDS:
self.width = c.GRID_ROOF_X_LEN
self.height = c.GRID_ROOF_Y_LEN
self.map = [[deepcopy(c.MAP_STATE_TILE) for x in range(self.width)] for y in range(self.height)]
@ -52,11 +52,11 @@ class Map():
return True
else:
return False
if any((i in {c.HOLE, c.ICE_FROZEN_PLOT, c.GRAVE}) for i in self.map[map_y][map_x][c.MAP_PLANT]):
if any((i in c.NON_PLANT_OBJECTS) for i in self.map[map_y][map_x][c.MAP_PLANT]):
return False
if self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_GRASS: # 草地
# 首先需要判断植物是否是水生植物,水生植物不能种植在陆地上
if plantName not in {c.LILYPAD, c.SEASHROOM, c.TANGLEKLEP}: # 这里的集合也可以换成存储在某一文件中的常数的表达
if plantName not in c.WATER_PLANTS:
if not self.map[map_y][map_x][c.MAP_PLANT]: # 没有植物肯定可以种植
return True
elif (all((i in {'花盆(未实现)', '南瓜头(未实现)'}) for i in self.map[map_y][map_x][c.MAP_PLANT])
@ -68,7 +68,7 @@ class Map():
return False
elif self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_TILE: # 屋顶
# 首先需要判断植物是否是水生植物,水生植物不能种植在陆地上
if plantName not in {c.LILYPAD, c.SEASHROOM, c.TANGLEKLEP}: # 这里的集合也可以换成存储在某一文件中的常数的表达
if plantName not in c.WATER_PLANTS:
if '花盆(未实现)' in self.map[map_y][map_x][c.MAP_PLANT]:
if (all((i in {'花盆(未实现)', '南瓜头(未实现)'}) 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])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植;判断方法:并集
@ -83,7 +83,7 @@ class Map():
else:
return False
elif self.map[map_y][map_x][c.MAP_PLOT_TYPE] == c.MAP_WATER: # 水里
if plantName in {c.LILYPAD, c.SEASHROOM, c.TANGLEKLEP}: # 是水生植物
if plantName in c.WATER_PLANTS: # 是水生植物
if not self.map[map_y][map_x][c.MAP_PLANT]: # 只有无植物时才能在水里种植水生植物
return True
else:
@ -92,7 +92,7 @@ class Map():
if c.LILYPAD in self.map[map_y][map_x][c.MAP_PLANT]:
if (all((i in {c.LILYPAD, '南瓜头(未实现)'}) 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,'花盆(未实现)'}: # 不能在睡莲上种植的植物
if plantName in {c.SPIKEWEED, c.POTATOMINE, '花盆(未实现)'}: # 不能在睡莲上种植的植物
return False
else:
return True
@ -105,11 +105,11 @@ class Map():
def getMapIndex(self, x, y):
# 引入新地图后需要增加这里的内容
if self.background_type in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
x -= c.MAP_POOL_OFFSET_X
y -= c.MAP_POOL_OFFSET_Y
return (x // c.GRID_POOL_X_SIZE, y // c.GRID_POOL_Y_SIZE)
elif self.background_type in {c.BACKGROUND_ROOF, c.BACKGROUND_ROOFNIGHT}:
elif self.background_type in c.ON_ROOF_BACKGROUNDS:
x -= c.MAP_ROOF_OFFSET_X
y -= c.MAP_ROOF_OFFSET_X
gridX = x // c.GRID_ROOF_X_SIZE
@ -124,10 +124,10 @@ class Map():
return (x // c.GRID_X_SIZE, y // c.GRID_Y_SIZE)
def getMapGridPos(self, map_x, map_y):
if self.background_type in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
return (map_x * c.GRID_POOL_X_SIZE + c.GRID_POOL_X_SIZE//2 + c.MAP_POOL_OFFSET_X,
map_y * c.GRID_POOL_Y_SIZE + c.GRID_POOL_Y_SIZE//5 * 3 + c.MAP_POOL_OFFSET_Y)
elif self.background_type in {c.BACKGROUND_ROOF, c.BACKGROUND_ROOFNIGHT}:
elif self.background_type in c.ON_ROOF_BACKGROUNDS:
return (map_x * c.GRID_ROOF_X_SIZE + c.GRID_ROOF_X_SIZE//2 + c.MAP_ROOF_OFFSET_X,
map_y * c.GRID_ROOF_Y_SIZE + 20 * max(0, (6 - map_y)) + c.GRID_ROOF_Y_SIZE//5 * 3 + c.MAP_POOL_OFFSET_Y)
else:

View File

@ -467,7 +467,7 @@ class ThreePeaShooter(Plant):
offset_y = 9 # modify bullet in the same y position with bullets of other plants
for i in range(3):
tmp_y = self.map_y + (i - 1)
if self.background_type in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
if tmp_y < 0 or tmp_y >= c.GRID_POOL_Y_LEN:
continue
else:

View File

@ -104,6 +104,19 @@ BACKGROUND_WALLNUTBOWLING = 6
BACKGROUND_SINGLE = 7
BACKGROUND_TRIPLE = 8
# 地图类型集合
# 白天场地
DAYTIME_BACKGROUNDS = { BACKGROUND_DAY, BACKGROUND_POOL,
BACKGROUND_ROOF, BACKGROUND_WALLNUTBOWLING,
BACKGROUND_SINGLE, BACKGROUND_TRIPLE,
}
# 带有泳池的场地
POOL_EQUIPPED_BACKGROUNDS = { BACKGROUND_POOL, BACKGROUND_FOG,
}
# 屋顶上的场地
ON_ROOF_BACKGROUNDS = { BACKGROUND_ROOF, BACKGROUND_ROOFNIGHT,
}
# 夜晚地图的墓碑数量等级
GRADE_GRAVES = 'grade_graves'
GRADE0_GRAVES = 0 # 无墓碑
@ -218,6 +231,60 @@ GRAVE = 'Grave'
GRAVEBUSTER = 'GraveBuster'
FUMESHROOM = 'FumeShroom'
# 植物集体属性
# 在生效时不用与僵尸进行碰撞检测的对象
SKIP_ZOMBIE_COLLISION_CHECK_WHEN_WORKING = {# 注意爆炸坚果的触发也是啃食类碰撞,因此这里不能省略
SQUASH, ICESHROOM,
REDWALLNUTBOWLING, CHERRYBOMB,
JALAPENO, DOOMSHROOM,
POTATOMINE,
}
# 非植物对象
NON_PLANT_OBJECTS = { HOLE, ICE_FROZEN_PLOT,
GRAVE,
}
# 所有可能不用与僵尸进行碰撞检测的对象
CAN_SKIP_ZOMBIE_COLLISION_CHECK = ( # 生效时不检测的植物
SKIP_ZOMBIE_COLLISION_CHECK_WHEN_WORKING |
# 非植物对象
NON_PLANT_OBJECTS |
# 地刺类
{SPIKEWEED, }
)
# 死亡时不触发音效的对象
PLANT_DIE_SOUND_EXCEPTIONS = { WALLNUTBOWLING, TANGLEKLEP,
ICE_FROZEN_PLOT, HOLE,
GRAVE, JALAPENO,
REDWALLNUTBOWLING, CHERRYBOMB,
}
# color_key为白色的对象
PLANT_COLOR_KEY_WHITE = { POTATOMINE, SPIKEWEED,
JALAPENO, SCAREDYSHROOM,
SUNSHROOM, ICESHROOM,
HYPNOSHROOM, SQUASH,
WALLNUTBOWLING, REDWALLNUTBOWLING,
}
# 直接水生植物
WATER_PLANTS = { LILYPAD, SEASHROOM,
TANGLEKLEP,
}
# 不用使用通用方法检验攻击状态的植物
PLANT_NON_CHECK_ATTACK_STATE = ({ # 单独指定攻击状态的植物
WALLNUTBOWLING,
# 没有攻击状态的植物
WALLNUT, TALLNUT,
TORCHWOOD, SUNFLOWER,
SUNSHROOM, COFFEEBEAN,
GRAVEBUSTER, LILYPAD,
HYPNOSHROOM,
} |
# 非植物类
NON_PLANT_OBJECTS
)
# 范围爆炸植物,即灰烬植物与寒冰菇
ASH_PLANTS_AND_ICESHROOM = { REDWALLNUTBOWLING, CHERRYBOMB,
JALAPENO, DOOMSHROOM,
ICESHROOM,}
# 植物生命值
PLANT_HEALTH = 300
@ -316,6 +383,12 @@ ZOMBONI = 'Zomboni'
BOOMDIE = 'BoomDie'
# 僵尸集体属性
# 水上僵尸集合
WATER_ZOMBIE = { DUCKY_TUBE_ZOMBIE, CONEHEAD_DUCKY_TUBE_ZOMBIE,
BUCKETHEAD_DUCKY_TUBE_ZOMBIE,
}
# 对僵尸的攻击类型设置
ZOMBIE_DEAFULT_DAMAGE = 'helmet2First'
ZOMBIE_HELMET_2_FIRST = 'helmet2First' # 优先攻击二类防具

View File

@ -149,7 +149,7 @@ class Level(tool.State):
while (volume >= minCost) and (len(zombieList) < 50):
newZombie = choices(useableZombies, weights)[0]
# 普通僵尸、路障僵尸、铁桶僵尸有概率生成水中变种
if self.background_type in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
# 有泳池第一轮的第四波设定上生成水生僵尸
if survivalRounds == 0 and wave == 4:
if newZombie in self.convertZombieInPool:
@ -226,7 +226,7 @@ class Level(tool.State):
else:
self.zombie_groups[item[1]].add(zombie.ConeHeadZombie(itemX, itemY, self.head_group))
self.graveZombieCreated = True
elif self.map_data[c.BACKGROUND_TYPE] in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
elif self.map_data[c.BACKGROUND_TYPE] in c.POOL_EQUIPPED_BACKGROUNDS:
if not self.createdZombieFromPool:
if current_time - self.waveTime > 1500:
for i in range(3):
@ -637,7 +637,7 @@ class Level(tool.State):
for i in self.plant_groups[map_y]:
if (x >= i.rect.x and x <= i.rect.right and
y >= i.rect.y and y <= i.rect.bottom):
if i.name in {c.HOLE, c.ICE_FROZEN_PLOT, c.GRAVE}:
if i.name in c.NON_PLANT_OBJECTS:
continue
# 优先移除花盆、睡莲上的植物而非花盆、睡莲本身
if len(self.map.map[map_y][map_x][c.MAP_PLANT]) >= 2:
@ -791,8 +791,8 @@ class Level(tool.State):
if map_y == None:
# 情况复杂:分水路和陆路,不能简单实现,需要另外加判断
# 0, 1, 4, 5路为陆路2, 3路为水路
if self.map_data[c.BACKGROUND_TYPE] in {c.BACKGROUND_POOL, c.BACKGROUND_FOG}:
if name in {c.DUCKY_TUBE_ZOMBIE, c.CONEHEAD_DUCKY_TUBE_ZOMBIE, c.BUCKETHEAD_DUCKY_TUBE_ZOMBIE}: # 水生僵尸集合
if self.map_data[c.BACKGROUND_TYPE] in c.POOL_EQUIPPED_BACKGROUNDS:
if name in c.WATER_ZOMBIE: # 水生僵尸集合
map_y = randint(2, 3)
elif name == '这里应该换成气球僵尸的名字(最好写调用的变量名,最好不要直接写,保持风格统一)':
map_y = randint(0, 5)
@ -923,7 +923,7 @@ class Level(tool.State):
new_plant = plant.FumeShroom(x, y, self.bullet_groups[map_y], self.zombie_groups[map_y])
if new_plant.can_sleep and self.background_type in {c.BACKGROUND_DAY, c.BACKGROUND_POOL, c.BACKGROUND_ROOF, c.BACKGROUND_WALLNUTBOWLING, c.BACKGROUND_SINGLE, c.BACKGROUND_TRIPLE}:
if new_plant.can_sleep and self.background_type in c.DAYTIME_BACKGROUNDS:
new_plant.setSleep()
mushroomSleep = True
else:
@ -981,12 +981,7 @@ class Level(tool.State):
rect = frame_list[0].get_rect()
width, height = rect.w, rect.h
if (plant_name in { c.POTATOMINE, c.SPIKEWEED,
c.JALAPENO, c.SCAREDYSHROOM,
c.SUNSHROOM, c.ICESHROOM,
c.HYPNOSHROOM, c.SQUASH,
c.WALLNUTBOWLING, c.REDWALLNUTBOWLING,
}):
if (plant_name in c.PLANT_COLOR_KEY_WHITE):
color = c.WHITE
else:
color = c.BLACK
@ -1087,27 +1082,10 @@ class Level(tool.State):
attackableBackupPlant.append(plant)
# 一般植物情形
# 同时也忽略了不可啃食对象
elif plant.name not in {# 不可啃食对象
# 非植物对象
c.HOLE, c.ICE_FROZEN_PLOT,
c.GRAVE,
# 对一般僵尸无条件不可啃食植物:地刺
c.SPIKEWEED,
# 对一般僵尸有条件不可啃食植物:跳起的倭瓜、释放效果后的爆炸类植物
# 这类在后面还需要判断
c.SQUASH, c.ICESHROOM,
c.REDWALLNUTBOWLING, c.CHERRYBOMB,
c.JALAPENO, c.DOOMSHROOM,
c.POTATOMINE
}:
elif plant.name not in c.CAN_SKIP_ZOMBIE_COLLISION_CHECK:
attackableCommonPlants.append(plant)
# 在某些状态下忽略啃食碰撞但某些状况下不能忽略的情形
elif plant.name in {# 注意爆炸坚果的触发也是啃食类碰撞,因此这里不能省略
c.SQUASH, c.ICESHROOM,
c.REDWALLNUTBOWLING, c.CHERRYBOMB,
c.JALAPENO, c.DOOMSHROOM,
c.POTATOMINE,
}:
elif plant.name in c.SKIP_ZOMBIE_COLLISION_CHECK_WHEN_WORKING:
if plant.name == c.SQUASH:
if not plant.squashing:
attackableCommonPlants.append(plant)
@ -1125,7 +1103,7 @@ class Level(tool.State):
for actualTargetPlant in self.plant_groups[i]:
# 检测同一格的其他植物
if self.map.getMapIndex(actualTargetPlant.rect.centerx, actualTargetPlant.rect.bottom) == (map_x, map_y):
if actualTargetPlant.name in {"南瓜头(未实现)"}:
if actualTargetPlant.name == "南瓜头(未实现)":
targetPlant = actualTargetPlant
break
elif actualTargetPlant.name not in {c.LILYPAD, "花盆(未实现)"}:
@ -1241,10 +1219,7 @@ class Level(tool.State):
# 毁灭菇的情况:爆炸时为了防止蘑菇云被坑掩盖没有加入坑,这里毁灭菇死亡(即爆炸动画结束)后再加入
if targetPlant.name == c.DOOMSHROOM:
self.plant_groups[map_y].add(plant.Hole(targetPlant.originalX, targetPlant.originalY, self.map.map[map_y][map_x][c.MAP_PLOT_TYPE]))
elif targetPlant.name not in { c.WALLNUTBOWLING, c.TANGLEKLEP,
c.ICE_FROZEN_PLOT, c.HOLE,
c.GRAVE, c.JALAPENO,
c.REDWALLNUTBOWLING, c.CHERRYBOMB,}:
elif targetPlant.name not in c.PLANT_DIE_SOUND_EXCEPTIONS:
# 触发植物死亡音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "plantDie.ogg")).play()
else:
@ -1265,17 +1240,7 @@ class Level(tool.State):
def checkPlant(self, targetPlant, i):
zombie_len = len(self.zombie_groups[i])
# 不用检查攻击状况的情况
if targetPlant.name in { # 单独指定攻击状态的植物
c.WALLNUTBOWLING,
# 没有攻击状态的植物
c.WALLNUT, c.TALLNUT,
c.TORCHWOOD, c.SUNFLOWER,
c.SUNSHROOM, c.COFFEEBEAN,
c.GRAVEBUSTER, c.LILYPAD,
c.HYPNOSHROOM,
# 非植物类
c.HOLE, c.GRAVE,
c.ICE_FROZEN_PLOT}:
if targetPlant.name in c.PLANT_NON_CHECK_ATTACK_STATE:
pass
elif targetPlant.name == c.THREEPEASHOOTER:
if targetPlant.state == c.IDLE:
@ -1360,9 +1325,7 @@ class Level(tool.State):
targetPlant.setAttack(zombie, self.zombie_groups[i])
break
# 灰烬植物与寒冰菇
elif targetPlant.name in { c.REDWALLNUTBOWLING, c.CHERRYBOMB,
c.JALAPENO, c.DOOMSHROOM,
c.ICESHROOM,}:
elif targetPlant.name in c.ASH_PLANTS_AND_ICESHROOM:
if targetPlant.start_boom and (not targetPlant.boomed):
# 这样分成两层是因为场上灰烬植物肯定少,一个一个判断代价高,先笼统判断灰烬即可
if targetPlant.name in {c.REDWALLNUTBOWLING, c.CHERRYBOMB}:
@ -1467,7 +1430,7 @@ class Level(tool.State):
for i in self.plant_groups[map_y]:
if (x >= i.rect.x and x <= i.rect.right and
y >= i.rect.y and y <= i.rect.bottom):
if i.name in {c.HOLE, c.ICE_FROZEN_PLOT, c.GRAVE}:
if i.name in c.NON_PLANT_OBJECTS:
continue
# 优先选中睡莲、花盆上的植物
if len(self.map.map[map_y][map_x][c.MAP_PLANT]) >= 2: