Squashed commit of the following:

commit b6799a240bb2674f6b835b8402da609e22059030
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 20:03:55 2022 +0800

    修改异常处理方式

commit dcf925ca526e66166c5b19b0b8442a32120a332d
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 19:51:06 2022 +0800

    暂时放弃OpenGL

commit 2c0dc94c75d902aa356ee0b8350ea0aa02c84fdb
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 19:41:50 2022 +0800

    更改非Nuitka程序图标设定

commit 1dd0894adffdafd61bd696807a6eb9d2735d4d25
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 19:16:21 2022 +0800

    维护清理

commit b8a7fc0a66a22fae0ead9a9e4f88aa024276f078
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 14:43:51 2022 +0800

    修复传送带模式中点击到达传送带底部的卡片没有透明度变化的bug

commit 9303304e94aabd4f955c3c186ff73525057bb133
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 14:21:47 2022 +0800

    优化报纸僵尸设定

commit 0b9dbdc14513916dcb15dc717060faf380c1b681
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 14:17:26 2022 +0800

    微调报纸僵尸速度

commit 44e6ce77e77fba19ebec22d08cdccf6d07246905
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 13:58:31 2022 +0800

    清理

commit e00ed2f061ff148cbe0b38991a6ab585963ec9b3
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 13:58:05 2022 +0800

    修复潜水僵尸只能攻击一次的bug

commit 790bc0bc5eeb206ebe769d91a4f339d050e86100
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri Jun 3 10:15:33 2022 +0800

    更改构建命令

commit db86b3144ced0603c4db1e7220dbc47559b9dd87
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Thu Jun 2 19:03:13 2022 +0800

    更改模块调用方式

commit 885f9902af79b2e23590956626e6eabe17e71931
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Wed Jun 1 14:15:50 2022 +0800

    更新null值引用方式

commit d054ff498ba58356e9886064ae9c1a62fb0585a5
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Wed Jun 1 13:39:56 2022 +0800

    进一步将常数性内容汇总到constants.py中

commit c4a756756b922cba8f8224b247bce7e7e7838808
Author: 星外之神 <wszqkzqk@qq.com>
Date:   Fri May 27 15:23:52 2022 +0800

    说明
This commit is contained in:
星外之神 2022-06-03 21:29:45 +08:00
parent cdf992095e
commit 783e0743ba
9 changed files with 220 additions and 199 deletions

View File

@ -45,6 +45,7 @@ jobs:
--distpath ./out `
--noconsole `
--add-data="resources;./resources" `
--add-data="pypvz-exec-logo.png;./pypvz-exec-logo.png" `
-i ./pypvz.ico
- name: Release the version built by pyinstaller
@ -76,8 +77,8 @@ jobs:
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbisfile-3.dll=libvorbisfile-3.dll `
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbis-0.dll=libvorbis-0.dll `
--windows-disable-console `
-o ./out/pypvz-with-python${{ matrix.python_version }}-nuitka-msvc-x64.exe `
main.py
mv ./out/main.exe ./out/pypvz-with-python${{ matrix.python_version }}-nuitka-msvc-x64.exe
# artifact压缩包处上传包含exe和运行环境的文件夹
- name: "Upload binaries"

BIN
pypvz-exec-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -44,7 +44,6 @@ class Map():
# 判断位置是否可用
# 暂时没有写紫卡植物的判断方法
# 由于紫卡植物需要移除以前的植物,所以可用另外定义一个函数
# 注意咖啡豆生效后需要同时将植物的睡眠状态和格子的睡眠记录改变
def isAvailable(self, map_x, map_y, plantName):
# 咖啡豆和墓碑吞噬者的判别最为特殊
if plantName == c.COFFEEBEAN:
@ -97,7 +96,7 @@ class Map():
else: # 非水生植物,依赖睡莲
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])): # 例外植物:集合中填花盆和南瓜头,只要这里没有这种植物就能种植;判断方法:并集
and (plantName not in self.map[map_y][map_x][c.MAP_PLANT])):
if plantName in {c.SPIKEWEED, c.POTATOMINE, '花盆(未实现)'}: # 不能在睡莲上种植的植物
return False
else:

View File

