简体   繁体   中英

time.sleep function within while loop keeps crashing program, solution or alternative method?

I am trying to make a space invaders game using turtle, and in order to move the bullet up the screen I am trying to update the y coordinate of the bullet every 0.5 seconds. I tried to do this with a while loop and the time.sleep() function, but everytime I try to fire a bullet, the program crashes. Is there any way I can stop it from doing this? Or why is it not working? Is there an equally effective method that will not crash my program?

import turtle
import time

userx = 0

x = 0
y = -300

enemies = [(300,50, "left"), (400,50, "left"), (350, -50, "right")]

bullets = []

gameover = False

def frame():
    pass
    ship = turtle.Turtle()
    ship.pu()
    ship.ht()
    ship.setpos(userx, -300)
    ship.pd()
    ship.circle(5)

    bullet = turtle.Turtle()
    bullet.pu()
    bullet.ht()
    bullet.setpos(x, y)
    bullet.pd()
    bullet.circle(2)

def key_left():
    global userx
    pass
    userx += -10
    print(userx)

def key_right():
    global userx
    pass
    userx += 10
    print(userx)

def key_space():
    pass # your code here
    global x
    global y
    global bullets
    x = userx
    while y <= 300:
        time.sleep(0.5)
        y += 4
    else: y = 0
    bullets += (x,y)

def physics():
    global bullets
    global enemies
    pass

def ai():
    global enemies
    global gameover
    pass

def reset():
    global enemies
    global bullets
    global userx
    global gameover
    pass

def main():
    turtle.tracer(0,0)
    turtle.hideturtle()
    turtle.onkey(key_left, "Left")
    turtle.onkey(key_right, "Right")
    turtle.onkey(key_space, "space")
    turtle.listen()
    reset()
    while not gameover:
        turtle.clear()
        physics()
        ai()
        frame()
        turtle.update()
        time.sleep(0.05)

main()

I would:

def key_space():
    # simply spawn a new bullet and put it into your bullets list 

def advance_bullet(): # call this after paintnig all bullets in frame 
    # iterate over all bullets inside bullets, advance the Y position by 3

def frame(): 
    # add code to paint all bullets inside bullets - and call advance_bullets()

In the code that checks for collision with enemies:

# remove a bullet from bullets when its outside your screen (or passed all enemies max y coord) - no need to track that bullet anymore

if you ned to advance the bullets slower then your main loops intervall, make a "framespassed" counter and see if framespassed % something == 0 and only then advance your bullets.

Adapted to what you already have

You need to change these parts:

def frame():
    global bullets
    pass
    ship = turtle.Turtle()
    ship.pu()
    ship.ht()
    ship.setpos(userx, -300)
    ship.pd()
    ship.circle(5)

    # debugging all bullets: 
    # print(bullets) # remove this

    for idx in range(0,len(bullets)): # paint ALL bullets in the bullets list
        bulletTurtle = turtle.Turtle()
        b = bullets[idx] # current bullet we are painting
        bulletTurtle.pu()
        bulletTurtle.ht()
        bulletTurtle.setpos(b[0], b[1])
        bulletTurtle.pd()
        bulletTurtle.circle(2)
        b[1] += 13 # quick and dirty approach, move bulltet after painting
                   # to save another complete bullets-foreach-loop 

    # quick n dirty bullet removal for out of screen bullets
    # normally I would do this probably in your "check if enemy hit" 
    # method as you are going over bullets there as well and can remove
    # them as soon as they passed all enemies 
    bullets = [x for x in bullets if x[1] < 500] 


def key_space():
    global x
    global y
    global bullets
    bullets.append([userx,-300]) # start a new bullet at current player position

Edit:

You might want to take a look at turtle.shape, turtle.size and turtle.stamp - by using a "circle" shape and a size that fits, you might be able to "stamp" this shape down. Advantage: you can simply delete the stamped shape - by its integer-id. I haven*t worked with turtle ever - consider yourself if that would be a way to easily redraw your players position and/or bullets

It is not ideal but it starts working.

In key_space you only add new bullet to list.
In while not gameover you run function which will move all bullets.
In frame you draw all bullets.

import turtle
import time

userx = 0

x = 0
y = -300

enemies = [(300,50, "left"), (400,50, "left"), (350, -50, "right")]

bullets = []

gameover = False

def frame():
    pass
    ship = turtle.Turtle()
    ship.pu()
    ship.ht()
    ship.setpos(userx, -300)
    ship.pd()
    ship.circle(5)

    # redraw bullets
    for x, y in bullets:
        bullet = turtle.Turtle()
        bullet.pu()
        bullet.ht()
        bullet.setpos(x, y)
        bullet.pd()
        bullet.circle(2)

def key_left():
    global userx
    pass
    userx += -10
    print(userx)

def key_right():
    global userx
    pass
    userx += 10
    print(userx)

def key_space():
    pass # your code here
    global x
    global y
    global bullets
    x = userx

    # add bullet to list
    bullets.append([x, -300])

def move_bullets():
    global bullets

    live_bullets = []

    # move every bullet and check if should still live
    for x, y in bullets:
        y += 4

        # keep only some bullets and other forget (kill/remove)
        if y <= 300:
            live_bullets.append([x, y])

    bullets = live_bullets

def physics():
    global bullets
    global enemies
    pass

def ai():
    global enemies
    global gameover
    pass

def reset():
    global enemies
    global bullets
    global userx
    global gameover
    pass

def main():
    turtle.tracer(0,0)
    turtle.hideturtle()
    turtle.onkey(key_left, "Left")
    turtle.onkey(key_right, "Right")
    turtle.onkey(key_space, "space")
    turtle.listen()
    reset()
    while not gameover:
        turtle.clear()
        physics()
        ai()
        move_bullets() # <--  move bullets (or maybe before physics)
        frame()
        turtle.update()
        time.sleep(0.05)

main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM