From 81dcdfb76d4ebca48dc2761a6db6f2adcd4967df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AA?= <30586666+callmebg@users.noreply.github.com> Date: Tue, 24 Nov 2020 18:44:44 +0800 Subject: [PATCH] fix --- .gitignore | 2 ++ resources/data/map/level_1.json | 2 +- source/component/menubar.py | 1 + source/component/zombie.py | 15 ++++++------ source/main.py | 3 ++- source/state/level.py | 4 +++- source/state/mainmenu.py | 9 +++++-- source/tool.py | 42 ++++++++++++++++++++++++--------- 8 files changed, 55 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 20bcfb7..25706da 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ main.spec .vscode/ __pycache__/ */__pycache__/ +# ignore test +test.py diff --git a/resources/data/map/level_1.json b/resources/data/map/level_1.json index 59801a4..cc14eda 100644 --- a/resources/data/map/level_1.json +++ b/resources/data/map/level_1.json @@ -1,6 +1,6 @@ { "background_type":0, - "init_sun_value":50, + "init_sun_value":5000, "zombie_list":[ {"time":20000, "map_y":0, "name":"Zombie"}, {"time":40000, "map_y":2, "name":"FlagZombie"}, diff --git a/source/component/menubar.py b/source/component/menubar.py index 265d5d4..58730d7 100644 --- a/source/component/menubar.py +++ b/source/component/menubar.py @@ -216,6 +216,7 @@ class MenuBar(): for card in self.card_list: card.draw(surface) +# 关卡模式选植物的界面 class Panel(): def __init__(self, card_list, sun_value): self.loadImages(sun_value) diff --git a/source/component/zombie.py b/source/component/zombie.py index dd9835c..1ac0ce0 100644 --- a/source/component/zombie.py +++ b/source/component/zombie.py @@ -20,7 +20,7 @@ class Zombie(pg.sprite.Sprite): self.health = health self.damage = damage self.dead = False - self.losHead = False + self.lostHead = False self.helmet = False self.head_group = head_group @@ -64,7 +64,7 @@ class Zombie(pg.sprite.Sprite): def walking(self): if self.health <= 0: self.setDie() - elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead: + elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead: self.changeFrames(self.losthead_walk_frames) self.setLostHead() elif self.health <= c.NORMAL_HEALTH and self.helmet: @@ -83,7 +83,7 @@ class Zombie(pg.sprite.Sprite): def attacking(self): if self.health <= 0: self.setDie() - elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead: + elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead: self.changeFrames(self.losthead_attack_frames) self.setLostHead() elif self.health <= c.NORMAL_HEALTH and self.helmet: @@ -107,7 +107,7 @@ class Zombie(pg.sprite.Sprite): def freezing(self): if self.health <= 0: self.setDie() - elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead: + elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead: if self.old_state == c.WALK: self.changeFrames(self.losthead_walk_frames) else: @@ -117,7 +117,7 @@ class Zombie(pg.sprite.Sprite): self.setWalk() def setLostHead(self): - self.losHead = True + self.lostHead = True if self.head_group is not None: self.head_group.add(ZombieHead(self.rect.centerx, self.rect.bottom)) @@ -181,7 +181,7 @@ class Zombie(pg.sprite.Sprite): if self.helmet: self.changeFrames(self.helmet_walk_frames) - elif self.losHead: + elif self.lostHead: self.changeFrames(self.losthead_walk_frames) else: self.changeFrames(self.walk_frames) @@ -195,7 +195,7 @@ class Zombie(pg.sprite.Sprite): if self.helmet: self.changeFrames(self.helmet_attack_frames) - elif self.losHead: + elif self.lostHead: self.changeFrames(self.losthead_attack_frames) else: self.changeFrames(self.attack_frames) @@ -270,6 +270,7 @@ class NormalZombie(Zombie): self.frames = self.walk_frames +# 路障僵尸 class ConeHeadZombie(Zombie): def __init__(self, x, y, head_group): Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, c.CONEHEAD_HEALTH, head_group) diff --git a/source/main.py b/source/main.py index 7734e25..b1badeb 100644 --- a/source/main.py +++ b/source/main.py @@ -6,10 +6,11 @@ from .state import mainmenu, screen, level # create a standard game def main(): + # 控制状态机运行 game = tool.Control() state_dict = {c.MAIN_MENU: mainmenu.Menu(), c.GAME_VICTORY: screen.GameVictoryScreen(), c.GAME_LOSE: screen.GameLoseScreen(), c.LEVEL: level.Level()} game.setup_states(state_dict, c.MAIN_MENU) - game.main() \ No newline at end of file + game.run() \ No newline at end of file diff --git a/source/state/level.py b/source/state/level.py index 6ef4e9b..dd4d4e3 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -66,7 +66,8 @@ class Level(tool.State): for i in range(self.map_y_len): _, y = self.map.getMapGridPos(0, i) self.cars.append(plant.Car(-25, y+20, i)) - + + # 更新函数每帧被调用,将鼠标事件传入给状态处理函数 def update(self, surface, current_time, mouse_pos, mouse_click): self.current_time = self.game_info[c.CURRENT_TIME] = current_time if self.state == c.CHOOSE: @@ -83,6 +84,7 @@ class Level(tool.State): self.map.setMapGridType(x, y, c.MAP_EXIST) def initState(self): + # 小游戏才有CHOOSEBAR_TYPE if c.CHOOSEBAR_TYPE in self.map_data: self.bar_type = self.map_data[c.CHOOSEBAR_TYPE] else: diff --git a/source/state/mainmenu.py b/source/state/mainmenu.py index 98c96b7..168af18 100644 --- a/source/state/mainmenu.py +++ b/source/state/mainmenu.py @@ -16,6 +16,10 @@ class Menu(tool.State): def setupBackground(self): frame_rect = [80, 0, 800, 600] + # 1、形参中加单星号,即f(*x)则表示x为元组,所有对x的操作都应将x视为元组类型进行。 + # 2、双星号同上,区别是x视为字典。 + # 3、在变量前加单星号表示将元组(列表、集合)拆分为单个元素。 + # 4、双星号同上,区别是目标为字典,字典前加单星号的话可以得到“键”。 self.bg_image = tool.get_image(tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect) self.bg_rect = self.bg_image.get_rect() self.bg_rect.x = 0 @@ -27,8 +31,7 @@ class Menu(tool.State): frame_rect = [0, 0, 165, 77] for name in frame_names: - self.option_frames.append(tool.get_image(tool.GFX[name], *frame_rect, c.BLACK, 1.7)) - + self.option_frames.append(tool.get_image_menu(tool.GFX[name], *frame_rect, c.BLACK, 1.7)) self.option_frame_index = 0 self.option_image = self.option_frames[self.option_frame_index] self.option_rect = self.option_image.get_rect() @@ -50,10 +53,12 @@ class Menu(tool.State): def update(self, surface, current_time, mouse_pos, mouse_click): self.current_time = self.game_info[c.CURRENT_TIME] = current_time + # 没有选到选项时,检查有没有点到选项 if not self.option_clicked: if mouse_pos: self.checkOptionClick(mouse_pos) else: + # 点到后播放动画 if(self.current_time - self.option_timer) > 200: self.option_frame_index += 1 if self.option_frame_index >= 2: diff --git a/source/tool.py b/source/tool.py index 6fff94a..ed5aa53 100644 --- a/source/tool.py +++ b/source/tool.py @@ -2,6 +2,7 @@ import os import json from abc import abstractmethod import pygame as pg +from pygame.locals import * from . import constants as c # an abstract class, one state of automata @@ -9,18 +10,19 @@ class State(): def __init__(self): self.start_time = 0.0 self.current_time = 0.0 - self.done = False # is it finished - self.next = None - self.persist = {} + self.done = False # false 代表未做完 + self.next = None # 表示这个状态退出后要转到的下一个状态 + self.persist = {} # 在状态间转换时需要传递的数据 + # 当从其他状态进入这个状态时,需要进行的初始化操作 @abstractmethod def startup(self, current_time, persist): '''abstract method''' - + # 当从这个状态退出时,需要进行的清除操作 def cleanup(self): self.done = False return self.persist - + # 在这个状态运行时进行的更新操作 @abstractmethod def update(self, surface, keys, current_time): '''abstract method''' @@ -30,7 +32,7 @@ class Control(): def __init__(self): self.screen = pg.display.get_surface() self.done = False - self.clock = pg.time.Clock() + self.clock = pg.time.Clock() # 创建一个对象来帮助跟踪时间 self.fps = 60 self.keys = pg.key.get_pressed() self.mouse_pos = None @@ -49,14 +51,18 @@ class Control(): self.state.startup(self.current_time, self.game_info) def update(self): + # 返回自 pygame_init() 调用以来的毫秒数 self.current_time = pg.time.get_ticks() + if self.state.done: self.flip_state() + self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click) self.mouse_pos = None self.mouse_click[0] = False self.mouse_click[1] = False + # 状态转移 def flip_state(self): previous, self.state_name = self.state_name, self.state.next persist = self.state.cleanup() @@ -75,11 +81,11 @@ class Control(): self.mouse_pos = pg.mouse.get_pos() self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed() print('pos:', self.mouse_pos, ' mouse:', self.mouse_click) - else: - print(pg.event.event_name(event.type)) + #else: + # print(pg.event.event_name(event.type)) - def main(self): + def run(self): while not self.done: self.event_loop() self.update() @@ -98,6 +104,18 @@ def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1): int(rect.height*scale))) return image +def get_image_menu(sheet, x, y, width, height, colorkey=c.BLACK, scale=1): + # 一定要保留阿尔法通道,修复主菜单bug,游戏中car显示又有bug + image = pg.Surface([width, height], SRCALPHA) + rect = image.get_rect() + + image.blit(sheet, (0, 0), (x, y, width, height)) + image.set_colorkey(colorkey) + image = pg.transform.scale(image, + (int(rect.width*scale), + int(rect.height*scale))) + return image + def load_image_frames(directory, image_name, colorkey, accept): frame_list = [] tmp = {} @@ -121,6 +139,7 @@ def load_image_frames(directory, image_name, colorkey, accept): frame_list.append(tmp[i]) return frame_list +# colorkeys 是设置图像中的某个颜色值为透明,这里用来消除白边 def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')): graphics = {} for name1 in os.listdir(directory): @@ -156,6 +175,7 @@ def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '. graphics[name] = img return graphics +# 从文件加载矩形碰撞范围 def loadZombieImageRect(): file_path = os.path.join('resources', 'data', 'entity', 'zombie.json') f = open(file_path) @@ -171,8 +191,8 @@ def loadPlantImageRect(): return data[c.PLANT_IMAGE_RECT] pg.init() -pg.display.set_caption(c.ORIGINAL_CAPTION) -SCREEN = pg.display.set_mode(c.SCREEN_SIZE) +pg.display.set_caption(c.ORIGINAL_CAPTION) # 设置标题 +SCREEN = pg.display.set_mode(c.SCREEN_SIZE) # 设置初始屏幕 GFX = load_all_gfx(os.path.join("resources","graphics")) ZOMBIE_RECT = loadZombieImageRect()