Ron Gerbi
Ron Gerbi

Reputation: 61

Isn't turtle.mainloop() supposed to keep looping? How can I make a function called every instant?

I used the Python turtle library to create two turtles that can move around using the .onkey() method. I want to make the program to print "Clash" if the two turtles are close. I created the function clash() that I call in the main function and used turtle.mainloop() because I thought it makes the program loop over and over. However the function is called only one time in the beginning, and if the turtles are crashing into each other later on, the function won't work.

How can I make the function be called over and over, every instant of the game?

import turtle

my_Turtles = [turtle.Turtle(),
              turtle.Turtle()

]
screen = turtle.Screen()
# functions
def up(number):
    my_Turtles[number].setheading(90)
    my_Turtles[number].forward(10)


def down(number):
    my_Turtles[number].setheading(270)
    my_Turtles[number].forward(10)


def left(number):
    my_Turtles[number].setheading(180)
    my_Turtles[number].forward(10)


def right(number):
    my_Turtles[number].setheading(0)
    my_Turtles[number].forward(10)

def clash():
    if (my_Turtles[0].distance(my_Turtles[1].xcor(), my_Turtles[1].ycor()) < 10):
        print ("Clash")

my_Turtles[0].speed(0)
my_Turtles[1].speed(0)

turtle.listen()

turtle.onkey(lambda: up(0), 'Up')
turtle.onkey(lambda: right(0), 'Right')
turtle.onkey(lambda: left(0), 'Left')
turtle.onkey(lambda: down(0), 'Down')

turtle.onkey(lambda: up(1), 'w')
turtle.onkey(lambda: right(1), 'd')
turtle.onkey(lambda: left(1), 'a')
turtle.onkey(lambda: down(1), 's')

clash()


turtle.mainloop()

Upvotes: 0

Views: 898

Answers (1)

cdlane
cdlane

Reputation: 41872

used turtle.mainloop() because i thought it makes the program loop over and over

The mainloop() function does loop over and over, but doing its thing, not yours! Its thing is to constantly check for keyboard, mouse, etc. events and call your registered event handlers.

To get your clash() function called at the appropriate time, add a call to it in any function that changes the position of a turtle. In this case, the up, down, right and left event handlers.

I demonstrate that below in my rework of your code. I also redesigned the code to not know how many turtles are in play -- I upped it to three just to check that my logic is working:

from turtle import Screen, Turtle
from functools import partial
from random import randint

KEYSETS = [
    ('Up', 'Down', 'Left', 'Right'),
    ('w', 's', 'a', 'd'),
    ('i', 'k', 'j', 'l'),
]

def up(turtle):
    turtle.setheading(90)
    turtle.forward(10)
    clash(turtle)

def down(turtle):
    turtle.setheading(270)
    turtle.forward(10)
    clash(turtle)

def left(turtle):
    turtle.setheading(180)
    turtle.forward(10)
    clash(turtle)

def right(turtle):
    turtle.setheading(0)
    turtle.forward(10)
    clash(turtle)

def clash(turtle):
    for other_turtle in my_turtles:
        if other_turtle == turtle:
            continue

        if turtle.distance(other_turtle) < 10:
            print("Clash!")
            break

screen = Screen()

my_turtles = []

for UP, DOWN, LEFT, RIGHT in KEYSETS:
    turtle = Turtle()
    turtle.shape('turtle')

    screen.onkey(partial(up, turtle), UP)
    screen.onkey(partial(down, turtle), DOWN)
    screen.onkey(partial(left, turtle), LEFT)
    screen.onkey(partial(right, turtle), RIGHT)

    turtle.penup()
    turtle.goto(randint(-100, 100), randint(-100, 100))
    turtle.pendown()

    turtle.setheading(randint(1, 360))

    my_turtles.append(turtle)

screen.listen()
screen.mainloop()

Upvotes: 1

Related Questions