@ -4,133 +4,6 @@ import pygame as pg
from .. import tool
from .. import constants as c
plantInfo = (# 元组 (植物名称, 卡片名称, 阳光, 冷却时间)
(c.PEASHOOTER,
c.CARD_PEASHOOTER,
100,
7500),
(c.SUNFLOWER,
c.CARD_SUNFLOWER,
50,
7500),
(c.CHERRYBOMB,
c.CARD_CHERRYBOMB,
150,
50000),
(c.WALLNUT,
c.CARD_WALLNUT,
50,
30000),
(c.POTATOMINE,
c.CARD_POTATOMINE,
25,
30000),
(c.SNOWPEASHOOTER,
c.CARD_SNOWPEASHOOTER,
175,
7500),
(c.CHOMPER,
c.CARD_CHOMPER,
150,
7500),
(c.REPEATERPEA,
c.CARD_REPEATERPEA,
200,
7500),
(c.PUFFSHROOM,
c.CARD_PUFFSHROOM,
0,
7500),
(c.SUNSHROOM,
c.CARD_SUNSHROOM,
25,
7500),
(c.FUMESHROOM,
c.CARD_FUMESHROOM,
75,
7500),
(c.GRAVEBUSTER,
c.CARD_GRAVEBUSTER,
75,
7500),
(c.HYPNOSHROOM,
c.CARD_HYPNOSHROOM,
75,
30000),
(c.SCAREDYSHROOM,
c.CARD_SCAREDYSHROOM,
25,
7500),
(c.ICESHROOM,
c.CARD_ICESHROOM,
75,
50000),
(c.DOOMSHROOM,
c.CARD_DOOMSHROOM,
75,
50000),
(c.LILYPAD,
c.CARD_LILYPAD,
25,
7500),
(c.SQUASH,
c.CARD_SQUASH,
50,
30000),
(c.TANGLEKLEP,
c.CARD_TANGLEKLEP,
25,
30000),
(c.THREEPEASHOOTER,
c.CARD_THREEPEASHOOTER,
325,
7500),
(c.JALAPENO,
c.CARD_JALAPENO,
125,
50000),
(c.SPIKEWEED,
c.CARD_SPIKEWEED,
100,
7500),
(c.TORCHWOOD,
c.CARD_TORCHWOOD,
175,
7500),
(c.TALLNUT,
c.CARD_TALLNUT,
125,
30000),
(c.SEASHROOM,
c.CARD_SEASHROOM,
125,
30000),
(c.STARFRUIT,
c.CARD_STARFRUIT,
125,
7500),
(c.COFFEEBEAN,
c.CARD_COFFEEBEAN,
75,
7500),
(c.GARLIC,
c.CARD_GARLIC,
50,
7500),
# 应当保证这两个在一般模式下不可选的特殊植物恒在最后
(c.WALLNUTBOWLING,
c.CARD_WALLNUT,
0,
0),
(c.REDWALLNUTBOWLING,
c.CARD_REDWALLNUT,
0,
0),
)
# 指定了哪些卡可选
cards_to_choose = range(len(plantInfo) - 2)
def getSunValueImage(sun_value):
# for pack, must include ttf
@ -152,7 +25,7 @@ def getSunValueImage(sun_value):
def getCardPool(data):
card_pool = []
for card in data:
for i,name in enumerate(plantInfo):
for i,name in enumerate(c.PLANT_CARD_INFO):
if name[c.PLANT_NAME_INDEX] == card:
card_pool.append(i)
break
@ -160,14 +33,14 @@ def getCardPool(data):
class Card():
def __init__(self, x, y, index, scale=0.5):
self.loadFrame(plantInfo[index][c.CARD_INDEX], scale)
self.loadFrame(c.PLANT_CARD_INFO[index][c.CARD_INDEX], scale)
self.rect = self.orig_image.get_rect()
self.rect.x = x
self.rect.y = y
self.index = index
self.sun_cost = plantInfo[index][c.SUN_INDEX]
self.frozen_time = plantInfo[index][c.FROZEN_INDEX]
self.sun_cost = c.PLANT_CARD_INFO[index][c.SUN_INDEX]
self.frozen_time = c.PLANT_CARD_INFO[index][c.FROZEN_INDEX]
self.frozen_timer = -self.frozen_time
self.refresh_timer = 0
self.select = True
@ -289,7 +162,7 @@ class MenuBar():
for card in self.card_list:
if card.checkMouseClick(mouse_pos):
if card.canClick(self.sun_value, self.current_time):
result = (plantInfo[card.index][c.PLANT_NAME_INDEX], card)
result = (c.PLANT_CARD_INFO[card.index][c.PLANT_NAME_INDEX], card)
break
return result
@ -310,7 +183,7 @@ class MenuBar():
def setCardFrozenTime(self, plant_name):
for card in self.card_list:
if plantInfo[card.index][c.PLANT_NAME_INDEX] == plant_name:
if c.PLANT_CARD_INFO[card.index][c.PLANT_NAME_INDEX] == plant_name:
card.setFrozenTime(self.current_time)
break
@ -440,7 +313,7 @@ class Panel():
if self.selected_num >= c.CARD_LIST_NUM:
surface.blit(self.button_image, self.button_rect)
# 传送带模式
# 传送带模式的卡片
class MoveCard():
def __init__(self, x, y, card_name, plant_name, scale=0.5):
self.loadFrame(card_name, scale)
@ -526,8 +399,8 @@ class MoveBar():
y = 6
index = random.randint(0, len(self.card_pool) - 1)
card_index = self.card_pool[index]
card_name = plantInfo[card_index][c.CARD_INDEX] + '_move'
plant_name = plantInfo[card_index][c.PLANT_NAME_INDEX]
card_name = c.PLANT_CARD_INFO[card_index][c.CARD_INDEX] + '_move'
plant_name = c.PLANT_CARD_INFO[card_index][c.PLANT_NAME_INDEX]
self.card_list.append(MoveCard(x, y, card_name, plant_name))
return True

