0

For practice programming, I made a game in Python with turtle graphics and tkinter. I have a problem: if I press a key, the game loop stops and the enemies don't move. Is there any solution for this problem?

import random
import time
import turtle
from tkinter import *

running = True

#window

wn = Tk()
wn.geometry("900x700")

canvas = Canvas(wn, width=750, height=600)
canvas.pack()
canvas.place(relx=0.5, rely=0.5, anchor=CENTER)


#player

player = turtle.RawTurtle(canvas)

player_speed = 3


#enemies

enemies = []

for enemy in range(5):
    enemies.append((turtle.RawTurtle(canvas), 10))


for enemy in enemies:
    enemy[0].penup()
    enemy[0].speed(0)
    enemy[0].setheading(90)
    enemy[0].goto(enemy_position_x(), enemy_position_y())#random position


#move the player
def move_left(event):
    player.setheading(180)
    player.setx(player.xcor() - player_speed)


def move_right(event):
    player.setheading(360)
    player.setx(player.xcor() + player_speed)


def move_up(event):
    player.setheading(90)
    player.sety(player.ycor() + player_speed)


def move_down(event):
    player.setheading(270)
    player.sety(player.ycor() - player_speed)


def shoot(event):
    #I don't write the shoot function, because it's long
    print("shoot")


wn.bind('<Left>', move_left)
wn.bind('<Right>', move_right)
wn.bind('<Up>', move_up)
wn.bind('<Down>', move_down)
wn.bind('<space>', shoot)


#game loop
while running:

    #move the enemy
    for this_enemy in enemies:
        if this_enemy[0].xcor() < player.xcor():
            this_enemy[0].setx(this_enemy[0].xcor() + 3)
            time.sleep(0.1)

        if this_enemy[0].xcor() > player.xcor():
            this_enemy[0].setx(this_enemy[0].xcor() - 3)
            time.sleep(0.1)

        if this_enemy[0].ycor() < player.ycor():
            this_enemy[0].sety(this_enemy[0].ycor() + 3)
            time.sleep(0.1)

        if this_enemy[0].ycor() > player.ycor():
            this_enemy[0].sety(this_enemy[0].ycor() - 3)
            time.sleep(0.1)

wn.mainloop()
cdlane
  • 40,441
  • 5
  • 32
  • 81
Laszlo
  • 1

1 Answers1

0

The basic design of your program is incorrect. Turtle (and tkinter) are event-driven but using a while True: loop with time.sleep() works against that. I've rewritten your code below to use timer events, along with other changes. Enemies should keep moving while you control the player with the keyboard. I tossed the tkinter wrapper code as it wasn't doing anything that turtle couldn't do for itself:

from turtle import Screen, Turtle
from random import randint

def enemy_position_x():
    return randint(-325, 325)

def enemy_position_y():
    return randint(-300, 300)

# move the player
def move_left():
    player.setheading(180)
    player.setx(player.xcor() - player_speed)

def move_right():
    player.setheading(360)
    player.setx(player.xcor() + player_speed)

def move_up():
    player.setheading(90)
    player.sety(player.ycor() + player_speed)

def move_down():
    player.setheading(270)
    player.sety(player.ycor() - player_speed)

def move():

    # move the enemy
    for enemy in enemies:
        enemy.setheading(enemy.towards(player))

        if enemy.distance(player) > 10:
            enemy.forward(enemy_speed)

    screen.ontimer(move, 100)

# window

screen = Screen()
screen.setup(900, 700)

# player

player = Turtle()
player.speed('fastest')
player.color('green')
player.penup()

player_speed = 3

# enemies

enemies = []

for _ in range(5):
    enemy = Turtle()
    enemy.penup()
    enemy.speed('fastest')
    enemy.color('red')
    enemy.goto(enemy_position_x(), enemy_position_y())

    enemies.append(enemy)

enemy_speed = 3

screen.onkey(move_left, 'Left')
screen.onkey(move_right, 'Right')
screen.onkey(move_up, 'Up')
screen.onkey(move_down, 'Down')
screen.listen()

move()

screen.mainloop()
cdlane
  • 40,441
  • 5
  • 32
  • 81
  • Sorry, but I will use onkeypress. The player must smoothly move. – Laszlo May 29 '19 at 18:30
  • @Laszlo, I have no idea what that means. Or why you're sorry. But sure. – cdlane May 29 '19 at 19:29
  • The player must move while key is pressed. With onkey the player move once if I press the key. – Laszlo May 31 '19 at 05:36
  • @Laszlo, you may be misunderstanding key events. When you push a key, you generate a 'press' and when you let go, a 'release'. Holding the key doesn't itself generate more 'press' events but rather the operating system kicks in its auto key repeat which generates a sequence of 'press' and 'release' events. I don't believe switching from 'press' to 'release' in this scenario makes a significant difference. I tried both `onkeyrelease` and `onkeypress` and the only difference I noted is that latter ties it specifically to Python 3 but doesn't affect the action. – cdlane May 31 '19 at 06:18
  • Thanks, now I understand it, but is there any solution for my problem? – Laszlo Jun 03 '19 at 13:14
  • @Laszlo, did the code I provided not get around the problem? – cdlane Jun 03 '19 at 15:36