对于我的pygame Tower Defense程序,我有一个名为main.py
的python文件,它创建了一个名为Menu
的类的实例(它位于一个名为startup.py
的单独模块中
)启动游戏的主菜单。
菜单屏幕上的一个按钮然后在另一个名为main
的python模块中运行(单击时)一个名为mapgen.py
的函数。此功能包含运行主游戏和更新屏幕所需的所有代码。它为必要的类创建实例,然后在while循环中运行所有类函数:
def main():
global money
money = side.Money()
global health
health = side.Health()
global live_grid
live_grid = Grid() #Creates instance of grid
global live_sidebar
live_sidebar = side.Sidebar() #Creates instance of sidebar
while True:
money.money_update() #Updates the current money of the player
live_grid.blit_grid() #Blits the grid background
live_sidebar.event_main() #Runs event handler for the sidebar to update any information there
live_sidebar.blit_sidebar() #Blits the sidebar
pg.display.update()
C.clock.tick(C.FPS)
我将main
(主游戏循环)作为一个函数的原因是我可以从startup
模块(包含主菜单)调用它。
然而,这使我无法制作暂停屏幕,因为我无法在不启动课程的情况下恢复该功能。
我还需要能够从其他模块访问类的实例。这就是我为模块创建全局实例的原因。
如果我尝试在函数之外创建类的实例以避免这种情况,我会得到错误,我认为这是由于python导入模块的方式引起的,如下所示:
Traceback (most recent call last):
File ".\main.py", line 2, in <module>
import startup, config as C
File "C:\Users\bobsh\Programming Project\Version 0.7b\startup.py", line 2, in <module>
import config as C, button as B, mapgen
File "C:\Users\bobsh\Programming Project\Version 0.7b\button.py", line 2, in <module>
import mapgen, config as C, startup
File "C:\Users\bobsh\Programming Project\Version 0.7b\mapgen.py", line 140, in <module>
font = B.font
AttributeError: module 'button' has no attribute 'font' (even though it does)
这是一个相当长的问题,但我应该如何构建我的while循环以及随后的任何其他代码,以便我能够轻松创建暂停屏幕(基本上中断主游戏过程,以便玩家可以选择是否退出或恢复)并从Menu
中的startup.py
班级运行游戏?
这是我的代码的Github gist,这里是运行游戏本身所需的一切Dropbox。
我非常感谢任何人都可以提供的任何帮助。
答案 0 :(得分:0)
这个答案将分为两部分,一部分向您展示如何在您的main()
功能中隐藏暂停屏幕,另一部分向您概述如何更好地构建代码。
将暂停屏幕隐藏到main()
功能
好吧,这绝不是最好的方法,但我认为这也不是一个坏方法。这非常简单。
#main game function
def main():
#Creates instances of necessary classes
global money
money = side.Money()
global health
health = side.Health()
global live_grid
live_grid = Grid()
global live_sidebar
live_sidebar = side.Sidebar()
paused = False
while True:
# Pause functionality
keys = pg.keys.get_pressed();
if keys[pg.k_SPACE]:
if paused:
paused = False
else:
paused = True
if not paused:
money.money_update() #Updates the current money of the player
live_grid.blit_grid() #Blits the grid background
live_sidebar.event_main() #Runs event handler for the sidebar to update any information there
live_sidebar.blit_sidebar() #Blits the sidebar
pg.display.update()
if paused:
# Pause menu code goes here
C.clock.tick(C.FPS)
这就是它。我已经大量使用这种技术将不同的菜单,按钮等叠加到主游戏屏幕上,它的效果非常好。对于像暂停屏幕这样简单的东西,我认为创建另一个类或函数没有任何意义,因为那时你必须重新初始化类,确保你在游戏中的同一个地方等等。
以更好的方式构建代码:
你的游戏是我喜欢称之为“多米诺骨牌效应”的受害者。这个术语非常明显。你调用一个函数,然后调用另一个函数,依此类推。
这可以通过取出创建此多米诺骨牌效果的线条来解决,而是在实际执行游戏的文件中调用该函数:main.py
。
我将以第一个例子向您展示如何做到这一点。
class Menu():
def __init__(self):
pg.init()
self.screen = C.screen
self.button_x = C.game_screen_full_w * 0.4
self.button_y = [C.game_screen_h * 0.30, C.game_screen_h * 0.50, C.game_screen_h * 0.70]
self.play_button = B.Button("mapgen.main()", (140, 40), (self.button_x,self.button_y[0]), C.L_BLUE, C.BLUE, None, C.DARK_GREY, C.L_BLUE , "Play")
self.lead_button = B.Button("startup.Lead()", (200, 40), (self.button_x - 30,self.button_y[1]), C.L_BLUE, C.BLUE, None, C.DARK_GREY, C.L_BLUE, "Leaderboard")
self.quit_button = B.Button("quit()", (140, 40), (self.button_x,self.button_y[2]), C.L_BLUE, C.BLUE, None, C.DARK_GREY, C.L_BLUE, "Quit")
self.vol_button = B.Button(None, (50,50), (40,40), C.L_BLUE, C.BLUE, None, C.DARK_GREY, C.L_BLUE, "♫")
#self.menu_screen()
请注意,我注释掉了最后一行。该行调用另一个在其中具有while
循环的函数。如您所见,这会产生多米诺骨牌效应。
现在在main.py
你可以自己添加一行。
if __name__ == '__main__':
live_menu = startup.Menu()
live_menu.menu_screen()
我看到的下一个例子是第if event.button == 1 and self.action is not None: exec(self.action)
行。修改按钮代码,使其不调用该功能。提示:您可以返回一个值,并使用它从main.py
之类的地方调用该函数。
至于导入模块,我看到没有问题。导入模块时,没有运行代码,因为您只定义了类和函数。您收到了错误,因为font
后没有括号。该行应为font = B.font()
。
但是,当你说你不能在函数之外实例化类时,你是对的。你不能因为当你导入文件时,你正在运行那行代码。如果你想要,你也可以把它代码放入它自己的函数中,只调用一次。
完成后,您的代码应该更好一些。
作为开始时构建代码的经验法则:仅在一个文件中实例化类;只在一个文件中创建函数,而不是方法,函数;尝试尽可能限制多米诺骨牌效应,以便您的代码尽可能易于管理。
如果您需要任何指导,请查看this repo中的代码。所有代码都在一个文件中。
祝你好运!我希望这个答案对你有帮助,如果你有任何问题,请随时在下面发表评论!