0

I've just started trying to teach myself Pygame Zero, because we are doing an assignment on it in class next term and I want to be prepared.

I tried to make a simple program where your spaceship constantly accelerates forwards and you can use the left and right arrows to turn it. The problem is that my code is bugging in two ways. Firstly, when the program first starts, the ship is facing up, but it continually moves right and nothing can stop it, even though it should be accelerating in the same direction as the ship. Also, when I try and press the left and right arrows to turn it, the program freezes, and then stops responding. I've tried my hardest to fix it but there is very little online about Pygame Zero. If someone could help me I'd really appreciate it.

Heres my code:

import pgzrun
ship=Actor('ship')
WIDTH = 800
HEIGHT = 450
def draw():
    screen.clear()
    screen.blit("background",(WIDTH,HEIGHT))
    screen.fill((255, 255, 255))
    ship.draw()
def on_key_down(key):
    if key == keys.LEFT:
        left = True
        while left == True:
            ship.angle += 10
    if key == keys.RIGHT:
        right = True
        while right == True:
            ship.angle -= 10
def on_key_up(key):
    if key == keys.LEFT:
        left = False
    if key == keys.RIGHT:
        right = False
    
def update():
    if ship.angle >= 350:
        ship.x += 0
        ship.y -= 3.5
    elif ship.angle >= 330:
        ship.x += 0.1
        ship.y -= 3.3
    elif ship.angle >= 310:
        ship.x += 0.3
        ship.y -= 3.1
    elif ship.angle >= 290:
        ship.x += 0.5
        ship.y -= 2.9
    elif ship.angle >= 270:
        ship.x += 0.7
        ship.y -= 2.7
    elif ship.angle >= 250:
        ship.x += 0.9
        ship.y -= 2.5
    elif ship.angle >= 230:
        ship.x += 1.1
        ship.y -= 2.3
    elif ship.angle >= 210:
        ship.x += 1.3
        ship.y -= 2.1
    elif ship.angle >= 190:
        ship.x += 1.5
        ship.y -= 1.9
    elif ship.angle >= 170:
        ship.x += 1.7
        ship.y -= 1.7
    elif ship.angle >= 150:
        ship.x += 1.9
        ship.y -= 1.5
    elif ship.angle >= 130:
        ship.x += 2.1
        ship.y -= 1.3
    elif ship.angle >= 110:
        ship.x += 2.3
        ship.y -= 1.1
    elif ship.angle >= 90:
        ship.x += 2.5
        ship.y -= 0.9
    elif ship.angle >= 70:
        ship.x += 2.7
        ship.y -= 0.7
    elif ship.angle >= 50:
        ship.x += 2.9
        ship.y -= 0.5
    elif ship.angle >= 30:
        ship.x += 3.1
        ship.y -= 0.3
    elif ship.angle >= 10:
        ship.x += 3.3
        ship.y -= 0.1
    else:
        ship.x += 3.5
        ship.y -= 0


pgzrun.go()
martineau
  • 119,623
  • 25
  • 170
  • 301

1 Answers1

0

This is the part that causes the freeze:

def on_key_down(key):
    if key == keys.LEFT:
        left = True
        while left == True:
            ship.angle += 10
    if key == keys.RIGHT:
        right = True
        while right == True:
            ship.angle -= 10

As you can see, you start a while loop with a condition that is always True. The code is constructed with the assumption that the on_key_up method will be called as soon as the key is relased, and the variable controling the while condition would be changed to False. That could happen if this code would be multi-threading - then the other function could be called concurrently. That is not the case: the main loop of pygame zero is single-threaded and depend on each of the called functions be run to completion and returning, before the game state can be updated.

(and even if it was multithreaded, and pygamezero could change the left and right checks to False, the two line while loop would update the ship angle several million times per second, when you probably want it to update 10 degrees (or less) per game frame).

All you need to do is to upgrade the right and left variables indicating rotation on the "keyup" and "keydown" events, and make the angle change itself on the update function - that is called once per frame (I guess - there is a lot of time since I tried pygame zero).

On a side note, you could get a mathematical formula for updating the ship position based on angle, and not rely on that chain of if/elifs - while it will work, it is not the most fancy code.


import math

...

def draw(...):
    ...

left = right = False
def on_key_down(key):
    global left, right
    if key == keys.LEFT:
        left = True
    if key == keys.RIGHT:
        right = True

def on_key_up(key):
    global left, right
    if key == keys.LEFT:
        left = False
    if key == keys.RIGHT:
        right = False
        

def update():
   global left, right

   if left:
       ship.angle += 10
   elif right: 
       ship.angle -= 10
   # constrain the angle to 0-360 range:
   ship.angle %= 360

   ship.x += 3.5 * sin(math.radians(angle))
   ship.y -= 3.5 * cos(math.radians(angle))
   
jsbueno
  • 99,910
  • 10
  • 151
  • 209