Error Global Variable not defined when importing class

冷暖自知 提交于 2019-12-20 07:33:23

问题


I am trying to implement a movement system where the player move's towards the click position. But I have been running into some problems with the arguments of the movement method.

The movement method currently needs to take all the variables as arguments:

This code works:

def move(self,event,mouse_pos, screen, background):
        if event.type == MOUSEBUTTONDOWN:
            if mouse_pos[1] > self.pos[1]:
                screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                self.speed = 1
                self.move_south() #moves player
            if mouse_pos[0] > self.pos[0]:
                screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                self.speed = 1
                self.move_east() #moves player
            screen.blit(self.image, self.pos) #draws player  

This code doesn't work:

def move(self,event):
        if event.type == MOUSEBUTTONDOWN:
            if mouse_pos[1] > self.pos[1]:
                screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                self.speed = 1
                self.move_south() #moves player
            if mouse_pos[0] > self.pos[0]:
                screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                self.speed = 1
                self.move_east() #moves player
            screen.blit(self.image, self.pos) #draws player   

Full Class code:

import pygame, sys
from pygame.locals import *

class GameObject:
    def __init__(self, image, height, speed):
        self.speed = speed
        self.image = image
        self.pos = image.get_rect().move(0, height) #initial placement

    def move_south(self):
        self.pos = self.pos.move(0, self.speed)
        if self.pos.right > 600:
            self.pos.left = 0

    def move_east(self):
        self.pos = self.pos.move(self.speed , 0)
        if self.pos.right > 600:
            self.pos.left = 0

    def move(self,event,mouse_pos, screen, background):
            if event.type == MOUSEBUTTONDOWN:
                if mouse_pos[1] > self.pos[1]:
                    screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = 1
                    self.move_south() #moves player
                if mouse_pos[0] > self.pos[0]:
                    screen.blit(background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = 1
                    self.move_east() #moves player
                screen.blit(self.image, self.pos) #draws player      

main script code:

import pygame, sys
from pygame.locals import *
from classes import *

screen = pygame.display.set_mode((640, 480))
#Importing Chars
player = pygame.image.load('green_hunter_small.png').convert()
#player.set_alpha(100) #makes whole player transparent
player.set_colorkey((0,0,0)) #sets background colour to transparent

ennemi =  pygame.image.load('red_hunter_small.png').convert()
ennemi.set_colorkey((0,0,0))

background = pygame.image.load('grass_map_640x640.png').convert()
screen.blit(background, (0, 0))
objects = []
mouse_pos = (320, 240)
objects.append(GameObject(player, 80, 0))
for x in range(2):      #create 2 objects
    o = GameObject(ennemi, x*40, 0)
    objects.append(o)
while True:
    for event in pygame.event.get(): #setting up quit
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == MOUSEBUTTONDOWN :
            mouse_pos = pygame.mouse.get_pos()
            print mouse_pos
            for o in objects:
                screen.blit(background, o.pos, o.pos) #erases players by bliting bg 
            for o in objects:
                o.move(event,mouse_pos,screen,background)
    pygame.display.update()
    pygame.time.delay(100)

I've got two questions : 1) how to reduce the number of arguments for my method ? 2) how to get my player to move continually towards the click position rather than once at every click ?


回答1:


Your problem is that "global" variables in python are not actually global, but rather local to the module in which they were defined in. Thus, you cannot reference globals decalred in the main.py file in the classes.py file.

There are three possible solutions:

  1. (not recomended) Move the declarations of screen and background to the classes.py file, which would put them seemingly out of place.

  2. (also not recommended) Add a from main import screen, background to the classes.py file, which creates circular import problems, forcing the main.py module to do its from classes import * after defining screen and background

  3. Add a third display.py or screen.py file, where the screen and background variabled are defined and import it from main.py and classes.py

The mouse_pos variable is totally unnecessary and misused:

  1. You could just use pygame.mouse.get_pos() directly in the classes.py file, but
  2. Using pygame.mouse.get_pos() itself is extranious because pygame.MOUSEBUTTONDOWN events have a pos attribute pointing to the position of the mouse when the event was fired.



回答2:


So after a bit more work I found the solution to my problem.

I only had two python files which both imported each other.

I had to create a third file to avoid this "circular" importation.

I made one file with my main code called main.py importing both the classes.py file and the variables.py file.

main.py:

import pygame, sys, variables
from pygame.locals import *
from classes import *

#Creating the characters
objects = []
objects.append(GameObject(variables.player, 80, 0))
for x in range(2):      #create 2 objects
    o = GameObject(variables.ennemi, x*40, 0)
    objects.append(o)

#game loop    
while True:
    for event in pygame.event.get(): #setting up quit
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == MOUSEBUTTONDOWN : #initiating movement on click

            for o in objects:
                variables.screen.blit(variables.background, o.pos, o.pos) #erases players by bliting bg 
            for o in objects:
                o.move(event)
    pygame.display.update()
    pygame.time.delay(20)

classes.py:

import pygame, sys, variables
from pygame.locals import *

class GameObject:
    def __init__(self, image, height, speed):
        self.speed = speed
        self.image = image
        self.pos = image.get_rect().move(0, height) #initial placement

    def move_NS(self):
        self.pos = self.pos.move(0, self.speed)
        if self.pos.right > 600:
            self.pos.left = 0

    def move_EW(self):
        self.pos = self.pos.move(self.speed , 0)
        if self.pos.right > 600:
            self.pos.left = 0


    def move(self,event):#,mouse_pos, screen, background
            if event.type == MOUSEBUTTONDOWN:
                if pygame.mouse.get_pos()[1] > self.pos[1]:
                    variables.screen.blit(variables.background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = 1
                    self.move_NS() #moves player
                if pygame.mouse.get_pos()[0] > self.pos[0]:
                    variables.screen.blit(variables.background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = 1
                    self.move_EW() #moves player
                if pygame.mouse.get_pos()[1] < self.pos[1]:
                    variables.screen.blit(variables.background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = -1
                    self.move_NS() #moves player
                if pygame.mouse.get_pos()[0] < self.pos[0]:
                    variables.screen.blit(variables.background, self.pos, self.pos) #erases players by bliting bg 
                    self.speed = -1
                    self.move_EW() #moves player

                variables.screen.blit(self.image, self.pos) #draws player     

variables.py:

import pygame, sys
from pygame.locals import *
#Variables
screen = pygame.display.set_mode((640, 480))

#Importing Chars
player = pygame.image.load('green_hunter_small.png').convert()
player.set_colorkey((0,0,0)) #sets background colour to transparent

ennemi =  pygame.image.load('red_hunter_small.png').convert()
ennemi.set_colorkey((0,0,0))

#importing background
background = pygame.image.load('grass_map_640x640.png').convert()
screen.blit(background, (0, 0))

Hope it helps !



来源:https://stackoverflow.com/questions/36814328/error-global-variable-not-defined-when-importing-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!