全面修改碰撞机制
This commit is contained in:
parent
46780ee81e
commit
2ce597bd48
@ -3,7 +3,7 @@
|
||||
"choosebar_type":2,
|
||||
"shovel":0,
|
||||
"spawn_zombies":"auto",
|
||||
"included_zombies":["Zombie", "ConeheadZombie", "BucketheadZombie", "NewspaperZombie"],
|
||||
"included_zombies":["Zombie", "ConeheadZombie", "BucketheadZombie", "NewspaperZombie", "PoleVaultingZombie"],
|
||||
"num_flags":4,
|
||||
"inevitable_zombie_list":{"20":["BucketheadZombie"]},
|
||||
"card_pool":[
|
||||
|
||||
@ -12,6 +12,7 @@ class Car(pg.sprite.Sprite):
|
||||
rect = tool.GFX[c.CAR].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
self.image = tool.get_image(tool.GFX[c.CAR], 0, 0, width, height)
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.bottom = y
|
||||
@ -46,7 +47,9 @@ class Bullet(pg.sprite.Sprite):
|
||||
self.frames = []
|
||||
self.frame_index = 0
|
||||
self.load_images()
|
||||
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.x = x
|
||||
self.rect.y = start_y
|
||||
@ -57,6 +60,8 @@ class Bullet(pg.sprite.Sprite):
|
||||
self.effect = effect
|
||||
self.state = c.FLY
|
||||
self.current_time = 0
|
||||
self.animate_timer = 0
|
||||
self.animate_interval = 70
|
||||
self.passedTorchWood = passedTorchWood # 记录最近通过的火炬树横坐标,如果没有缺省为None
|
||||
|
||||
def loadFrames(self, frames, name):
|
||||
@ -106,12 +111,20 @@ class Bullet(pg.sprite.Sprite):
|
||||
elif self.state == c.EXPLODE:
|
||||
if (self.current_time - self.explode_timer) > 250:
|
||||
self.kill()
|
||||
if self.current_time - self.animate_timer >= self.animate_interval:
|
||||
self.frame_index += 1
|
||||
self.animate_timer = self.current_time
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.frame_index = 0
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
def setExplode(self):
|
||||
self.state = c.EXPLODE
|
||||
self.explode_timer = self.current_time
|
||||
self.frames = self.explode_frames
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.frame_num = len(self.frames)
|
||||
self.image = self.frames[0]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
# 播放子弹爆炸音效
|
||||
if self.name == c.BULLET_FIREBALL:
|
||||
@ -133,6 +146,7 @@ class Fume(pg.sprite.Sprite):
|
||||
self.load_images()
|
||||
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.x = x
|
||||
self.rect.y = y
|
||||
@ -223,6 +237,7 @@ class Plant(pg.sprite.Sprite):
|
||||
self.loadImages(name, scale)
|
||||
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
|
||||
@ -263,6 +278,7 @@ class Plant(pg.sprite.Sprite):
|
||||
bottom = self.rect.bottom
|
||||
x = self.rect.x
|
||||
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.x = x
|
||||
@ -297,6 +313,7 @@ class Plant(pg.sprite.Sprite):
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 200):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
@ -536,6 +553,7 @@ class CherryBomb(Plant):
|
||||
old_rect = self.rect
|
||||
image = tool.get_image(frame, 0, 0, width, height, c.BLACK, 1)
|
||||
self.image = image
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
self.rect = image.get_rect()
|
||||
self.rect.centerx = old_rect.centerx
|
||||
self.rect.centery = old_rect.centery
|
||||
@ -558,6 +576,7 @@ class CherryBomb(Plant):
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
|
||||
class Chomper(Plant):
|
||||
@ -590,9 +609,11 @@ class Chomper(Plant):
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.state == c.IDLE and zombie.state != c.DIGEST and
|
||||
self.rect.x <= zombie.rect.right and (not zombie.lostHead) and
|
||||
(self.rect.right + c.GRID_X_SIZE >= zombie.rect.x)):
|
||||
if (zombie.name in {c.POLE_VAULTING_ZOMBIE}) and (not zombie.jumped):
|
||||
return False
|
||||
elif (self.state == c.IDLE and zombie.state != c.DIGEST and
|
||||
self.rect.x <= zombie.rect.right - 10 and (not zombie.lostHead) and
|
||||
(self.rect.x + c.GRID_X_SIZE*2.6 >= zombie.rect.centerx)):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -707,7 +728,7 @@ class PotatoMine(Plant):
|
||||
def canAttack(self, zombie):
|
||||
if (self.name == c.POLE_VAULTING_ZOMBIE and (not self.jumped)):
|
||||
return False
|
||||
elif (pg.sprite.collide_circle_ratio(0.55)(zombie, self) and
|
||||
elif (pg.sprite.collide_mask(zombie, self) and
|
||||
(not self.is_init) and (not zombie.lostHead)):
|
||||
return True
|
||||
return False
|
||||
@ -755,7 +776,7 @@ class Squash(Plant):
|
||||
# 攻击状态
|
||||
elif (self.state == c.ATTACK):
|
||||
# 碰撞检测
|
||||
if pg.sprite.collide_circle_ratio(0.7)(zombie, self):
|
||||
if pg.sprite.collide_mask(zombie, self):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -805,6 +826,7 @@ class Spikeweed(Plant):
|
||||
|
||||
def canAttack(self, zombie):
|
||||
# 地刺能不能扎的判据:僵尸中心与地刺中心的距离或僵尸包括了地刺中心和右端(平衡得到合理的攻击范围,"僵尸包括了地刺中心和右端"是为以后巨人做准备)
|
||||
# 暂时不能用碰撞判断,平衡性不好
|
||||
if ((-45 <= zombie.rect.x - self.rect.x <= 30) or (zombie.rect.left <= self.rect.x <= zombie.rect.right and zombie.rect.left <= self.rect.right <= zombie.rect.right)):
|
||||
return True
|
||||
return False
|
||||
@ -869,6 +891,7 @@ class Jalapeno(Plant):
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
def getPosition(self):
|
||||
return self.orig_pos
|
||||
@ -1027,6 +1050,7 @@ class IceShroom(Plant):
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
def getPosition(self):
|
||||
return self.orig_pos
|
||||
@ -1137,6 +1161,7 @@ class WallNutBowling(Plant):
|
||||
|
||||
image = self.frames[self.frame_index]
|
||||
self.image = pg.transform.rotate(image, self.rotate_degree)
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
# must keep the center postion of image when rotate
|
||||
self.rect = self.image.get_rect(center=self.init_rect.center)
|
||||
|
||||
@ -1201,6 +1226,7 @@ class RedWallNutBowling(Plant):
|
||||
self.image = pg.transform.rotate(image, self.rotate_degree)
|
||||
else:
|
||||
self.image = image
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
# must keep the center postion of image when rotate
|
||||
self.rect = self.image.get_rect(center=self.init_rect.center)
|
||||
|
||||
@ -1218,16 +1244,16 @@ class TorchWood(Plant):
|
||||
def idling(self):
|
||||
for i in self.bullet_group:
|
||||
if i.name == c.BULLET_PEA:
|
||||
if i.passedTorchWood != self.rect.x:
|
||||
if -10 <= i.rect.x - self.rect.x <= 20:
|
||||
if i.passedTorchWood != self.rect.centerx:
|
||||
if abs(i.rect.centerx - self.rect.centerx) <= 20:
|
||||
self.bullet_group.add(Bullet(i.rect.x, i.rect.y, i.rect.y,
|
||||
c.BULLET_FIREBALL, c.BULLET_DAMAGE_FIREBALL_BODY, effect=c.BULLET_EFFECT_UNICE, passedTorchWood=self.rect.x))
|
||||
c.BULLET_FIREBALL, c.BULLET_DAMAGE_FIREBALL_BODY, effect=c.BULLET_EFFECT_UNICE, passedTorchWood=self.rect.centerx))
|
||||
i.kill()
|
||||
elif i.name == c.BULLET_PEA_ICE:
|
||||
if i.passedTorchWood != self.rect.x:
|
||||
if -10 <= i.rect.x - self.rect.x <= 20:
|
||||
if i.passedTorchWood != self.rect.centerx:
|
||||
if abs(i.rect.centerx - self.rect.centerx) <= 20:
|
||||
self.bullet_group.add(Bullet(i.rect.x, i.rect.y, i.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=False, passedTorchWood=self.rect.x))
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, effect=False, passedTorchWood=self.rect.centerx))
|
||||
i.kill()
|
||||
|
||||
class StarFruit(Plant):
|
||||
@ -1304,6 +1330,7 @@ class CoffeeBean(Plant):
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 200):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
@ -1501,6 +1528,7 @@ class DoomShroom(Plant):
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
# 用于描述毁灭菇的坑
|
||||
class Hole(Plant):
|
||||
@ -1563,6 +1591,7 @@ class Grave(Plant):
|
||||
Plant.__init__(self, x, y, c.GRAVE, c.INF, None)
|
||||
self.frame_index = randint(0, self.frame_num - 1)
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
|
||||
def animation(self):
|
||||
pass
|
||||
@ -1590,6 +1619,7 @@ class GraveBuster(Plant):
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 200):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
@ -1663,6 +1693,7 @@ class FumeShroom(Plant):
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.mask = pg.mask.from_surface(self.image)
|
||||
if (self.current_time - self.highlightTime < 200):
|
||||
self.image.set_alpha(150)
|
||||
elif ((self.current_time - self.hit_timer) < 200):
|
||||
|
||||
@ -16,6 +16,7 @@ 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.rect.centerx = x
|
||||
self.rect.bottom = y
|
||||
@ -261,6 +262,7 @@ class Zombie(pg.sprite.Sprite):
|
||||
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
|
||||
@ -282,6 +284,7 @@ class Zombie(pg.sprite.Sprite):
|
||||
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:
|
||||
@ -669,8 +672,8 @@ class FootballZombie(Zombie):
|
||||
self.animate_interval = 50
|
||||
self.walk_animate_interval = 50
|
||||
self.attack_animate_interval = 60
|
||||
self.lostHead_animate_interval = 50
|
||||
self.die_animate_interval = 50
|
||||
self.lostHead_animate_interval = 180
|
||||
self.die_animate_interval = 150
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
@ -922,6 +925,7 @@ class PoleVaultingZombie(Zombie):
|
||||
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:
|
||||
|
||||
@ -166,7 +166,7 @@ PANEL_Y_INTERNAL = 73
|
||||
PANEL_X_INTERNAL = 53
|
||||
BAR_CARD_X_INTERNAL = 51
|
||||
CARD_MAX_NUM = 10 # 这里以后可以增加解锁功能,从最初的6格逐渐解锁到10格
|
||||
CARD_LIST_NUM = CARD_MAX_NUM
|
||||
CARD_LIST_NUM = 0#CARD_MAX_NUM
|
||||
|
||||
# 所选植物信息索引
|
||||
PLANT_NAME_INDEX = 0
|
||||
|
||||
@ -994,10 +994,11 @@ class Level(tool.State):
|
||||
for bullet in self.bullet_groups[i]:
|
||||
if bullet.name == c.FUME:
|
||||
continue
|
||||
elif bullet.name == c.BULLET_STAR:
|
||||
collided_func = pg.sprite.collide_circle_ratio(1)
|
||||
else:
|
||||
collided_func = pg.sprite.collide_circle_ratio(0.7)
|
||||
# elif bullet.name == c.BULLET_STAR:
|
||||
# collided_func = pg.sprite.collide_circle_ratio(1)
|
||||
# else:
|
||||
# collided_func = pg.sprite.collide_circle_ratio(0.7)
|
||||
collided_func = pg.sprite.collide_mask
|
||||
if bullet.state == c.FLY:
|
||||
# 利用循环而非内建精灵组碰撞判断函数,处理更加灵活,可排除已死亡僵尸
|
||||
for zombie in self.zombie_groups[i]:
|
||||
@ -1014,14 +1015,18 @@ class Level(tool.State):
|
||||
|
||||
|
||||
def checkZombieCollisions(self):
|
||||
if self.bar_type == c.CHOSSEBAR_BOWLING:
|
||||
ratio = 0.6
|
||||
else:
|
||||
ratio = 0.5
|
||||
collided_func = pg.sprite.collide_circle_ratio(ratio)
|
||||
# if self.bar_type == c.CHOSSEBAR_BOWLING:
|
||||
# ratio = 0.6
|
||||
# else:
|
||||
# ratio = 0.5
|
||||
# collided_func = pg.sprite.collide_circle_ratio(ratio)
|
||||
for i in range(self.map_y_len):
|
||||
hypo_zombies = []
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if zombie.name in {c.POLE_VAULTING_ZOMBIE} and (not zombie.jumped):
|
||||
collided_func = pg.sprite.collide_rect_ratio(0.6)
|
||||
else:
|
||||
collided_func = pg.sprite.collide_mask
|
||||
if zombie.state != c.WALK:
|
||||
if zombie.state != c.ATTACK:
|
||||
continue
|
||||
@ -1050,7 +1055,7 @@ class Level(tool.State):
|
||||
targetPlant = max(attackableCommonPlants, key=lambda i: i.rect.x)
|
||||
elif attackableBackupPlant:
|
||||
targetPlant = max(attackableBackupPlant, key=lambda i: i.rect.x)
|
||||
map_x, map_y = self.map.getMapIndex(targetPlant.rect.centerx, targetPlant.rect.bottom)
|
||||
map_x, map_y = self.map.getMapIndex(targetPlant.rect.centerx, targetPlant.rect.centery)
|
||||
if len(self.map.map[map_y][map_x][c.MAP_PLANT]) >= 2:
|
||||
for actualTargetPlant in self.plant_groups[i]:
|
||||
# 检测同一格的其他植物
|
||||
@ -1069,12 +1074,19 @@ class Level(tool.State):
|
||||
if targetPlant:
|
||||
# 撑杆跳的特殊情况
|
||||
if zombie.name in {c.POLE_VAULTING_ZOMBIE} and (not zombie.jumped):
|
||||
map_x, map_y = self.map.getMapIndex(targetPlant.rect.centerx, targetPlant.rect.bottom)
|
||||
jumpX = targetPlant.rect.x - c.GRID_X_SIZE * 0.7
|
||||
if c.TALLNUT in self.map.map[map_y][map_x][c.MAP_PLANT]:
|
||||
if not zombie.jumping:
|
||||
zombie.jumpMap_x, zombie.jumpMap_y = self.map.getMapIndex(targetPlant.rect.centerx, targetPlant.rect.centery)
|
||||
zombie.jumpMap_x, zombie.jumpMap_y = min(c.GRID_X_LEN, zombie.jumpMap_x), min(self.map_y_len, zombie.jumpMap_y)
|
||||
jumpX = targetPlant.rect.x - c.GRID_X_SIZE * 0.6
|
||||
if c.TALLNUT in self.map.map[zombie.jumpMap_y][zombie.jumpMap_x][c.MAP_PLANT]:
|
||||
zombie.setJump(False, jumpX)
|
||||
else:
|
||||
zombie.setJump(True, jumpX)
|
||||
else:
|
||||
if c.TALLNUT in self.map.map[zombie.jumpMap_y][zombie.jumpMap_x][c.MAP_PLANT]:
|
||||
zombie.setJump(False, zombie.jumpX)
|
||||
else:
|
||||
zombie.setJump(True, zombie.jumpX)
|
||||
continue
|
||||
|
||||
if targetPlant.name == c.WALLNUTBOWLING:
|
||||
@ -1175,7 +1187,7 @@ class Level(tool.State):
|
||||
elif (targetPlant.name == c.POTATOMINE and not targetPlant.is_init): # 土豆雷不是灰烬植物,不能用Boom
|
||||
for zombie in self.zombie_groups[map_y]:
|
||||
# 双判断:发生碰撞或在攻击范围内
|
||||
if ((pg.sprite.collide_circle_ratio(0.6)(zombie, targetPlant)) or
|
||||
if ((pg.sprite.collide_mask(zombie, targetPlant)) or
|
||||
(abs(zombie.rect.centerx - x) <= targetPlant.explode_x_range)):
|
||||
zombie.setDamage(1800, damageType=c.ZOMBIE_RANGE_DAMAGE)
|
||||
# 对于墓碑:移除存储在墓碑集合中的坐标
|
||||
@ -1202,7 +1214,14 @@ class Level(tool.State):
|
||||
|
||||
def checkPlant(self, plant, i):
|
||||
zombie_len = len(self.zombie_groups[i])
|
||||
if plant.name == c.THREEPEASHOOTER:
|
||||
# 没有攻击状态的植物
|
||||
if plant.name in { c.WALLNUTBOWLING, c.REDWALLNUTBOWLING,
|
||||
c.WALLNUT, c.TALLNUT,
|
||||
c.TORCHWOOD, c.SUNFLOWER,
|
||||
c.SUNSHROOM, c.COFFEEBEAN,
|
||||
c.GRAVEBUSTER, c.LILYPAD}:
|
||||
pass
|
||||
elif plant.name == c.THREEPEASHOOTER:
|
||||
if plant.state == c.IDLE:
|
||||
if zombie_len > 0:
|
||||
plant.setAttack()
|
||||
@ -1277,8 +1296,6 @@ class Level(tool.State):
|
||||
if plant.canAttack(zombie):
|
||||
plant.setAttack(zombie, self.zombie_groups[i])
|
||||
break
|
||||
elif plant.name in {c.WALLNUTBOWLING, c.REDWALLNUTBOWLING, c.WALLNUT, c.TALLNUT}:
|
||||
pass
|
||||
else:
|
||||
can_attack = False
|
||||
if (zombie_len > 0):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user