Skip to main content
add a more refined version
Source Link
ggorlen
  • 142
  • 10

Here's a more abstracted version of the same thing, based on this answer:

# ...
# Set turtle movement speed
speed = 3
turn_speed = 15

def bind(key):
    wn.onkeypress(lambda: keys.add(key), key)
    wn.onkeyrelease(lambda: keys.remove(key), key)

keys = set()
actions = {
    "Left": lambda: player.left(turn_speed),
    "Right": lambda: player.right(turn_speed),
    "a": lambda: player2.left(turn_speed),
    "d": lambda: player2.right(turn_speed),
}

for key in actions.keys():
    bind(key)

wn.listen()
wn.tracer(True)

while True:
    for key in [*keys]:
        actions[key]()

    player.forward(speed)
    player2.forward(speed)
    # ...

Here's a more abstracted version of the same thing, based on this answer:

# ...
# Set turtle movement speed
speed = 3
turn_speed = 15

def bind(key):
    wn.onkeypress(lambda: keys.add(key), key)
    wn.onkeyrelease(lambda: keys.remove(key), key)

keys = set()
actions = {
    "Left": lambda: player.left(turn_speed),
    "Right": lambda: player.right(turn_speed),
    "a": lambda: player2.left(turn_speed),
    "d": lambda: player2.right(turn_speed),
}

for key in actions.keys():
    bind(key)

wn.listen()
wn.tracer(True)

while True:
    for key in [*keys]:
        actions[key]()

    player.forward(speed)
    player2.forward(speed)
    # ...
use onkeypress
Source Link
ggorlen
  • 142
  • 10
import math
from turtle import Screen, Turtle

wn = Screen()
wn.bgcolor("black")
wn.tracer(False)

# Write Tron
text = Turtle()
text.pencolor("aqua")
text.hideturtle()
text.penup()
text.setposition(150, 300)
text.write("TRON", font=("system", 30))

# Draw border
pen = Turtle()
pen.penup()
pen.pencolor("white")
pen.setposition(-300, -300)
pen.pendown()
pen.pensize(3)
for side in range(4):
    pen.forward(600)
    pen.left(90)
pen.hideturtle()

# Create player 1
player = Turtle()
player.setposition(240, 240)
player.setheading(180)
player.color("red")
player.shape("triangle")
player.speed(0)

# Create player 2
player2 = Turtle()
player2.setposition(-240, -240)
player2.color("aqua")
player2.shape("triangle")
player2.position()
player2.speed(0)

# Set turtle movement speed
speed = 3

# Set keyboard bindings for p1ayer 1
wn.listen()
wn.onkeyonkeypress(lambda: player.left(30), "Left")
wn.onkeyonkeypress(lambda: player.right(30), "Right")

# Set keyboard bindings for player 2
wn.onkeyonkeypress(lambda: player2.left(30), "a")
wn.onkeyonkeypress(lambda: player2.right(30), "d")
wn.onkeyonkeypress(lambda: player2.left(30), "A")
wn.onkeyonkeypress(lambda: player2.right(30), "D")
wn.tracer(True)

while True:
    player.forward(speed)
    player2.forward(speed)

    if player.distance(player2) < 30:
        print("collision")
        quit()

    # Check border collisions
    if (
        player.xcor() > 300 or player.xcor() < -300 or
        player.ycor() > 300 or player.ycor() < -300 or
        player2.xcor() > 300 or player2.xcor() < -300 or
        player2.ycor() > 300 or player2.ycor() < -300
    ):
        print("GAME OVER")
        quit()

Note also that onkey is actually onkeyrelease, and that your game is subject to the operating system's keyboard retrigger makes fortiming. This leads to a jarring movementpoor experience. SeeFollowing this post for a better approach, you can decouple movement and key presses, leading to design real-time turtle applications.smooth movement:

# ...

# Set turtle movement speed
speed = 3
turn_speed = 15

# Set keyboard bindings for p1ayer 1
keys = set()
wn.listen()
wn.onkeypress(lambda: keys.add("Left"), "Left")
wn.onkeypress(lambda: keys.add("Right"), "Right")
wn.onkeyrelease(lambda: keys.remove("Left"), "Left")
wn.onkeyrelease(lambda: keys.remove("Right"), "Right")

