Reputation: 759
I recently downloaded Kivy as it's given me the most comprehensible tutorials and documentation, etc. I've tried pygame and cocos but never could get a foundation, and with Kivy it's been easy.
So heres my problem, I've made a pong game, and I'm trying to make the game pause by stopping the pong ball, and then starting it again when it's unpaused (by changing its velocity).
Here's my code:
class PongGame(Widget):
...
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'escape':
#Why doesnt it work without global?
#If I don't use a global i get "tempBallVelocity referenced before assignment
global tempBallVelocity
tempBallVelocity = self.ball.velocity
self.ball.velocity = 0,0
if keycode[1] == '`':
#Make the ball go again, thus exiting pause
#This is where the error occurs if I don't use global
self.ball.velocity = tempBallVelocity
As you can see in the comments, If I don't use global, I get referenced before assignment error. But it's a local variable, I don't understand why this is happening.
Anyone have any ideas? thanks?
Edit: Just to make sure everyone is clear in my intentions, I do NOT want to use a global, but it's the only way it will work. I would prefer not to use globals.
Upvotes: 0
Views: 973
Reputation: 61
Each time you set a variable inside a identated block of code, the variable is destroyed once you get out of that block, back into the previous identation;
If you write
if True:
foo = 'foo value, which is a string (?)'
print foo
inside a huge script, python only handles the foo variable while it's 'inside' the if statement, and once it ends it and gets out, foo is completely forgotten in order to make things faster, it's understood that if you set the variable inside a statement, you'll use it only inside that statement.
If you wanted to do something like this
if True:
foo = 'foo value'
# Right now foo has been trashed
if True:
print foo
# Raises an error
You'd have to set the foo variable outside the 'if' statements
foo = ''
if True:
foo = 'foo value'
# Right now foo still exists and keeps it's recently changed value
if True:
print foo
# prints 'foo value'
Or you may also do it by setting foo as a global variable so it isn't destroyed once you get outside the 'if' statement
if True:
global foo
foo = 'foo value'
# foo still exists as it's a global variable
if True:
print foo
# There's no reason so it wouldn't work
But that may be unnecesary and confusing in most circunstances, or even problematic if you start making everything global so variables that you only use once accrue uselessly on your device's memory during the program.
Right now you are writing a class, so the right way to do what you are doing would be (from my point of view) to storage the 'tempBallVelocity' variable in the class like this
class PongGame(Widget):
...
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'escape':
self.tempBallVelocity = self.ball.velocity
self.ball.velocity = 0,0
if keycode[1] == '`':
self.ball.velocity = self.tempBallVelocity
It looks like it doesn't respect the rule I've just told you but the thing here is that when you write 'self.tempBallVelocity = ...' you are storaging the info in self, which is the shortcut to the PongGame object you'll instantiate in order to run the game, which will run that method, so the variable stands storaged there when you get out the method.
I hope this answer is helpful to you, you should get a more solid knowledge about python, Learn Python The Hard Way is a site of a book with a free html version that was useful for me.
See you! :D
Upvotes: 0
Reputation: 175
Your code inside the function is not indented, is that just a copying mistake? If not I wonder why you don't get an error.
Edit:
Ok, it's easy you set the variable tempBallVelocity
when you call the function with 'escape'
but then the function exits and you loose the variable. If you then call it with 'backtick' you haven't set the variable tempBallVelocity
yet, the best solution would probably be:
self.tempBallVelocity = self.ball.velocity
.
Upvotes: 1
Reputation: 264
If you fix the indentation error again you will see that:
You can see that:
the escape escape
should work without the global, however tempBallVelocity
will be considered as a local variable. If you want to modify a global variable you need to add the global declaration to tell python that tempBallVelocity
is not local but global.
In the second case, tempBallVelocity
is not locally initialized if you do not enter the escape block and thus cannot be used as a local RValue. In this case python should look for the variable outside of the class. Is tempBallVelocity
really a global variable ?
remark: if the cases are exclusive you should use elif
instead of if
for the second case.
Upvotes: 1