在Python中,如何通过具有属性的类甚至函数返回变量甚至值?

在Python中,如何通过具有属性的类甚至函数返回变量甚至值?,python,pygame,Python,Pygame,因此,我正在用python为一个隐形游戏编写代码,我正在使用pygame模块,但这个问题可能与它无关。我的菜单中有几个阶段,我正在采用面向对象的方法。我是面向对象的新手,所以请不要太讨厌我的代码!其中按钮是为有播放和退出按钮的菜单生成的。然后,在旧按钮上加载Easy、medium、hard和Experiant按钮,以前的按钮失去功能,然后在以前的按钮上加载Level的1、2、3和4按钮(如果有意义的话)。然而,按照我编写代码的方式,我需要变量阶段,其中阶段1是播放和退出,阶段2是难度,阶段3是传

因此,我正在用python为一个隐形游戏编写代码,我正在使用pygame模块,但这个问题可能与它无关。我的菜单中有几个阶段,我正在采用面向对象的方法。我是面向对象的新手,所以请不要太讨厌我的代码!其中按钮是为有播放和退出按钮的菜单生成的。然后,在旧按钮上加载Easy、medium、hard和Experiant按钮,以前的按钮失去功能,然后在以前的按钮上加载Level的1、2、3和4按钮(如果有意义的话)。然而,按照我编写代码的方式,我需要变量阶段,其中阶段1是播放和退出,阶段2是难度,阶段3是传递给它需要的方法和类的级别号。我不知道如何在不声明带有全局范围的变量的情况下实现这一点,我认为这违背了OOP的目的。那我该怎么办?因为除此之外,代码只接受输入,并通过所有按钮直到结束。 这是我的代码,你需要的图像,我猜至少是文本文件

#Stealth Assassin
import pygame #Imports the pygame module inclulding many in built functions that aids in game design
import time #Imports the time module for which I can implement delays into my program

pygame.init() #Runs pygame
clock = pygame.time.Clock() #Intialises the variable to control the game clock (FPS)
gameDisplay = pygame.display.set_mode((1920,1080),pygame.FULLSCREEN) #Variable which will set the resolution of the game window and put the window into fullscreen mode
pygame.display.set_caption("Stealth Assassin") #Sets the title of the pygame window for the game

class DisplayImage: #This class contains methods required to load images into the game

    def __init__(self, filename, xpos, ypos): #Method used to allow the class to intialise attributes

        self.filename = filename #Defines filename as the filename attribute passed through
        self.xpos = xpos #Defines the x axis positioning of the image as the attribute passed through
        self.ypos = ypos #Defines the y axis positioning of the image as the attribute passed through

    def LoadImage(self): #This method will load images into the game displaying them

        image = pygame.image.load(self.filename+".png") #Image is loaded into the program
        gameDisplay.blit(image, (self.xpos,self.ypos)) #Image is displayed to coordinates which were attributes that were defined prior


stage = 1 #Sets the menu as stage 1 which is the play and quit buttons