# Set keyboard bindings for player 2
wn.onkeypress(lambda: keys.add("a"), "a")
wn.onkeypress(lambda: keys.add("d"), "d")
wn.onkeyrelease(lambda: keys.remove("a"), "a")
wn.onkeyrelease(lambda: keys.remove("d"), "d")
wn.tracer(True)

while True:
    if "Left" in keys:
        player.left(turn_speed)
    if "Right" in keys:
        player.right(turn_speed)
    if "a" in keys:
        player2.left(turn_speed)
    if "d" in keys:
        player2.right(turn_speed)

    player.forward(speed)
    player2.forward(speed)
    # ...
import math
from turtle import Screen, Turtle

wn = Screen()
wn.bgcolor("black")
wn.tracer(False)

# Write Tron
text = Turtle()
text.pencolor("aqua")
text.hideturtle()
text.penup()
text.setposition(150, 300)
text.write("TRON", font=("system", 30))

# Draw border
pen = Turtle()
pen.penup()
pen.pencolor("white")
pen.setposition(-300, -300)
pen.pendown()
pen.pensize(3)
for side in range(4):
    pen.forward(600)
    pen.left(90)
pen.hideturtle()

# Create player 1
player = Turtle()
player.setposition(240, 240)
player.setheading(180)
player.color("red")
player.shape("triangle")
player.speed(0)

# Create player 2
player2 = Turtle()
player2.setposition(-240, -240)
player2.color("aqua")
player2.shape("triangle")
player2.position()
player2.speed(0)

# Set turtle movement speed
speed = 3

# Set keyboard bindings for p1ayer 1
wn.listen()
wn.onkey(lambda: player.left(30), "Left")
wn.onkey(lambda: player.right(30), "Right")

# Set keyboard bindings for player 2
wn.onkey(lambda: player2.left(30), "a")
wn.onkey(lambda: player2.right(30), "d")
wn.onkey(lambda: player2.left(30), "A")
wn.onkey(lambda: player2.right(30), "D")
wn.tracer(True)

while True:
    player.forward(speed)
    player2.forward(speed)

    if player.distance(player2) < 30:
        print("collision")
        quit()

    # Check border collisions
    if (
        player.xcor() > 300 or player.xcor() < -300 or
        player.ycor() > 300 or player.ycor() < -300 or
        player2.xcor() > 300 or player2.xcor() < -300 or
        player2.ycor() > 300 or player2.ycor() < -300
    ):
        print("GAME OVER")
        quit()

Note also that the keyboard retrigger makes for a jarring movement experience. See this post for a better approach to design real-time turtle applications.

import math
from turtle import Screen, Turtle

wn = Screen()
wn.bgcolor("black")
wn.tracer(False)

# Write Tron
text = Turtle()
text.pencolor("aqua")
text.hideturtle()
text.penup()
text.setposition(150, 300)
text.write("TRON", font=("system", 30))

# Draw border
pen = Turtle()
pen.penup()
pen.pencolor("white")
pen.setposition(-300, -300)
pen.pendown()
pen.pensize(3)
for side in range(4):
    pen.forward(600)
    pen.left(90)
pen.hideturtle()

# Create player 1
player = Turtle()
player.setposition(240, 240)
player.setheading(180)
player.color("red")
player.shape("triangle")
player.speed(0)

# Create player 2
player2 = Turtle()
player2.setposition(-240, -240)
player2.color("aqua")
player2.shape("triangle")
player2.position()
player2.speed(0)

# Set turtle movement speed
speed = 3

# Set keyboard bindings for p1ayer 1
wn.listen()
wn.onkeypress(lambda: player.left(30), "Left")
wn.onkeypress(lambda: player.right(30), "Right")

# Set keyboard bindings for player 2
wn.onkeypress(lambda: player2.left(30), "a")
wn.onkeypress(lambda: player2.right(30), "d")
wn.onkeypress(lambda: player2.left(30), "A")
wn.onkeypress(lambda: player2.right(30), "D")
wn.tracer(True)

