diff --git a/resources/data/map/level_0.json b/resources/data/map/level_0.json index 77b1ded..fe4ab6f 100644 --- a/resources/data/map/level_0.json +++ b/resources/data/map/level_0.json @@ -2,6 +2,7 @@ "background_type":2, "init_sun_value":5000, "shovel":1, + "spawn_zombies":"zombie_list", "zombie_list":[ {"time":1000, "map_y":2, "name":"FootballZombie"}, {"time":60000, "map_y":2, "name":"Zombie"} diff --git a/resources/data/map/level_1.json b/resources/data/map/level_1.json index 359abec..a6c40b3 100644 --- a/resources/data/map/level_1.json +++ b/resources/data/map/level_1.json @@ -2,6 +2,9 @@ "background_type": 0, "init_sun_value": 50, "shovel": 1, + "spawn_zombies":"auto", + "included_zombies":["Zombie"], + "num_flags":2, "zombie_list": [ { "time": 20000, "name": "Zombie" }, { "time": 40000, "name": "FlagZombie" }, diff --git a/resources/data/map/level_2.json b/resources/data/map/level_2.json index eb21058..85166dc 100644 --- a/resources/data/map/level_2.json +++ b/resources/data/map/level_2.json @@ -2,6 +2,8 @@ "background_type":0, "init_sun_value":50, "shovel":1, + "spawn_zombies":"auto", + "num_flags":3, "zombie_list":[ {"time":20000, "name":"Zombie"}, {"time":40000, "name":"FlagZombie"}, diff --git a/resources/data/map/level_3.json b/resources/data/map/level_3.json index 02bf49a..ce6bd5f 100644 --- a/resources/data/map/level_3.json +++ b/resources/data/map/level_3.json @@ -2,6 +2,8 @@ "background_type":1, "init_sun_value":50, "shovel":1, + "spawn_zombies":"auto", + "num_flags":3, "zombie_list":[ {"time":20000, "name":"Zombie"}, {"time":40000, "name":"ConeheadZombie"}, diff --git a/resources/data/map/level_4.json b/resources/data/map/level_4.json index 306f9c7..ac030af 100644 --- a/resources/data/map/level_4.json +++ b/resources/data/map/level_4.json @@ -2,6 +2,8 @@ "background_type":2, "init_sun_value":50, "shovel":1, + "spawn_zombies":"auto", + "num_flags":4, "zombie_list":[ {"time":20000, "name":"Zombie"}, {"time":40000, "name":"ConeheadZombie"}, diff --git a/resources/data/map/littleGame_1.json b/resources/data/map/littleGame_1.json index 7b58813..69c0ceb 100644 --- a/resources/data/map/littleGame_1.json +++ b/resources/data/map/littleGame_1.json @@ -2,6 +2,8 @@ "background_type":0, "choosebar_type":1, "shovel":1, + "spawn_zombies":"auto", + "num_flags":4, "card_pool":[ {"name":"Peashooter"}, {"name":"SnowPea"}, diff --git a/resources/data/map/littleGame_2.json b/resources/data/map/littleGame_2.json index 9f2e217..1a4feab 100644 --- a/resources/data/map/littleGame_2.json +++ b/resources/data/map/littleGame_2.json @@ -2,6 +2,8 @@ "background_type":6, "choosebar_type":2, "shovel":0, + "spawn_zombies":"auto", + "num_flags":4, "card_pool":[ {"name":"WallNutBowling"}, {"name":"RedWallNutBowling"} diff --git a/source/constants.py b/source/constants.py index f2822d5..bac3c2b 100755 --- a/source/constants.py +++ b/source/constants.py @@ -97,6 +97,15 @@ BACKGROUND_WALLNUTBOWLING = 6 BACKGROUND_SINGLE = 7 BACKGROUND_TRIPLE = 8 +# 僵尸生成方式 +SPAWN_ZOMBIES = 'spawn_zombies' +SPAWN_ZOMBIES_AUTO = 'auto' +SPAWN_ZOMBIES_LIST = 'list' +NUM_FLAGS = 'num_flags' +INEVITABLE_ZOMBIE_DICT = 'inevitable_zombie_list' +SURVIVAL_ROUNDS = 'survival_rounds' + + # 地图单元格属性 MAP_PLANT = 'plantnames' MAP_SLEEP = 'sleep' # 有没有休眠的蘑菇,作是否能种植咖啡豆的判断 diff --git a/source/state/level.py b/source/state/level.py index 7269313..bcc255b 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -104,12 +104,57 @@ class Level(tool.State): self.hypno_zombie_groups.append(pg.sprite.Group()) self.bullet_groups.append(pg.sprite.Group()) + # 新的僵尸生成机制:级别——权重生成 + self.createZombieInfo = {# 生成僵尸:(级别, 权重) + c.NORMAL_ZOMBIE:(1, 4000), + c.FLAG_ZOMBIE:(1, 0), + c.CONEHEAD_ZOMBIE:(2, 4000), + c.BUCKETHEAD_ZOMBIE:(4, 3000), + c.NEWSPAPER_ZOMBIE:(2, 1000), + c.FOOTBALL_ZOMBIE:(2, 2000) + } + + # 按照规则生成每一波僵尸 + # 可以考虑将波刷新和一波中的僵尸生成分开 + # useableZombie是指可用的僵尸种类的元组 + # inevitableZombie指在本轮必然出现的僵尸,输入形式为字典: {波数1:(僵尸1, 僵尸2……), 波数2:(僵尸1, 僵尸2……)……} + def createWaves(self, useableZombies, numFlags, survivalRounds=0, inevitableZombieDict=None): + waves = [] + + # 权重值 + weights = [] + for zombie in useableZombies: + weights.append(self.createZombieInfo[zombie][1]) + + # 按照原版pvz设计的僵尸容量函数,是从无尽解析的,但是普通关卡也可以遵循 + for wave in range(1, 10 * numFlags + 1): + volume = int(int((wave + survivalRounds*20)*0.8)/2) + 1 + if wave % 10 == 0: + volume = int(volume*2.5) + zombieList = [] + + if inevitableZombieDict and (wave in inevitableZombieDict.keys()): + for newZombie in inevitableZombieDict[wave]: + zombieList += newZombie + volume -= self.createZombieInfo[newZombie][0] + if volume < 0: + print('警告:第{}波中手动设置的僵尸级别总数超过上限!'.format(wave)) + + while (volume > 0) and (len(zombieList) < 50): + newZombie = choices(useableZombies, weights) # 注意这个的输出是列表 + if self.createZombieInfo[newZombie][0] <= volume: + zombieList += newZombie + volume -= self.createZombieInfo[newZombie][0] + waves.append(zombieList) + + self.waves = waves + def setupZombies(self): def takeTime(element): return element[0] self.zombie_list = [] - # 目前设置为从JSON文件中读取僵尸出现的时间、种类、位置信息,以后可以将时间设置为模仿原版的机制,位置设置为随机数 + # 目前设置为从JSON文件中读取僵尸出现的时间、种类、位置信息,以后可以将时间设置为模仿原版的机制 for data in self.map_data[c.ZOMBIE_LIST]: if 'map_y' in data.keys(): self.zombie_list.append((data['time'], data['name'], data['map_y'])) @@ -199,7 +244,19 @@ class Level(tool.State): self.removeMouseImage() self.setupGroups() - self.setupZombies() + if (c.ZOMBIE_LIST in self.map_data.keys()) and self.map_data[c.SPAWN_ZOMBIES] == c.SPAWN_ZOMBIES_LIST: + self.setupZombies() + else: + # 暂时没有生存模式,所以 survivalRounds = 0 + if c.INEVITABLE_ZOMBIE_DICT in self.map_data.keys(): + self.createWaves( useableZombies=self.map_data[c.USEABLE_ZOMBIES], + numFlags=self.map_data[c.NUM_FLAGS], + survivalRounds=0, + inevitableZombieDict=self.map_data[c.INEVITABLE_ZOMBIE_DICT]) + else: + self.createWaves( useableZombies=self.map_data[c.USEABLE_ZOMBIES], + numFlags=self.map_data[c.NUM_FLAGS], + survivalRounds=0) self.setupCars() # 地图有铲子才添加铲子 @@ -217,16 +274,6 @@ class Level(tool.State): self.setupLittleMenu() - # 新的僵尸生成机制:级别——权重生成 - self.createZombieInfo = {# 生成僵尸:(级别, 权重) - c.NORMAL_ZOMBIE:(1, 4000), - c.FLAG_ZOMBIE:(1, 0), - c.CONEHEAD_ZOMBIE:(2, 4000), - c.BUCKETHEAD_ZOMBIE:(4, 3000), - c.NEWSPAPER_ZOMBIE:(2, 1000), - c.FOOTBALL_ZOMBIE:(2, 2000) - } - # 小菜单 def setupLittleMenu(self): # 具体运行游戏必定有个小菜单, 导入菜单和选项 @@ -451,42 +498,6 @@ class Level(tool.State): self.checkGameState() - # 按照规则生成每一波僵尸 - # 可以考虑将波刷新和一波中的僵尸生成分开 - # useableZombie是指可用的僵尸种类的元组 - # inevitableZombie指在本轮必然出现的僵尸,输入形式为字典: {波数1:(僵尸1, 僵尸2……), 波数2:(僵尸1, 僵尸2……)……} - def createWaves(self, useableZombies, numFlags, survivalRounds=0, inevitableZombieDict=None): - waves = [] - - # 权重值 - weights = [] - for zombie in useableZombies: - weights.append(self.createZombieInfo[zombie][1]) - - # 按照原版pvz设计的僵尸容量函数,是从无尽解析的,但是普通关卡也可以遵循 - for wave in range(1, 10 * numFlags + 1): - volume = int(int((wave + survivalRounds*20)*0.8)/2) + 1 - if wave % 10 == 0: - volume = int(volume*2.5) - zombieList = [] - - if inevitableZombieDict and (wave in inevitableZombieDict.keys()): - for newZombie in inevitableZombieDict[wave]: - zombieList += newZombie - volume -= self.createZombieInfo[newZombie][0] - if volume < 0: - print('警告:第{}波中手动设置的僵尸级别总数超过上限!'.format(wave)) - - while (volume > 0) and (len(zombieList) < 50): - newZombie = choices(useableZombies, weights) # 注意这个的输出是列表 - if self.createZombieInfo[newZombie][0] <= volume: - zombieList += newZombie - volume -= self.createZombieInfo[newZombie][0] - waves.append(zombieList) - - self.waves = waves - - def createZombie(self, name, map_y=None): # 有指定时按照指定生成,无指定时随机位置生成 # 0:白天 1:夜晚 2:泳池 3:浓雾 4:屋顶 5:月夜 6:坚果保龄球