class Button: #This class contains methods for buttons including display and functionality

    def __init__(self, buttonname, buttonx, buttony, buttonwidth, buttonheight, textfile, textx, texty, stage): #Methods used to allow classes to intialise attributes

        self.buttonname = buttonname #Defines the name of the button as the attribute passed through
        self.buttonx = buttonx #Defines the x axis positioning of the button as the attribute passed through 
        self.buttony = buttony #Defines the y axis positioning of the button as the attribute passed through
        self.buttonwidth = buttonwidth #Defines the width of the button as the attribute passed through
        self.buttonheight = buttonheight #Defines the height of the button as the attribute passed through
        self.textfile = textfile #Sets the name of the textfile to be called
        self.textx = textx #Defines the x axis positioning of the text as the attribute passed through
        self.texty = texty #Defines the y axis positioning of the text as the attribute passed through
        self.stage = stage #Sets the stage of the menu which has 3 states of play/quit, difficulty and level choice

    def createbutton(self): #Method which creates a button for the menu

        buttonname = pygame.draw.rect(gameDisplay, (0,0,0), [self.buttonx, self.buttony, self.buttonwidth, self.buttonheight]) #Draws a rectangular button which is black and given the size and coordinates which were attributes
        text = pygame.image.load(self.textfile+".png")  #Loads the text file into the program      
        gameDisplay.blit(text, (self.textx,self.texty)) #Displays the text given coordinates

    def quitbutton(self): #Method which quits the program if the quit button is clicked

        if self.buttonx+self.buttonwidth > mouse[0] > self.buttonx and self.buttony+self.buttonheight > mouse[1] > self.buttony and pressed[0] == 1: #If the button is clicked (regarding its dimensions)

            pygame.quit() #Exits pygame
            quit() #Quits program

    def buttonaction(self): #Method which takes action for the particular button

        if self.buttonx+self.buttonwidth > mouse[0] > self.buttonx and self.buttony+self.buttonheight > mouse[1] > self.buttony and pressed[0] == 1: #If the button is clicked (regarding its dimensions)

            if self.stage == 1: #If the play/quit buttons are active

                EasyButton.createbutton() #Creates and displays the easy button through the button class and its method
                MediumButton.createbutton() #Creates and displays the medium button through the button class and its method
                HardButton.createbutton() #Creates and displays the hard button through the button class and its method
                VeteranButton.createbutton() #Creates and displays the veteran button through the button class and its method

            if self.stage == 2: #If the difficulty buttons are active

                OneButton.createbutton() #Creates and displays the one button through the button class and its method
                TwoButton.createbutton() #Creates and displays the two button through the button class and its method
                ThreeButton.createbutton() #Creates and displays the three button through the button class and its method
                FourButton.createbutton() #Creates and displays the four button through the button class and its method    

                if self.buttonname == 'easybutton':
                    difficulty = 'easy'

                if self.buttonname == 'mediumbutton':
                    difficulty = 'medium'

                if self.buttonname == 'hardbutton':
                    difficulty = 'hard'                                

                if self.buttonname == 'veteranbutton':
                    difficulty = 'veteran'        

                print(difficulty)

            time.sleep(0.5)




PlayButton = Button('playbutton',133,477,756,223,'PlayText',387,545,1) #Creates play button      
QuitButton = Button('quitbutton',133,731,756,223,'QuitText',387,806,None) #Creates quit button

EasyButton = Button('easybutton',127,477,362,223,'EasyText',214,548,2) #Creates easy button
MediumButton = Button('mediumbutton',533,477,362,223,'MediumText',560,548,2) #Creates medium button
HardButton = Button('hardbutton',127,727,362,223,'HardText',214,806,2) #Creates hard button
VeteranButton = Button('veteranbutton',533,727,362,223,'VeteranText',537,806,2) #Creates veteran button

OneButton = Button('onebutton',127,477,362,223,'OneText',287,550,3) #Creates the level 1 button
TwoButton = Button('twobutton',533,477,362,223,'TwoText',693,550,3) #Creates the level 2 button
ThreeButton = Button('threebutton',127,727,362,223,'ThreeText',285,810,3) #Creates the level 3 button
FourButton = Button('fourbutton',533,727,362,223,'FourText',685,810,3) #Creates the level 4 button
PlayButton.createbutton() #Creates the play button through the button class and its method
QuitButton.createbutton() #Creates the play button through the button class and its method




while True:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

    mouse = pygame.mouse.get_pos() #Gets the x and y coordinates of the mouse cursor
    pressed = pygame.mouse.get_pressed() #Checks if the mouse has been pressed

    PlayButton.buttonaction() #Checks if the playbutton needs action
    QuitButton.quitbutton() #Checks if the quitbutton needs action
    EasyButton.buttonaction() #Checks if the easybutton needs action
    MediumButton.buttonaction() #Checks if the mediumbutton needs action
    HardButton.buttonaction() #Checks if the hardbutton needs action
    VeteranButton.buttonaction() #Checks if the veteranbutton needs action
    OneButton.buttonaction() #Checks if the onebutton needs action
    TwoButton.buttonaction() #Checks if the twobutton needs action
    ThreeButton.buttonaction() #Checks if the threebutton needs action
    FourButton.buttonaction() #Checks if the fourbutton needs action

    pressed = [0,0,0]
    pygame.display.update()
    clock.tick(5)

面向对象设计的原则之一是将对象建模/实现的所有方面都保留在对象内部,但仅此而已。此按钮的用途是什么?在屏幕上显示,接受用户输入,向主程序发送状态信号

所以在这方面,你的button类基本上是可以的。但是,它包含了按钮定义中真正不属于按钮工作的内容,例如:

def quitbutton(self): 
    #If the button is clicked (regarding its dimensions)
    if self.buttonx+self.buttonwidth > mouse[0] > self.buttonx and self.buttony+self.buttonheight > mouse[1] > self.buttony and pressed[0] == 1: 

        pygame.quit() #Exits pygame
        quit()        #Quits program
通用按钮类不应该负责退出程序,它只需要单击并取消单击。同样,对于在播放+退出和难度级别按钮设置之间切换的代码,这不是按钮的工作

我认为更好的按钮可以更简单地消除混乱:

class Button: 

    def __init__(self, buttonname, buttonx, buttony, buttonwidth, buttonheight, textfile, textx, texty ): 

        self.buttonname  = buttonname   # Name of the button
        self.buttonx     = buttonx      # X-axis position
        self.buttony     = buttony      # Y-axis position
        self.buttonwidth = buttonwidth  # Width of the button
        self.buttonheight= buttonheight # Height of the button
        self.text_image  = pygame.image.load( textfile+".png" )  # Button Label
        self.textx       = textx        # X-axis positioning of the text
        self.texty       = texty        # Y-axis positioning of the text

    def drawButton( self, screen ):
        """ Paint the button to the screen """
        # Black rectangle the size of the button
        pygame.draw.rect( screen, (0,0,0), [self.buttonx, self.buttony, self.buttonwidth, self.buttonheight]) 
        # Overlay the button text onto the background
        screen.blit( text_image, ( self.textx, self.texty ) )

    def mouseIsOver( self, mouse_position ):
        """ Returns true if the mouse is within this buttons area """
        inside = self.buttonx+self.buttonwidth > mouse_position[0] > self.buttonx and self.buttony+self.buttonheight > mouse_position[1] > self.buttony
        return inside
然后在主程序中:

PlayButton = Button('playbutton',133,477,756,223,'rock1_64',387,545,1) #Creates play button      
QuitButton = Button('quitbutton',133,731,756,223,'rock1_64',387,806,None) #Creates quit button

EasyButton = Button('easybutton',127,477,362,223,'rock1_64',214,548,2) #Creates easy button
MediumButton = Button('mediumbutton',533,477,362,223,'rock1_64',560,548,2) 
...

all_buttons = [ PlayButton, QuitButton, EasyButton, MediumButton ]


# Main Loop
while True:

    # Handle user-input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            break
        if event.type == pygame.MOUSEBUTTONUP:
            # The mouse button was clicked, was it inside a button?
            click_location = pygame.mouse.get_pos()
            for b in all_buttons:
                if ( b.mouseIsOver( click_location ) ):
                    print( "Button [%s] pressed" % ( b.buttonname ) )

     # Re-paint screen
     gameDisplay.fill( BACKGROUND_COLOUR )
     for b in all_buttons:
         b.drawButton( gameDisplay )
     pygame.display.flip()
     clock.tick_busy_loop( 60 ) # Limit FPS


 pygame.quit()
 quit()
否则,Button类可能会将事件发布到PyGame队列: 编辑:这里面有一个bug,它需要创建要发布的事件,修复了

BUTTON_CLICK_EVENT = pygame.USEREVENT + 1

...

class Button ( ... ):

    def checkClick( self, mouse_pos ):
        """ If the mouse-click is inside our rectangle, post a message to the queue """
        if ( self.buttonx+self.buttonwidth > mouse_position[0] > self.buttonx and self.buttony+self.buttonheight > mouse_position[1] > self.buttony ):
            pygame.event.post( pygame.event.Event( BUTTON_CLICK_EVENT, { "button_name" : self.buttonname } ) )

...

# Main loop

    if event.type == BUTTON_CLICK_EVENT:
        print("Clicked "+ event.button_name )

这样做可以将按钮逻辑与程序的其余部分分离,并防止需要全局变量。显然,您需要在按钮组之间切换,但这对于Button对象来说不是问题,它应该转到其他地方。也许在一个按钮组或类似的。

嗨-请考虑编辑你的问题。您的代码只是部分格式化,这使得它无法遵循。如果格式不正确,您的问题可能会被忽略!感谢修复它的人让我想到了这一点,一个按钮只是另一个不动的精灵。谢谢你,我明白我试图把所有东西都塞进一节课,但事实并非如此。我猜这个按钮的主要目的就是点击并松开。我有点不知所措,不知道如何写下行动将在哪里发生,但你已经很好地解释了这一点。谢谢,不客气。从长远来看,创建好的简单类可以使编程变得更容易、更快