diff --git a/README.md b/README.md index 8ecc53f..07eadc6 100644 --- a/README.md +++ b/README.md @@ -79,17 +79,17 @@ python pypvz.py * 使用鼠标收集阳光,种植植物 * 对于已经存在存档的用户,可以在`~\AppData\Roaming\wszqkzqk.dev\pypvz\userdata.json`(Windows)或`~/.config/wszqkzqk.dev/pypvz/userdata.json`(其他操作系统)中修改当前关卡: * 冒险模式: - * 1——引入:白昼模式——单行草皮 - * 2——引入:白昼模式——三行草皮 - * 3和4:白昼模式 - * 5和6:夜晚模式 - * 7、8和9:泳池模式 - * 10: 浓雾模式(暂时没有雾) + * 白昼模式——单行草皮:1 + * 白昼模式——三行草皮:2 + * 白昼模式:3~5 + * 夜晚模式:6~8 + * 泳池模式:9~11 + * 浓雾模式(暂时没有雾):12 * 小游戏模式: - * 1:坚果保龄球模式 - * 2:传送带模式(白天) - * 3:传送带模式(黑夜) - * 4:传送带模式(泳池) + * 坚果保龄球模式:1 + * 传送带模式(白天):2 + * 传送带模式(黑夜):3 + * 传送带模式(泳池):4 * 目前暂时按照以上设定,未与原版相符 * 可以通过修改存档JSON文件中的`game rate`值来调节游戏速度倍率 diff --git a/pypvz.py b/pypvz.py index 60aa395..e094c20 100755 --- a/pypvz.py +++ b/pypvz.py @@ -15,7 +15,7 @@ if __name__=="__main__": # 日志设置 if not os.path.exists(os.path.dirname(c.USERLOG_PATH)): os.makedirs(os.path.dirname(c.USERLOG_PATH)) - logger = logging.getLogger() + logger = logging.getLogger("main") formatter = logging.Formatter("%(asctime)s: %(message)s") fileHandler = RotatingFileHandler(c.USERLOG_PATH, "a", 1024*1024, 0, "utf-8") fileHandler.setFormatter(formatter) @@ -30,7 +30,8 @@ if __name__=="__main__": state_dict = { c.MAIN_MENU: mainmenu.Menu(), c.GAME_VICTORY: screen.GameVictoryScreen(), c.GAME_LOSE: screen.GameLoseScreen(), - c.LEVEL: level.Level() + c.LEVEL: level.Level(), + c.AWARD_SCREEN: screen.AwardScreen(), } game.setup_states(state_dict, c.MAIN_MENU) game.run() diff --git a/source/constants.py b/source/constants.py index 261ed12..2d9acf7 100755 --- a/source/constants.py +++ b/source/constants.py @@ -67,6 +67,7 @@ GOLD = (255, 215, 0) GREEN = ( 0, 255, 0) YELLOWGREEN = ( 55, 200, 0) LIGHTGRAY = (107, 108, 145) +PARCHMENT_YELLOW = (207, 146, 83) # 退出游戏按钮 EXIT = "exit" @@ -78,6 +79,7 @@ MAINMENU_BUTTON = "mainMenuButton" LITTLEGAME_BUTTON = "littleGameButton" OPTION_BUTTON = "optionButton" SOUND_VOLUME_BUTTON = "volumeButton" +UNIVERSAL_BUTTON = "universalButton" # 金银向日葵奖杯 TROPHY_SUNFLOWER = "sunflowerTrophy" # 小铲子 @@ -103,9 +105,10 @@ SOUND_VOLUME = "volume" # 整个游戏的状态 MAIN_MENU = "main menu" LOAD_SCREEN = "load screen" -GAME_LOSE = "game los" +GAME_LOSE = "game lose" GAME_VICTORY = "game victory" LEVEL = "level" +AWARD_SCREEN = "award screen" # 界面图片文件名 MAIN_MENU_IMAGE = "MainMenu" diff --git a/source/state/level.py b/source/state/level.py index 342385a..65c8113 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -2,9 +2,11 @@ import os import json import pygame as pg import random +import logging from .. import tool from .. import constants as c from ..component import map, plant, zombie, menubar +logger = logging.getLogger("main") class Level(tool.State): def __init__(self): @@ -42,19 +44,19 @@ class Level(tool.State): def loadMap(self): # 冒险模式 if self.game_info[c.GAME_MODE] == c.MODE_ADVENTURE: - if self.game_info[c.LEVEL_NUM] < map.TOTAL_LEVEL: + if 0 <= self.game_info[c.LEVEL_NUM] < map.TOTAL_LEVEL: self.map_data = map.LEVEL_MAP_DATA[self.game_info[c.LEVEL_NUM]] else: print("成功通关冒险模式!") self.game_info[c.LEVEL_NUM] = 1 self.game_info[c.LEVEL_COMPLETIONS] += 1 self.done = True - self.next = c.MAIN_MENU + self.next = c.LEVEL self.saveUserData() return # 小游戏模式 elif self.game_info[c.GAME_MODE] == c.MODE_LITTLEGAME: - if self.game_info[c.LITTLEGAME_NUM] < map.TOTAL_LITTLE_GAME: + if 0 <= self.game_info[c.LITTLEGAME_NUM] < map.TOTAL_LITTLE_GAME: self.map_data = map.LITTLE_GAME_MAP_DATA[self.game_info[c.LITTLEGAME_NUM]] else: print("成功通关玩玩小游戏!") @@ -150,7 +152,7 @@ class Level(tool.State): zombieList.append(newZombie) volume -= c.CREATE_ZOMBIE_DICT[newZombie][0] if volume < 0: - print(f'警告:第{wave}波中手动设置的僵尸级别总数超过上限!') + logger.warning(f'警告:第{wave}波中手动设置的僵尸级别总数超过上限!') # 防止因为僵尸最小等级过大,使得总容量无法完全利用,造成死循环的检查机制 minCost = c.CREATE_ZOMBIE_DICT[min(useableZombies, key=lambda x:c.CREATE_ZOMBIE_DICT[x][0])][0] diff --git a/source/state/screen.py b/source/state/screen.py index ff6632f..332ad1e 100644 --- a/source/state/screen.py +++ b/source/state/screen.py @@ -16,8 +16,7 @@ class Screen(tool.State): def set_next_state(self): pass - def setupImage(self, name): - frame_rect = [0, 0, 800, 600] + def setupImage(self, name, frame_rect=(0, 0, 800, 600)): self.image = tool.get_image(tool.GFX[name], *frame_rect) self.rect = self.image.get_rect() self.rect.x = 0 @@ -68,17 +67,87 @@ class GameLoseScreen(Screen): self.persist = persist self.game_info = persist name = self.getImageName() - self.setupImage(name) + self.setupImage(name, (-15, 0, 800, 600)) self.next = self.set_next_state() pg.display.set_caption("pypvz: 战斗失败!") # 播放失败音效 c.SOUND_LOSE.play() c.SOUND_SCREAM.play() -class AwardScreen(Screen): +class AwardScreen(tool.State): def __init__(self): - Screen.__init__() + tool.State.__init__(self) - def getImageName(self): - return c.AWARD_SCREEN_IMAGE + def setupImage(self, gainedTrophy=True): + # 主体 + frame_rect = (0, 0, 800, 600) + self.image = tool.get_image(tool.GFX[c.AWARD_SCREEN_IMAGE], *frame_rect) + self.rect = self.image.get_rect() + self.rect.x = 0 + self.rect.y = 0 + # 文字 + # 标题处文字 + font = pg.font.Font(c.FONT_PATH, 37) + title_text = font.render("您得到了新的战利品!", True, c.PARCHMENT_YELLOW) + title_text_rect = title_text.get_rect() + title_text_rect.x = 220 + title_text_rect.y = 23 + self.image.blit(title_text, title_text_rect) + + # 按钮 + frame_rect = (0, 0, 111, 26) + if gainedTrophy: + ## 主菜单按钮 + main_menu_button_image = tool.get_image(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect) + main_menu_button_image_rect = main_menu_button_image.get_rect() + main_menu_button_image_rect.x = 343 + main_menu_button_image_rect.y = 520 + ### 主菜单按钮上的文字 + font = pg.font.Font(c.FONT_PATH, 18) + main_menu_text = font.render("主菜单", True, c.NAVYBLUE) + main_menu_text_rect = main_menu_text.get_rect() + main_menu_text_rect.x = 29 + main_menu_button_image.blit(main_menu_text, main_menu_text_rect) + self.image.blit(main_menu_button_image, main_menu_button_image_rect) + else: + ## 继续按钮 + next_button_image = tool.get_image(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect) + next_button_image_rect = next_button_image.get_rect() + next_button_image_rect.x = 70 + ### 继续按钮上的文字 + font = pg.font.Font(c.FONT_PATH, 18) + next_text = font.render("继续", True, c.NAVYBLUE) + next_text_rect = next_text.get_rect() + next_text_rect.x = 37 + ## 主菜单按钮 + main_menu_button_image = tool.get_image(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect) + main_menu_button_image_rect = main_menu_button_image.get_rect() + main_menu_button_image_rect.x = 620 + next_button_image_rect.y = main_menu_button_image_rect.y = 540 + ### 主菜单按钮上的文字 + main_menu_text = font.render("主菜单", True, c.NAVYBLUE) + main_menu_text_rect = main_menu_text.get_rect() + main_menu_text_rect.x = 29 + next_button_image.blit(next_text, next_text_rect) + main_menu_button_image.blit(main_menu_text, main_menu_text_rect) + self.image.blit(next_button_image, next_button_image_rect) + self.image.blit(main_menu_button_image, main_menu_button_image_rect) + + + def startup(self, current_time, persist): + self.start_time = current_time + self.persist = persist + self.game_info = persist + self.setupImage() + + def update(self, surface, current_time, mouse_pos, mouse_click): + surface.fill(c.WHITE) + surface.blit(self.image, self.rect) + + def inArea(self, rect, x, y): + if (x >= rect.x and x <= rect.right and + y >= rect.y and y <= rect.bottom): + return True + else: + return False