View File

@ -1,4 +1,4 @@
from random import randint
import random
import pygame as pg
import os
from .. import tool
@ -1143,7 +1143,7 @@ class WallNutBowling(Plant):
self.animate_interval = 200
self.move_timer = 0
self.move_interval = 70
self.vel_x = randint(12, 15)
self.vel_x = random.randint(12, 15)
self.vel_y = 0
self.disable_hit_y = -1
@ -1192,7 +1192,7 @@ class WallNutBowling(Plant):
elif self.map_y == (c.GRID_Y_LEN - 1): # 坚果保龄球显然没有泳池的6行情形
self.vel_y = -self.vel_x
else:
if randint(0, 1):
if random.randint(0, 1):
self.vel_y = self.vel_x
else:
self.vel_y = -self.vel_x
@ -1227,7 +1227,7 @@ class RedWallNutBowling(Plant):
self.animate_interval = 200
self.move_timer = 0
self.move_interval = 70
self.vel_x = randint(12, 15)
self.vel_x = random.randint(12, 15)
self.start_boom = False
self.boomed = False
@ -1648,7 +1648,7 @@ class Hole(Plant):
class Grave(Plant):
def __init__(self, x, y):
Plant.__init__(self, x, y, c.GRAVE, c.INF, None)
self.frame_index = randint(0, self.frame_num - 1)
self.frame_index = random.randint(0, self.frame_num - 1)
self.image = self.frames[self.frame_index]
self.mask = pg.mask.from_surface(self.image)

View File

@ -1,6 +1,6 @@
import pygame as pg
import os
from random import randint
import random
from .. import tool
from .. import constants as c
@ -245,7 +245,8 @@ class Zombie(pg.sprite.Sprite):
self.changeFrames(self.attack_frames)
self.helmetType2 = False
if self.name == c.NEWSPAPER_ZOMBIE:
self.speed = 2.5
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)):
if self.prey.health > 0:
@ -273,7 +274,7 @@ class Zombie(pg.sprite.Sprite):
if self.checkToDie(self.losthead_attack_frames):
return
if (self.current_time - self.freeze_timer) >= c.MIN_FREEZE_TIME + randint(0, 2000):
if (self.current_time - self.freeze_timer) >= c.MIN_FREEZE_TIME + random.randint(0, 2000):
self.setWalk()
# 注意寒冰菇解冻后还有减速
self.ice_slow_timer = self.freeze_timer + 10000 # 每次冰冻冻结 + 减速时间为20 s而减速有10 s计时故这里+10 s
@ -737,6 +738,7 @@ class NewspaperZombie(Zombie):
self.changeFrames(self.walk_frames)
self.speedUp = True
self.speed = 2.65
self.walk_animate_interval = 300
# 触发报纸僵尸暴走音效
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "newspaperZombieAngry.ogg")).play()
return
@ -1252,3 +1254,10 @@ class SnorkelZombie(Zombie):
self.changeFrames(self.float_frames)
self.canSetAttack = False
def setWalk(self):
self.state = c.WALK
self.animate_interval = self.walk_animate_interval
if self.rect.right <= c.MAP_POOL_FRONT_X:
self.swimming = True
self.changeFrames(self.sink_frames)