while True:
    player.forward(speed)
    player2.forward(speed)

    if player.distance(player2) < 30:
        print("collision")
        quit()

    # Check border collisions
    if (
        player.xcor() > 300 or player.xcor() < -300 or
        player.ycor() > 300 or player.ycor() < -300 or
        player2.xcor() > 300 or player2.xcor() < -300 or
        player2.ycor() > 300 or player2.ycor() < -300
    ):
        print("GAME OVER")
        quit()

Note that onkey is actually onkeyrelease, and that your game is subject to the operating system's keyboard retrigger timing. This leads to a poor experience. Following this post, you can decouple movement and key presses, leading to smooth movement:

# ...

# Set turtle movement speed
speed = 3
turn_speed = 15

# Set keyboard bindings for p1ayer 1
keys = set()
wn.listen()
wn.onkeypress(lambda: keys.add("Left"), "Left")
wn.onkeypress(lambda: keys.add("Right"), "Right")
wn.onkeyrelease(lambda: keys.remove("Left"), "Left")
wn.onkeyrelease(lambda: keys.remove("Right"), "Right")

# Set keyboard bindings for player 2
wn.onkeypress(lambda: keys.add("a"), "a")
wn.onkeypress(lambda: keys.add("d"), "d")
wn.onkeyrelease(lambda: keys.remove("a"), "a")
wn.onkeyrelease(lambda: keys.remove("d"), "d")
wn.tracer(True)

while True:
    if "Left" in keys:
        player.left(turn_speed)
    if "Right" in keys:
        player.right(turn_speed)
    if "a" in keys:
        player2.left(turn_speed)
    if "d" in keys:
        player2.right(turn_speed)

    player.forward(speed)
    player2.forward(speed)
    # ...
Source Link
ggorlen
  • 142
  • 10

The existing answer neglects the builtin turtle .distance() method which trivializes this:

while True:
    player.forward(speed)
    player2.forward(speed)

    if player.distance(player2) < 30:
        print("collision")
        quit()

That's it! If the distance between the turtles is less than 30 (pick a number to taste), quit the game.

Here's a quick rewrite:

import math
from turtle import Screen, Turtle

wn = Screen()
wn.bgcolor("black")
wn.tracer(False)

# Write Tron
text = Turtle()
text.pencolor("aqua")
text.hideturtle()
text.penup()
text.setposition(150, 300)
text.write("TRON", font=("system", 30))

# Draw border
pen = Turtle()
pen.penup()
pen.pencolor("white")
pen.setposition(-300, -300)
pen.pendown()
pen.pensize(3)
for side in range(4):
    pen.forward(600)
    pen.left(90)
pen.hideturtle()

# Create player 1
player = Turtle()
player.setposition(240, 240)
player.setheading(180)
player.color("red")
player.shape("triangle")
player.speed(0)

# Create player 2
player2 = Turtle()
player2.setposition(-240, -240)
player2.color("aqua")
player2.shape("triangle")
player2.position()
player2.speed(0)

# Set turtle movement speed
speed = 3

# Set keyboard bindings for p1ayer 1
wn.listen()
wn.onkey(lambda: player.left(30), "Left")
wn.onkey(lambda: player.right(30), "Right")

# Set keyboard bindings for player 2
wn.onkey(lambda: player2.left(30), "a")
wn.onkey(lambda: player2.right(30), "d")
wn.onkey(lambda: player2.left(30), "A")
wn.onkey(lambda: player2.right(30), "D")
wn.tracer(True)

while True:
    player.forward(speed)
    player2.forward(speed)

    if player.distance(player2) < 30:
        print("collision")
        quit()

    # Check border collisions
    if (
        player.xcor() > 300 or player.xcor() < -300 or
        player.ycor() > 300 or player.ycor() < -300 or
        player2.xcor() > 300 or player2.xcor() < -300 or
        player2.ycor() > 300 or player2.ycor() < -300
    ):
        print("GAME OVER")
        quit()

This can be improved further to turn magic numbers like 300 into global constants, and avoiding repetition in player creation and collision checks, left as an exercise.

Note also that the keyboard retrigger makes for a jarring movement experience. See this post for a better approach to design real-time turtle applications.