From da1eb139463c6a4390dd1576bb11babf500974c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=9F=E5=A4=96=E4=B9=8B=E7=A5=9E?= Date: Wed, 10 Aug 2022 10:30:08 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=AF=E8=AF=BB?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pypvz.py | 2 +- source/constants.py | 2 +- source/state/level.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pypvz.py b/pypvz.py index 58be596..dffe61c 100755 --- a/pypvz.py +++ b/pypvz.py @@ -17,7 +17,7 @@ if __name__ == "__main__": os.makedirs(os.path.dirname(c.USERLOG_PATH)) logger = logging.getLogger("main") formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s") - fileHandler = RotatingFileHandler(c.USERLOG_PATH, "a", 1024*1024, 0, "utf-8") + fileHandler = RotatingFileHandler(c.USERLOG_PATH, "a", 1_000_000, 0, "utf-8") os.chmod(c.USERLOG_PATH, 420) # 设置日志文件权限,Unix为644,Windows为可读、可写 fileHandler.setFormatter(formatter) streamHandler = logging.StreamHandler() diff --git a/source/constants.py b/source/constants.py index df09fea..ceae9c5 100755 --- a/source/constants.py +++ b/source/constants.py @@ -480,7 +480,7 @@ FUME = "Fume" # 子弹伤害 BULLET_DAMAGE_NORMAL = 20 BULLET_DAMAGE_FIREBALL_BODY = 27 # 这是火球本体的伤害,注意不是40,本体(27) + 溅射(13)才是40 -BULLET_DAMAGE_FIREBALL_RANGE = 13 +BULLET_DAMAGE_FIREBALL_RANGE = 13 # 原版溅射伤害会随着僵尸数量增多而减少,这里相当于做了一个增强 # 子弹效果 BULLET_EFFECT_ICE = "ice" BULLET_EFFECT_UNICE = "unice" diff --git a/source/state/level.py b/source/state/level.py index 9a41d24..1602ead 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -101,7 +101,7 @@ class Level(tool.State): # 按照规则生成每一波僵尸 - # 可以考虑将波刷新和一波中的僵尸生成分开 + # 将波刷新和一波中的僵尸生成分开 # useableZombie是指可用的僵尸种类的元组 # inevitableZombie指在本轮必然出现的僵尸,输入形式为字典: {波数1:(僵尸1, 僵尸2……), 波数2:(僵尸1, 僵尸2……)……} def createWaves(self, useable_zombies, num_flags, survival_rounds=0, inevitable_zombie_dict=None): @@ -126,7 +126,7 @@ class Level(tool.State): zombie_list.append(c.FLAG_ZOMBIE) zombie_volume -= c.CREATE_ZOMBIE_DICT[c.FLAG_ZOMBIE][0] - # 保龄球模式应当增大僵尸容量 + # 传送带模式应当增大僵尸容量 if (self.bar_type != c.CHOOSEBAR_STATIC): zombie_volume += 2 From 5f83d8c80561d1041bd80e42c10ee7f5eab94e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=9F=E5=A4=96=E4=B9=8B=E7=A5=9E?= Date: Wed, 10 Aug 2022 10:47:54 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=85=B3=E5=8D=A1=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 79d8a7a..6f8a8fe 100644 --- a/README.md +++ b/README.md @@ -87,10 +87,11 @@ python pypvz.py * 泳池模式:9~11 * 浓雾模式(暂时没有雾):12 * 小游戏模式: - * 坚果保龄球模式:1 + * 坚果保龄球:1 * 传送带模式(白天):2 * 传送带模式(黑夜):3 * 传送带模式(泳池):4 + * 坚果保龄球(II):5 * 目前暂时按照以上设定,未与原版相符 * 可以通过修改存档JSON文件中的`game rate`值来调节游戏速度倍率 From 23824233df2c5ad4b5502852b88f27811ddbaa85 Mon Sep 17 00:00:00 2001 From: wszqkzqk Date: Wed, 10 Aug 2022 20:26:30 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/component/plant.py | 79 ++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/source/component/plant.py b/source/component/plant.py index a4e4a59..813137c 100755 --- a/source/component/plant.py +++ b/source/component/plant.py @@ -178,9 +178,12 @@ class Fume(pg.sprite.Sprite): # 杨桃的子弹 class StarBullet(Bullet): - def __init__(self, x, start_y, damage, direction, level, damage_type = c.ZOMBIE_DEAFULT_DAMAGE): # direction指星星飞行方向 - Bullet.__init__(self, x, start_y, start_y, c.BULLET_STAR, damage, damage_type = damage_type) - + def __init__( self, x, start_y, + damage, direction, + level, damage_type = c.ZOMBIE_DEAFULT_DAMAGE): # direction指星星飞行方向 + Bullet.__init__( self, x, start_y, + start_y, c.BULLET_STAR, + damage, damage_type = damage_type) self.level = level self.map_y = self.level.map.getMapIndex(self.rect.x, self.rect.centery)[1] self.direction = direction @@ -394,7 +397,8 @@ class SunFlower(Plant): self.sun_timer = self.current_time - (c.FLOWER_SUN_INTERVAL - 6000) elif (self.current_time - self.sun_timer) > c.FLOWER_SUN_INTERVAL: self.sun_group.add( - Sun(self.rect.centerx, self.rect.bottom, self.rect.right, self.rect.bottom + self.rect.h // 2)) + Sun( self.rect.centerx, self.rect.bottom, + self.rect.right, self.rect.bottom + self.rect.h // 2)) self.sun_timer = self.current_time @@ -697,8 +701,9 @@ class PuffShroom(Plant): def canAttack(self, zombie): if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames): return False - if (self.rect.x <= zombie.rect.right and - (self.rect.x + c.GRID_X_SIZE * 4 >= zombie.rect.x) and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): + if (self.rect.x <= zombie.rect.right + and (self.rect.x + c.GRID_X_SIZE * 4 >= zombie.rect.x) + and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): return True return False @@ -796,7 +801,8 @@ class Squash(Plant): return True # 攻击状态 elif (self.state == c.ATTACK): - if pg.sprite.collide_rect_ratio(0.5)(zombie, self) or pg.sprite.collide_mask(zombie, self): + if (pg.sprite.collide_rect_ratio(0.5)(zombie, self) + or pg.sprite.collide_mask(zombie, self)): return True return False @@ -844,9 +850,12 @@ class Spikeweed(Plant): self.state = c.IDLE def canAttack(self, zombie): - # 地刺能不能扎的判据:僵尸中心与地刺中心的距离或僵尸包括了地刺中心和右端(平衡得到合理的攻击范围,"僵尸包括了地刺中心和右端"是为以后巨人做准备) + # 地刺能不能扎的判据: + # 僵尸中心与地刺中心的距离或僵尸包括了地刺中心和右端(平衡得到合理的攻击范围,"僵尸包括了地刺中心和右端"是为以后巨人做准备) # 暂时不能用碰撞判断,平衡性不好 - if ((-40 <= zombie.rect.centerx - self.rect.centerx <= 40) or (zombie.rect.left <= self.rect.x <= zombie.rect.right and zombie.rect.left <= self.rect.right <= zombie.rect.right)): + if ((-40 <= zombie.rect.centerx - self.rect.centerx <= 40) + or (zombie.rect.left <= self.rect.x <= zombie.rect.right + and zombie.rect.left <= self.rect.right <= zombie.rect.right)): return True return False @@ -1050,8 +1059,10 @@ class IceShroom(Plant): sleep_name = name + "Sleep" trap_name = name + "Trap" - frame_list = [self.idle_frames, self.snow_frames, self.sleep_frames, self.trap_frames] - name_list = [idle_name, snow_name, sleep_name, trap_name] + frame_list = [ self.idle_frames, self.snow_frames, + self.sleep_frames, self.trap_frames] + name_list = [ idle_name, snow_name, + sleep_name, trap_name] scale_list = [1, 1.5, 1, 1] for i, name in enumerate(name_list): @@ -1308,13 +1319,17 @@ class StarFruit(Plant): 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 + # 斜向上,理想直线方程为: + # f(zombie.rect.x) = -0.75*(zombie.rect.x - (self.rect.right - 5)) + self.rect.y - 10 # 注意实际上为射线 - elif -100 <= (zombie.rect.y - (-0.75*(zombie.rect.x - (self.rect.right - 5)) + self.rect.y - 10)) <= 70 and (zombie.rect.left <= c.SCREEN_WIDTH) and (zombie.rect.x >= self.rect.x): + elif (-100 <= (zombie.rect.y - (-0.75*(zombie.rect.x - (self.rect.right - 5)) + self.rect.y - 10)) <= 70 + and (zombie.rect.left <= c.SCREEN_WIDTH) and (zombie.rect.x >= self.rect.x)): return True # 斜向下,理想直线方程为:f(zombie.rect.x) = zombie.rect.x + self.rect.y - self.rect.right - 15 # 注意实际上为射线 - elif abs(zombie.rect.y - (zombie.rect.x + self.rect.y - self.rect.right - 15)) <= 70 and (zombie.rect.left <= c.SCREEN_WIDTH) and (zombie.rect.x >= self.rect.x): + elif (abs(zombie.rect.y - (zombie.rect.x + self.rect.y - self.rect.right - 15)) <= 70 + and (zombie.rect.left <= c.SCREEN_WIDTH) + and (zombie.rect.x >= self.rect.x)): return True elif zombie.rect.left <= self.rect.x <= zombie.rect.right: return True @@ -1324,13 +1339,23 @@ class StarFruit(Plant): if self.shoot_timer == 0: self.shoot_timer = self.current_time - 700 elif (self.current_time - self.shoot_timer) >= 1400: - # 向后打的杨桃子弹无视铁门与报纸防具 - self.bullet_group.add(StarBullet(self.rect.left - 10, self.rect.y + 15, c.BULLET_DAMAGE_NORMAL, c.STAR_BACKWARD, self.level, damage_type = c.ZOMBIE_COMMON_DAMAGE)) + # pypvz特有设定:向后打的杨桃子弹无视铁门与报纸防具 + self.bullet_group.add(StarBullet( self.rect.left - 10, self.rect.y + 15, + c.BULLET_DAMAGE_NORMAL, c.STAR_BACKWARD, + self.level, damage_type = c.ZOMBIE_COMMON_DAMAGE)) # 其他方向的杨桃子弹伤害效果与豌豆等同 - self.bullet_group.add(StarBullet(self.rect.centerx - 20, self.rect.bottom - self.rect.h - 15, c.BULLET_DAMAGE_NORMAL, c.STAR_UPWARD, self.level)) - self.bullet_group.add(StarBullet(self.rect.centerx - 20, self.rect.bottom - 5, c.BULLET_DAMAGE_NORMAL, c.STAR_DOWNWARD, self.level)) - self.bullet_group.add(StarBullet(self.rect.right - 5, self.rect.bottom - 20, c.BULLET_DAMAGE_NORMAL, c.STAR_FORWARD_DOWN, self.level)) - self.bullet_group.add(StarBullet(self.rect.right - 5, self.rect.y - 10, c.BULLET_DAMAGE_NORMAL, c.STAR_FORWARD_UP, self.level)) + self.bullet_group.add(StarBullet( self.rect.centerx - 20, self.rect.bottom - self.rect.h - 15, + c.BULLET_DAMAGE_NORMAL, c.STAR_UPWARD, + self.level)) + self.bullet_group.add(StarBullet( self.rect.centerx - 20, self.rect.bottom - 5, + c.BULLET_DAMAGE_NORMAL, c.STAR_DOWNWARD, + self.level)) + self.bullet_group.add(StarBullet( self.rect.right - 5, self.rect.bottom - 20, + c.BULLET_DAMAGE_NORMAL, c.STAR_FORWARD_DOWN, + self.level)) + self.bullet_group.add(StarBullet( self.rect.right - 5, self.rect.y - 10, + c.BULLET_DAMAGE_NORMAL, c.STAR_FORWARD_UP, + self.level)) self.shoot_timer = self.current_time # 播放发射音效 c.SOUND_SHOOT.play() @@ -1358,8 +1383,8 @@ class CoffeeBean(Plant): for plant in self.plant_group: if plant.can_sleep: if plant.state == c.SLEEP: - plantMapX, _ = self.map.getMapIndex(plant.rect.centerx, plant.rect.bottom) - if plantMapX == self.map_x: + plant_map_x, _ = self.map.getMapIndex(plant.rect.centerx, plant.rect.bottom) + if plant_map_x == self.map_x: plant.state = c.IDLE plant.setIdle() plant.changeFrames(plant.idle_frames) @@ -1415,8 +1440,9 @@ class SeaShroom(Plant): def canAttack(self, zombie): if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames): return False - if (self.rect.x <= zombie.rect.right and - (self.rect.x + c.GRID_X_SIZE * 4 >= zombie.rect.x) and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): + if (self.rect.x <= zombie.rect.right + and (self.rect.x + c.GRID_X_SIZE * 4 >= zombie.rect.x) + and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): return True return False @@ -1706,8 +1732,9 @@ class FumeShroom(Plant): def canAttack(self, zombie): if (zombie.name == c.SNORKELZOMBIE) and (zombie.frames == zombie.swim_frames): return False - if (self.rect.x <= zombie.rect.right and - (self.rect.x + c.GRID_X_SIZE * 5 >= zombie.rect.x) and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): + if (self.rect.x <= zombie.rect.right + and (self.rect.x + c.GRID_X_SIZE * 5 >= zombie.rect.x) + and (zombie.rect.left <= c.SCREEN_WIDTH + 10)): return True return False From a0c8201d26e31e0bd6d1001676656be828bd8c5f Mon Sep 17 00:00:00 2001 From: wszqkzqk Date: Thu, 11 Aug 2022 10:42:30 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/component/map.py | 8 ++++---- source/component/menubar.py | 26 ++++++++++++++------------ source/state/level.py | 4 +++- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/source/component/map.py b/source/component/map.py index 87b6d40..11af345 100755 --- a/source/component/map.py +++ b/source/component/map.py @@ -56,10 +56,10 @@ class Map(): ] def isValid(self, map_x, map_y): - if (map_x < 0 or map_x >= self.width or - map_y < 0 or map_y >= self.height): - return False - return True + if ((0 <= map_x < self.width) + and (0 <= map_y < self.height)): + return True + return False # 地图单元格状态 # 注意是可变对象,不能直接引用 diff --git a/source/component/menubar.py b/source/component/menubar.py index 52bd69b..96cf58d 100755 --- a/source/component/menubar.py +++ b/source/component/menubar.py @@ -22,7 +22,8 @@ def getSunValueImage(sun_value): return image def getCardPool(data): - card_pool = {c.PLANT_CARD_INFO[c.PLANT_CARD_INDEX[card_name]]: data[card_name] for card_name in data} + card_pool = {c.PLANT_CARD_INFO[c.PLANT_CARD_INDEX[card_name]]: data[card_name] + for card_name in data} return card_pool class Card(): @@ -36,7 +37,8 @@ class Card(): self.sun_cost_img = font.render(str(c.PLANT_CARD_INFO[index][c.SUN_INDEX]), True, c.BLACK) self.sun_cost_img_rect = self.sun_cost_img.get_rect() sun_cost_img_x = 32 - self.sun_cost_img_rect.w - self.orig_image.blit(self.sun_cost_img, (sun_cost_img_x, 52, self.sun_cost_img_rect.w, self.sun_cost_img_rect.h)) + self.orig_image.blit(self.sun_cost_img, + (sun_cost_img_x, 52, self.sun_cost_img_rect.w, self.sun_cost_img_rect.h)) self.index = index self.sun_cost = c.PLANT_CARD_INFO[index][c.SUN_INDEX] @@ -86,7 +88,7 @@ class Card(): image = pg.Surface((self.rect.w, self.rect.h)) # 黑底 frozen_image = self.orig_image frozen_image.set_alpha(128) - frozen_height = (self.frozen_time - time)/self.frozen_time * self.rect.h + frozen_height = ((self.frozen_time - time)/self.frozen_time) * self.rect.h image.blit(frozen_image, (0,0), (0, 0, self.rect.w, frozen_height)) self.orig_image.set_alpha(192) @@ -177,8 +179,8 @@ class MenuBar(): def checkMenuBarClick(self, mouse_pos): x, y = mouse_pos - if (x >= self.rect.x and x <= self.rect.right and - y >= self.rect.y and y <= self.rect.bottom): + if (self.rect.x <= x <= self.rect.right and + self.rect.y <= y <= self.rect.bottom): return True return False @@ -299,8 +301,8 @@ class Panel(): return False x, y = mouse_pos - if (x >= self.button_rect.x and x <= self.button_rect.right and - y >= self.button_rect.y and y <= self.button_rect.bottom): + if (self.button_rect.x <= x <= self.button_rect.right and + self.button_rect.y <= y <= self.button_rect.bottom): return True return False @@ -349,8 +351,8 @@ class MoveCard(): def checkMouseClick(self, mouse_pos): x, y = mouse_pos - if (x >= self.rect.x and x <= self.rect.right and - y >= self.rect.y and y <= self.rect.bottom): + if (self.rect.x <= x <= self.rect.right and + self.rect.y <= y <= self.rect.bottom): return True return False @@ -426,7 +428,7 @@ class MoveBar(): card.update(left_x, self.current_time) left_x = card.rect.right + 1 - if(self.current_time - self.create_timer) > c.MOVEBAR_CARD_FRESH_TIME: + if (self.current_time - self.create_timer) > c.MOVEBAR_CARD_FRESH_TIME: if self.createCard(): self.create_timer = self.current_time @@ -440,8 +442,8 @@ class MoveBar(): def checkMenuBarClick(self, mouse_pos): x, y = mouse_pos - if (x >= self.rect.x and x <= self.rect.right and - y >= self.rect.y and y <= self.rect.bottom): + if (self.rect.x <= x <= self.rect.right and + self.rect.y <= y <= self.rect.bottom): return True return False diff --git a/source/state/level.py b/source/state/level.py index 1602ead..3b2c848 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -26,6 +26,7 @@ class Level(tool.State): # 导入地图参数 self.loadMap() self.map = map.Map(self.map_data[c.BACKGROUND_TYPE]) + self.map_x_len = self.map.width self.map_y_len = self.map.height self.setupBackground() self.initState() @@ -1115,7 +1116,8 @@ class Level(tool.State): zombie.health = 0 c.SOUND_BOWLING_IMPACT.play() elif not zombie.jumping: - zombie.jump_map_x, zombie.jump_map_y = min(c.GRID_X_LEN - 1, zombie.prey_map_x), min(self.map_y_len - 1, zombie.prey_map_y) + zombie.jump_map_x = min(self.map_x_len - 1, zombie.prey_map_x) + zombie.jump_map_y = min(self.map_y_len - 1, zombie.prey_map_y) jump_x = target_plant.rect.x - c.GRID_X_SIZE * 0.6 if c.TALLNUT in self.map.map[zombie.jump_map_y][zombie.jump_map_x][c.MAP_PLANT]: zombie.setJump(False, jump_x)