pythonturtle-graphicspython-turtle

Time and keypress events with Python's Turtle


I am trying to create a simple game with turtle:

Therefore, I need some events to be controlled with the keyboard and others that get triggered after a certain time. I cannot think about a way of doing this without a loop inside which I check the distance between the bullet and the enemy, but if I do it like that, I cannot control the main turtle during the loop.

import turtle as trtl
from random import randint
import time

class Game():
    def __init__(self):
        self.scr = trtl.Screen()
        self.scr.update()

        self.player = trtl.Turtle()
        self.player.shape('turtle')
        self.player.penup()

        trtl.onkeypress(self.forward,'w')
        trtl.onkeypress(self.backwards,'s')
        trtl.onkeypress(self.left,'a')
        trtl.onkeypress(self.right,'d')
        trtl.onkeypress(self.shoot,'space')
        trtl.listen()

        self.enemy = trtl.Turtle()
        self.enemy.shape('square')
        self.enemy.penup()
        self.enemy.speed(0)
        self.move_enemy()

        self.bullet = trtl.Turtle()
        self.bullet.penup()
        self.bullet.hideturtle()
        self.bulletShot = False


    def forward(self):
        self.player.forward(5)

    def backwards(self):
        self.player.back(5)

    def left(self):
        self.player.left(6)

    def right(self):
        self.player.right(6)

    def shoot(self):
        if self.bulletShot == False:
            self.bullet.speed(0)
            self.bullet.goto(self.player.pos())
            self.bullet.seth(self.player.heading())
            self.bullet.showturtle()
            self.bulletShot = True

    def move_enemy(self):
        x = randint(-300,300)
        y = randint(-300,300)
        self.enemy.hideturtle()
        self.enemy.goto(x,y)
        self.enemy.showturtle()

    def play(self):
        startTime = time.time()
        print(time.time() - startTime)
        while time.time() - startTime < 20:
            if self.bulletShot:
                self.bullet.forward(1)
                collision = self.bullet.distance(self.enemy.pos()) < 10
                isIn = (self.bullet.pos()[0] <= 300 and 
                        self.bullet.pos()[0] >= -300 and 
                        self.bullet.pos()[1] <= 300 and 
                        self.bullet.pos()[1] >= -300)

                if not(isIn):
                    self.bullet.hideturtle()
                    self.bulletShot = False
                elif collision:
                    self.bullet.hideturtle()
                    self.bulletShot = False
                    self.move_enemy()
                    startTime = time.time()

        self.player.write('You loose')
        self.scr.exitonclick()


game = Game()
game.play()

I tried a simpler version in which one turtle moves automatically in a loop and another turtle is controlled with the keyboard, and it works well.

import turtle as trtl

def up():
    jane.sety(jane.pos()[1] + 10)

def down():
    jane.sety(jane.pos()[1] - 10)

scr = trtl.Screen()
scr.update()

bob = trtl.Turtle()
bob.penup()
bob.seth(180)
bob.setx(300)
bob.speed(1)

jane = trtl.Turtle()
jane.penup()

trtl.onkeypress(up,'w')
trtl.onkeypress(down,'s')
trtl.listen()

while True:
    if bob.pos()[0] > -300:
        bob.forward(10)
    else:
        break

scr.exitonclick()

Is there a way of fixing this with turtle?


Solution

  • I managed to solve it without changing much the code and without making the function play() recursive. The problem was that if the if inside de while needs an else, otherwise, the key press is not recorded. So I gave it something to do and now it works as I want.

    while time.time() - startTime < 20:
        if self.bulletShot:
            self.bullet.forward(3)
            ...
        else:
            self.scr.update()