View File

@ -8,6 +8,8 @@ GAME_RATE = 1
# 窗口标题
ORIGINAL_CAPTION = 'pypvz'
# 窗口图标
ORIGINAL_LOGO = "pypvz-exec-logo.png"
# 游戏模式
GAME_MODE = 'mode'
@ -55,8 +57,6 @@ GREEN = ( 0, 255, 0)
# 退出游戏按钮
EXIT = 'exit'
# 当想要一个特殊值时用
NULL = 'null'
# 游戏界面可选的菜单
LITTLE_MENU = 'littleMenu'
BIG_MENU = 'bigMenu'
@ -342,7 +342,7 @@ ICE_SLOW_TIME = 10000
MIN_FREEZE_TIME = 4000
ICETRAP = 'IceTrap'
# 植物卡片信息
# 植物卡片名称
CARD_SUNFLOWER = 'card_sunflower'
CARD_PEASHOOTER = 'card_peashooter'
CARD_SNOWPEASHOOTER = 'card_snowpea'
@ -373,6 +373,136 @@ CARD_GRAVEBUSTER = 'card_gravebuster'
CARD_FUMESHROOM = 'card_fumeshroom'
CARD_GARLIC = 'card_garlic'
# 植物卡片信息汇总(包括植物名称, 卡片名称, 阳光, 冷却时间)
PLANT_CARD_INFO = (# 元组 (植物名称, 卡片名称, 阳光, 冷却时间)
(PEASHOOTER,
CARD_PEASHOOTER,
100,
7500),
(SUNFLOWER,
CARD_SUNFLOWER,
50,
7500),
(CHERRYBOMB,
CARD_CHERRYBOMB,
150,
50000),
(WALLNUT,
CARD_WALLNUT,
50,
30000),
(POTATOMINE,
CARD_POTATOMINE,
25,
30000),
(SNOWPEASHOOTER,
CARD_SNOWPEASHOOTER,
175,
7500),
(CHOMPER,
CARD_CHOMPER,
150,
7500),
(REPEATERPEA,
CARD_REPEATERPEA,
200,
7500),
(PUFFSHROOM,
CARD_PUFFSHROOM,
0,
7500),
(SUNSHROOM,
CARD_SUNSHROOM,
25,
7500),
(FUMESHROOM,
CARD_FUMESHROOM,
75,
7500),
(GRAVEBUSTER,
CARD_GRAVEBUSTER,
75,
7500),
(HYPNOSHROOM,
CARD_HYPNOSHROOM,
75,
30000),
(SCAREDYSHROOM,
CARD_SCAREDYSHROOM,
25,
7500),
(ICESHROOM,
CARD_ICESHROOM,
75,
50000),
(DOOMSHROOM,
CARD_DOOMSHROOM,
75,
50000),
(LILYPAD,
CARD_LILYPAD,
25,
7500),
(SQUASH,
CARD_SQUASH,
50,
30000),
(TANGLEKLEP,
CARD_TANGLEKLEP,
25,
30000),
(THREEPEASHOOTER,
CARD_THREEPEASHOOTER,
325,
7500),
(JALAPENO,
CARD_JALAPENO,
125,
50000),
(SPIKEWEED,
CARD_SPIKEWEED,
100,
7500),
(TORCHWOOD,
CARD_TORCHWOOD,
175,
7500),
(TALLNUT,
CARD_TALLNUT,
125,
30000),
(SEASHROOM,
CARD_SEASHROOM,
125,
30000),
(STARFRUIT,
CARD_STARFRUIT,
125,
7500),
(COFFEEBEAN,
CARD_COFFEEBEAN,
75,
7500),
(c.GARLIC,
c.CARD_GARLIC,
50,
7500),
# 应当保证这两个在一般模式下不可选的特殊植物恒在最后
(WALLNUTBOWLING,
CARD_WALLNUT,
0,
0),
(REDWALLNUTBOWLING,
CARD_REDWALLNUT,
0,
0),
)
# 指定了哪些卡可选(排除坚果保龄球特殊植物)
CARDS_TO_CHOOSE = range(len(PLANT_CARD_INFO) - 2)
# 子弹信息
# 子弹类型
BULLET_PEA = 'PeaNormal'

View File

@ -2,7 +2,7 @@ import os
import json
import sys
import pygame as pg
from random import randint, uniform, choices
import random
from .. import tool
from .. import constants as c
from ..component import map, plant, zombie, menubar
@ -41,7 +41,7 @@ class Level(tool.State):
f = open(file_path)
self.map_data = json.load(f)
f.close()
except Exception:
except:
print("成功通关!")
if self.game_info[c.GAME_MODE] == c.MODE_LITTLEGAME:
self.game_info[c.LEVEL_NUM] = c.START_LEVEL_NUM
@ -147,7 +147,7 @@ class Level(tool.State):
minCost = c.CREATE_ZOMBIE_DICT[min(useableZombies, key=lambda x:c.CREATE_ZOMBIE_DICT[x][0])][0]
while (volume >= minCost) and (len(zombieList) < 50):
newZombie = choices(useableZombies, weights)[0]
newZombie = random.choices(useableZombies, weights)[0]
# 普通僵尸、路障僵尸、铁桶僵尸有概率生成水中变种
if self.background_type in c.POOL_EQUIPPED_BACKGROUNDS:
# 有泳池第一轮的第四波设定上生成水生僵尸
@ -155,7 +155,7 @@ class Level(tool.State):
if newZombie in c.CONVERT_ZOMBIE_IN_POOL:
newZombie = c.CONVERT_ZOMBIE_IN_POOL[newZombie]
elif survivalRounds > 0 or wave > 4:
if randint(1, 3) == 1: # 1/3概率水上暂时人为设定
if random.randint(1, 3) == 1: # 1/3概率水上暂时人为设定
if newZombie in c.CONVERT_ZOMBIE_IN_POOL:
newZombie = c.CONVERT_ZOMBIE_IN_POOL[newZombie]
# 首先几轮不出水生僵尸
@ -201,20 +201,20 @@ class Level(tool.State):
elif c.GRAVE not in self.map.map[mapY][mapX][c.MAP_PLANT]:
occupied.append((mapX, mapY))
if unoccupied:
target = unoccupied[randint(0, len(unoccupied) - 1)]
target = unoccupied[random.randint(0, len(unoccupied) - 1)]
mapX, mapY = target
posX, posY = self.map.getMapGridPos(mapX, mapY)
self.plant_groups[mapY].add(plant.Grave(posX, posY))
self.map.map[mapY][mapX][c.MAP_PLANT].add(c.GRAVE)
self.graveSet.add((mapX, mapY))
elif occupied:
target = occupied[randint(0, len(occupied) - 1)]
target = occupied[random.randint(0, len(occupied) - 1)]
mapX, mapY = target
posX, posY = self.map.getMapGridPos(mapX, mapY)
for i in self.plant_groups[mapY]:
checkMapX, _ = self.map.getMapIndex(i.rect.centerx, i.rect.bottom)
if mapX == checkMapX:
# 不杀死毁灭菇坑和冰道
# 不杀死毁灭菇坑和冰道
if i.name not in exceptionObjects:
i.health = 0
self.plant_groups[mapY].add(plant.Grave(posX, posY))
@ -227,7 +227,7 @@ class Level(tool.State):
for item in self.graveSet:
itemX, itemY = self.map.getMapGridPos(*item)
# 目前设定2/3概率普通僵尸1/3概率路障僵尸
if randint(0, 2):
if random.randint(0, 2):
self.zombie_groups[item[1]].add(zombie.NormalZombie(itemX, itemY, self.head_group))
else:
self.zombie_groups[item[1]].add(zombie.ConeHeadZombie(itemX, itemY, self.head_group))
@ -237,11 +237,11 @@ class Level(tool.State):
if current_time - self.waveTime > 1500:
for i in range(3):
# 水中倒数四列内可以在此时产生僵尸。共产生3个
mapX, mapY = randint(5, 8), randint(2, 3)
mapX, mapY = random.randint(5, 8), random.randint(2, 3)
itemX, itemY = self.map.getMapGridPos(mapX, mapY)
# 用随机数指定产生的僵尸类型
# 带有权重
zombieType = randint(1, 6)
zombieType = random.randint(1, 6)
if zombieType == 1:
self.zombie_groups[mapY].add(zombie.BucketHeadDuckyTubeZombie(itemX, itemY, self.head_group))
elif zombieType <= 3:
@ -272,7 +272,7 @@ class Level(tool.State):
pg.mixer.Sound(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))) ,"resources", "sound", "zombieComing.ogg")).play()
return
if (self.waveNum % 10 != 9):
if ((current_time - self.waveTime >= 25000 + randint(0, 6000)) or (self.bar_type != c.CHOOSEBAR_STATIC and current_time - self.waveTime >= 12500 + randint(0, 3000))):
if ((current_time - self.waveTime >= 25000 + random.randint(0, 6000)) or (self.bar_type != c.CHOOSEBAR_STATIC and current_time - self.waveTime >= 12500 + random.randint(0, 3000))):
self.waveNum += 1
self.waveTime = current_time
self.waveZombies = self.waves[self.waveNum - 1]
@ -293,7 +293,7 @@ class Level(tool.State):
numZombies = 0
for i in range(self.map_y_len):
numZombies += len(self.zombie_groups[i])
if (numZombies / self.numZombie < uniform(0.15, 0.25)) and (current_time - self.waveTime > 4000):
if (numZombies / self.numZombie < random.uniform(0.15, 0.25)) and (current_time - self.waveTime > 4000):
# 当僵尸所剩无几并且时间过了4000 ms以上时改变时间记录使得2000 ms后刷新僵尸所以需要判断剩余时间是否大于2000 ms
if self.bar_type == c.CHOOSEBAR_STATIC:
if current_time - 43000 < self.waveTime: # 判断剩余时间是否有2000 ms
@ -364,7 +364,7 @@ class Level(tool.State):
def initChoose(self):
self.state = c.CHOOSE
self.panel = menubar.Panel(menubar.cards_to_choose, self.map_data[c.INIT_SUN_NAME])
self.panel = menubar.Panel(c.CARDS_TO_CHOOSE, self.map_data[c.INIT_SUN_NAME])
# 播放选卡音乐
pg.mixer.music.stop()
@ -417,7 +417,7 @@ class Level(tool.State):
self.removeMouseImage()
self.setupGroups()
if (c.ZOMBIE_LIST in self.map_data) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
if self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
self.setupZombies()
else:
# 僵尸波数数据及僵尸生成数据
@ -468,8 +468,8 @@ class Level(tool.State):
graveVolume = c.GRAVES_GRADE_INFO[gradeGraves]
self.graveSet = set()
while len(self.graveSet) < graveVolume:
mapX = randint(4, 8) # 注意是从0开始编号
mapY = randint(0, 4)
mapX = random.randint(4, 8) # 注意是从0开始编号
mapY = random.randint(0, 4)
self.graveSet.add((mapX, mapY))
if self.graveSet:
for i in self.graveSet:
@ -656,7 +656,7 @@ class Level(tool.State):
self.pauseAndCheckLittleMenuOptions(mouse_pos, mouse_click)
return
if (c.ZOMBIE_LIST in self.map_data) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
if self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
# 旧僵尸生成方式
if self.zombie_start_time == 0:
self.zombie_start_time = self.current_time
@ -694,7 +694,7 @@ class Level(tool.State):
if self.produce_sun:
# 原版阳光掉落机制:(已掉落阳光数*100 ms + 4250 ms) 与 9500 ms的最小值再加 0 ~ 2750 ms 之间的一个数
if (self.current_time - self.sun_timer) > min(c.PRODUCE_SUN_INTERVAL + 100*self.fallenSun, 9500) + randint(0, 2750):
if (self.current_time - self.sun_timer) > min(c.PRODUCE_SUN_INTERVAL + 100*self.fallenSun, 9500) + random.randint(0, 2750):
self.sun_timer = self.current_time
map_x, map_y = self.map.getRandomMapIndex()
x, y = self.map.getMapGridPos(map_x, map_y)
@ -728,8 +728,8 @@ class Level(tool.State):
clickedCardsOrMap = True
self.clickResult[1].clicked = False
elif mouse_click[0]:
self.clickResult[1].clicked = False
if self.menubar.checkMenuBarClick(mouse_pos):
self.clickResult[1].clicked = False
self.removeMouseImage()
else:
self.addPlant()
@ -778,22 +778,22 @@ class Level(tool.State):
# 情况复杂:分水路和陆路,不能简单实现,需要另外加判断
# 0, 1, 4, 5路为陆路2, 3路为水路
if self.map_data[c.BACKGROUND_TYPE] in c.POOL_EQUIPPED_BACKGROUNDS:
if name in c.WATER_ZOMBIE: # 水生僵尸集合
map_y = randint(2, 3)
if name in c.WATER_ZOMBIE:
map_y = random.randint(2, 3)
elif name == '这里应该换成气球僵尸的名字(最好写调用的变量名,最好不要直接写,保持风格统一)':
map_y = randint(0, 5)
map_y = random.randint(0, 5)
else: # 陆生僵尸
map_y = randint(0, 3)
map_y = random.randint(0, 3)
if map_y >= 2: # 后两路的map_y应当+2
map_y += 2
elif self.map_data[c.BACKGROUND_TYPE] == c.BACKGROUND_SINGLE:
map_y = 2
elif self.map_data[c.BACKGROUND_TYPE] == c.BACKGROUND_TRIPLE:
map_y = randint(1, 3)
map_y = random.randint(1, 3)
else:
map_y = randint(0, 4)
map_y = random.randint(0, 4)
if not ((c.ZOMBIE_LIST in self.map_data) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST):
if self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_AUTO:
# 旗帜波出生点右移
if self.waveNum % 10:
hugeWaveMove = 0
@ -802,35 +802,37 @@ class Level(tool.State):
else:
hugeWaveMove = 0
x, y = self.map.getMapGridPos(0, map_y)
# 新增的僵尸也需要在这里声明
if name == c.NORMAL_ZOMBIE:
self.zombie_groups[map_y].add(zombie.NormalZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.NormalZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.CONEHEAD_ZOMBIE:
self.zombie_groups[map_y].add(zombie.ConeHeadZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.ConeHeadZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.BUCKETHEAD_ZOMBIE:
self.zombie_groups[map_y].add(zombie.BucketHeadZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.BucketHeadZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.FLAG_ZOMBIE:
self.zombie_groups[map_y].add(zombie.FlagZombie(c.ZOMBIE_START_X, y, self.head_group))
elif name == c.NEWSPAPER_ZOMBIE:
self.zombie_groups[map_y].add(zombie.NewspaperZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.NewspaperZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.FOOTBALL_ZOMBIE:
self.zombie_groups[map_y].add(zombie.FootballZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.FootballZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.DUCKY_TUBE_ZOMBIE:
self.zombie_groups[map_y].add(zombie.DuckyTubeZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.DuckyTubeZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.CONEHEAD_DUCKY_TUBE_ZOMBIE:
self.zombie_groups[map_y].add(zombie.ConeHeadDuckyTubeZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.ConeHeadDuckyTubeZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.BUCKETHEAD_DUCKY_TUBE_ZOMBIE:
self.zombie_groups[map_y].add(zombie.BucketHeadDuckyTubeZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.BucketHeadDuckyTubeZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.SCREEN_DOOR_ZOMBIE:
self.zombie_groups[map_y].add(zombie.ScreenDoorZombie(c.ZOMBIE_START_X + randint(-20, 20) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.ScreenDoorZombie(c.ZOMBIE_START_X + random.randint(-20, 20) + hugeWaveMove, y, self.head_group))
elif name == c.POLE_VAULTING_ZOMBIE:
# 本来撑杆跳生成位置不同对齐左端可认为修正了一部分看作移动了70只需要相对修改即可
self.zombie_groups[map_y].add(zombie.PoleVaultingZombie(c.ZOMBIE_START_X + randint(0, 10) + hugeWaveMove, y, self.head_group))
self.zombie_groups[map_y].add(zombie.PoleVaultingZombie(c.ZOMBIE_START_X + random.randint(0, 10) + hugeWaveMove, y, self.head_group))
elif name == c.ZOMBONI:
# 冰车僵尸生成位置不同
self.zombie_groups[map_y].add(zombie.Zomboni(c.ZOMBIE_START_X + randint(0, 10) + hugeWaveMove, y, self.plant_groups[map_y], self.map, plant.IceFrozenPlot))
self.zombie_groups[map_y].add(zombie.Zomboni(c.ZOMBIE_START_X + random.randint(0, 10) + hugeWaveMove, y, self.plant_groups[map_y], self.map, plant.IceFrozenPlot))
elif name == c.SNORKELZOMBIE:
self.zombie_groups[map_y].add(zombie.SnorkelZombie(c.ZOMBIE_START_X + randint(0, 10) + hugeWaveMove, y, self.head_group))
# 潜水僵尸生成位置不同
self.zombie_groups[map_y].add(zombie.SnorkelZombie(c.ZOMBIE_START_X + random.randint(0, 10) + hugeWaveMove, y, self.head_group))
# 能否种植物的判断:
# 先判断位置是否合法 isValid(map_x, map_y)
@ -845,6 +847,9 @@ class Level(tool.State):
if pos is None:
return
# 恢复植物卡片样式
self.clickResult[1].clicked = False
if self.hint_image is None:
self.setupHintImage()
x, y = self.hint_rect.centerx, self.hint_rect.bottom
@ -924,7 +929,7 @@ class Level(tool.State):
mushroomSleep = False
self.plant_groups[map_y].add(new_plant)
# 种植植物后应当刷新僵尸的攻击对象
# 这里用植物名称代替布尔值,保存更多信息
# 用元组表示植物的名称和格子坐标
self.newPlantAndPositon = (new_plant.name, (map_x, map_y))
if self.bar_type == c.CHOOSEBAR_STATIC:
self.menubar.decreaseSunValue(self.select_plant.sun_cost)
@ -932,7 +937,7 @@ class Level(tool.State):
else:
self.menubar.deleateCard(self.select_plant)
if self.bar_type != c.CHOSSEBAR_BOWLING:
if self.bar_type != c.CHOSSEBAR_BOWLING: # 坚果保龄球关卡无需考虑格子被占用的情况
self.map.addMapPlant(map_x, map_y, self.plant_name, sleep=mushroomSleep)
self.removeMouseImage()
@ -1149,8 +1154,8 @@ class Level(tool.State):
for hypno_zombie in self.hypno_zombie_groups[i]:
if hypno_zombie.health <= 0:
continue
zombie_list = pg.sprite.spritecollide(hypno_zombie,
self.zombie_groups[i], False,collided_func)
zombie_list = pg.sprite.spritecollide( hypno_zombie, self.zombie_groups[i],
False, collided_func)
for zombie in zombie_list:
if zombie.state == c.DIE:
continue
@ -1372,7 +1377,7 @@ class Level(tool.State):
self.killPlant(plant)
def checkVictory(self):
if (c.ZOMBIE_LIST in self.map_data) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
if self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST:
if len(self.zombie_list) > 0:
return False
for i in range(self.map_y_len):
@ -1522,7 +1527,7 @@ class Level(tool.State):
surface.blit(self.restart_button, self.restart_button_rect)
surface.blit(self.mainMenu_button, self.mainMenu_button_rect)
if not ((c.ZOMBIE_LIST in self.map_data) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST):
if self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_AUTO:
self.showLevelProgress(surface)
if self.current_time - self.showHugeWaveApprochingTime <= 2000:
surface.blit(self.huge_wave_approching_image, self.huge_wave_approching_image_rect)

View File

@ -97,7 +97,7 @@ class Control():
while not self.done:
self.event_loop()
self.update()
pg.display.flip()
pg.display.update()
self.clock.tick(self.fps)
print('game over')
@ -106,7 +106,7 @@ def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
rect = image.get_rect()
image.blit(sheet, (0, 0), (x, y, width, height))
if colorkey != c.NULL:
if colorkey:
image.set_colorkey(colorkey)
image = pg.transform.scale(image,
(int(rect.width*scale),
@ -203,6 +203,10 @@ def loadPlantImageRect():
pg.init()
pg.display.set_caption(c.ORIGINAL_CAPTION) # 设置标题
SCREEN = pg.display.set_mode(c.SCREEN_SIZE) # 设置初始屏幕
try: # 设置窗口图标仅对非Nuitka时生效Nuitka不需要包括额外的图标文件自动跳过这一过程即可
pg.display.set_icon(pg.image.load(os.path.join(os.path.dirname(os.path.dirname(__file__)), c.ORIGINAL_LOGO)))
except:
pass
GFX = load_all_gfx(os.path.join(os.path.dirname(os.path.dirname(__file__)) ,os.path.join("resources","graphics")))
ZOMBIE_RECT = loadZombieImageRect()