Bouncing in Polski

08 May, 2019

Marzena writes:

I'm writing to you because neither me nor my 11-year old daughter with whom we're learning Python can figure out where the problem is. We get the following error:
 ================ RESTART: C:/Users/Enarpol/Desktop/brajan.py ================
 Traceback (most recent call last):
   File "C:/Users/Enarpol/Desktop/brajan.py", line 5, in
     class Piłka:
   File "C:/Users/Enarpol/Desktop/brajan.py", line 20, in Piłka
     if pozycja[1] <= 0:
 NameError: name 'pozycja' is not defined
And the code is exactly like in the book (some words are in Polish, but I assume it's not a problem for you to trace the error despite of it)

Your problem problem is caused by indentation and the idea of "scope" - I guess you're using the Polish language version of the book, so I'm not sure of the correct page number, but in the English language version of the book the section on Variables and Scope (page 84) would be useful to re-read.

In short, here is the incorrect bit of your code:

    def rysuj(self):
        self.płótno.move(self.id, self.x, self.y)
        pozycja = self.płótno.coords(self.id)
    if pozycja[1] <= 0:
        self.y = 3

If I re-indent this with visible spaces, to show how it should look, hopefully you can see what you need to fix in the rest of your code:

    def rysuj(self):
        self.płótno.move(self.id, self.x, self.y)
        pozycja = self.płótno.coords(self.id)
    ␣␣␣␣if pozycja[1] <= 0:
    ␣␣␣␣    self.y = 3

Why does this make a difference? Because in the case of rysuj above, the variable pozycja is only visible within the function - or to be exact, within the block of code that makes up the function. And how do we create a block of code? Basically through indentation. Your if statement was at the same indentation level as def rysuj(self), so it wasn't part of the function and that's why you're getting the error name 'pozycja' is not defined.

Hope that helps.


Traditional Chinese

16 Mar, 2019

你 好!

traditional chinese translation cover

Available from Wu Nan Books.


Stickman Moves

31 Jan, 2019

Alex Z writes (edited):

I'm playing with the last chapter game, cf. the stickmangame7.py file. I'm a little confused about how the key presses are expected to cause the character [to] move.

If the player hits the right or left key, the character starts moving but keeps moving and doesn't stop unless [colliding] against a wall or a platform. Even jumping on a platform doesn't cause the stick figure to stop. This makes hard to climb to the top parts of the area. Is it the expected behavior of the game ?

I am not the first to experience this problem, see the folowing message on stackoverflow: How to move character only when key is pressed down Python

Yes, that is the expected behaviour of the game. The point is to make it more difficult to reach the top platform, so once the character starts running he doesn't stop, unless he collides with something. However, if you do want to change it so that the character only moves when the key is held down, there's a few fairly minor modifications you can make (which are discussed in that stack overflow article):

i. Add a new function to stop the character moving, by changing the value of the x variable to 0. So in the StickFigureSprite sprite class we add this new function:

class StickFigureSprite(Sprite):
    ...
    ...
    ...
    def stop_moving(self, evt):
        self.x = 0

ii. Now we need a way to call the new function. So we add two new key bindings to the __init__ function of the same class, and set the starting value of the x variable to 0 (it's currently set to -2 so that the stick figure starts running as soon as the game starts):

class StickFigureSprite(Sprite):
    def __init__(self, game):
        ...
        ...
        self.x = 0
        ...
        ...
        game.canvas.bind_all('<KeyRelease-Left>', self.stop_moving)
        game.canvas.bind_all('<KeyRelease-Right>', self.stop_moving)

So with these changes the game starts and the stick man won't move. When you hold the left or right key down, the x variable is set to -2 or 2 respectively which starts "him" moving. When you release the key, it sets the value back to 0, which stops him moving again.

You might notice one slight problem when running the game after this change - the stickman starts quickly and then slows down. This is caused by the keyboard repeating which then impacts the performance of the mainloop function in the Game class. This is an unfortunate side effect of the way the code for the game is written (the stickman code is not the standard way to handle animation with tkinter -- however it was written this way to hopefully make animation concepts, in programming, slightly easier for a child to understand).


PFK and iPython

27 Jan, 2019

Jobakhan writes (edited):

Using this code
import sys
def moon_weight():
    print('Please enter your current Earth weight')
    weight = float(sys.stdin.readline())
    print('Please enter the amount your weight might increase each year')
    increase = float(sys.stdin.readline())
    print('Please enter the number of years')
    years = int(sys.stdin.readline())
    years = years + 1
    for year in range(1, years):
        weight = weight + increase
        moon_weight = weight * 0.165
        print('Year %s is %s' % (years , moon_weight))

then it gives me this:
error in ipython
Why is this happening?

It looks like you're using iPython/Jupyter Notebook to run the examples in the book. Python for Kids wasn't specifically written to work with iPython (nor was the code actually tested with that app), which is why you're having issues. Having said that, I think many of the examples will work, but some, like the code you sent, will need modification.

In the case of the moon_weight function, it's using sys.stdin.readline() (that's the sys module, "standard input" object, readline function) to read input from the user running the program. There are a couple of ways to read command line input in Python - and in the case of Jupyter it looks like stdin doesn't behave the same way as the Python shell. I found the following in the Jupyter client documentation:

This pattern of requesting user input is quite different from how stdin works at a lower level. The Jupyter protocol does not support everything code running in a terminal can do with stdin...

So what's actually happening when you run that code? The function sys.stdin.readline() returns straight away with an empty string (''), and Python then throws an error when trying to convert that empty string to a floating point number. If you replace sys.stdin.readline() in the above code with input(), the program should then work in jupyter:

weight = float(input())
...
increase = float(input())
...
years = int(input())

iPad Pro and Pythonista

26 Jan, 2019

Lucia C writes:

I am currently reading your book but do not have access to a computer. I do however have my Ipad pro.

There is an app available called Pythonista 3, are you familiar with this app and would you recomend it to follow your book?

Unfortunately, Pythonista has it's own custom UI library, so I don't believe it supports turtle or tkinter -- the latter chapters of the book rely heavily on tkinter for graphics in the games. Without this you're going to struggle completing all the examples.

If you only have an iPad, a cheap option might be to purchase a Raspberry Pi (at time of writing a Pi starter kit is UK£51.99/US$79.99) and use that for your programming activities. While you'll initially need a monitor as well, if you want to stick with the iPad, it looks like it is possible to connect from the iPad to the Pi (so your iPad effectively becomes the monitor) using VNC -- more info can be found here in this instructables article.

Hope that helps.