How to make one turtle follow another side by side? - python

I am just trying to make something very simple in turtle graphics, but I'm having trouble figuring out how to make one turtle stay next to another turtle, when that turtle is being controlled by someone using the keyboard.
I've tried looking this up but I couldn't find any answers.
'''
import turtle
wn = turtle.Screen()
wn.bgcolor("black")
def bob_start():
bob.speed(0)
bob.penup()
bob.hideturtle()
bob.goto(500,0)
bob.showturtle()
def fred_start():
fred.speed(0)
fred.penup()
fred.hideturtle()
fred.goto(-500,0)
fred.showturtle()
#Fred
fred = turtle.Turtle()
fred.color("red")
fred.shape("square")
fred.shapesize(stretch_len=2,stretch_wid=2)
fred_start()
#Bob
bob = turtle.Turtle()
bob.color("blue")
bob.shape("square")
bob.shapesize(stretch_len=2,stretch_wid=2)
bob_start()
#Bob Laser
bob_laser = turtle.Turtle()
bob_laser.shape("square")
bob_laser.shapesize(stretch_len=5,stretch_wid=0.5)
bob_laser.color("yellow")
bob_laser.penup()
def fred_up():
y = fred.ycor()
y += 4
fred.sety(y)
def fred_down():
y = fred.ycor()
y -= 4
fred.sety(y)
def bob_up():
y = bob.ycor()
y += 4
bob.sety(y)
def bob_down():
y = bob.ycor()
y -= 4
bob.sety(y)
# Key Bindings
turtle.listen()
turtle.onkeypress(fred_up, "w")
turtle.onkeypress(fred_down, "s")
turtle.onkeypress(bob_up, "Up")
turtle.onkeypress(bob_down, "Down")
wn.exitonclick()
while bob_laser.ycor != bob.ycor:
bob_laser.penup()
bob_laser.hideturtle()
bob_laser.goto(500,bob.ycor)
bob_laser.showturtle()
'''
I am trying to make one turtle stay next to another turtle while that turtle is being controlled by a person.

Depending on what you're ultimately trying to do, the answer could be as simple as:
bob_laser.goto(bob.position())
whenever you move turtle bob. Here's a rework of your code using this approach:
from turtle import Screen, Turtle
def turtle_start(color, x_coordinate):
turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.shapesize(2)
turtle.speed('fastest')
turtle.setheading(90)
turtle.penup()
turtle.color(color)
turtle.setx(x_coordinate)
turtle.showturtle()
return turtle
def fred_up():
fred.forward(4)
def fred_down():
fred.backward(4)
def bob_up():
screen.onkeypress(None, 'Up') # disable complex handler inside handler
bob.forward(4)
bob_laser.goto(bob.position())
screen.onkeypress(bob_up, 'Up') # reenable handler
def bob_down():
screen.onkeypress(None, 'Down')
bob.backward(4)
bob_laser.goto(bob.position())
screen.onkeypress(bob_down, 'Down')
screen = Screen()
screen.setup(1200, 600)
screen.bgcolor('black')
# Fred
fred = turtle_start('red', -500)
# Bob
bob = turtle_start('blue', 500)
# Bob Laser
bob_laser = Turtle()
bob_laser.shape('square')
bob_laser.shapesize(stretch_len=5, stretch_wid=0.5)
bob_laser.color('yellow')
bob_laser.penup()
# Key Bindings
screen.onkeypress(fred_up, 'w')
screen.onkeypress(fred_down, 's')
screen.onkeypress(bob_up, 'Up')
screen.onkeypress(bob_down, 'Down')
screen.listen()
screen.exitonclick()

Related

Why won't my square move right? I'm trying all different methods to move it in turtle module it works for up and down but not left and right?

# Game creation
import turtle
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("Black")
wn.setup(width=800, height=800)
wn.tracer(0)
# paddle a
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.penup()
paddle_a.goto(0, 0)
# Functions
def paddle_a_right():
turtle.forward(100)
wn.onkeypress(paddle_a_right, 'd')
while True:
wn.update()
Want the square to move to the right or left using 'a' or 'd' I don't know very much about turtle, I just want to program a simple game.
There are three major issues with your code. First, you need to call wn.listen() to allow the window to receive keyboard input. Second, you do turtle.forward(100) when you mean paddle_a.forward(100). Finally, since you did tracer(0), you now need to call wn.update() anytime a change is made that you want your user to see.
Here's a simplified example:
from turtle import Screen, Turtle
def paddle_right():
paddle.forward(10)
screen.update()
screen = Screen()
screen.title("Pong")
screen.bgcolor("Black")
screen.setup(width=800, height=800)
screen.tracer(0)
paddle = Turtle()
paddle.shape("square")
paddle.color("white")
paddle.penup()
screen.onkeypress(paddle_right, 'd')
screen.listen()
screen.update()
screen.mainloop()

i am getting an error it is saying turtle object not callable

import turtle
import tkinter as tk
def importantmoving():
win = turtle.Screen()
win.title("moving")
win.bgcolor("black")
win.setup(width=800, height=800)
win.tracer(0)
#moving
a = turtle.Turtle()
a.speed(0)
a.shape("square")
a.color("white")
a.shapesize(stretch_wid=5,stretch_len=5)
a.penup()
a.goto(0,0)
#functions
def a_up():
y = a.ycor()
y += 20
a.sety(y)
def a_down():
y = a.ycor()
y -= 20
a.sety(y)
def a_right():
x = a.xcor()
x += 20
a.setx(x)
def a_left():
x = a.xcor()
x -= 20
a.setx(x)
#keyboard binding
win.listen()
win.onkeypress(a,"Up")
win.onkeypress(a,"Right")
win.onkeypress(a,"Down")
win.onkeypress(a,"Left")
while True:
win.update()
importantmoving()
and this is the code
i first tried to run my code see in which line my error was and the it came up with line 1921 and my code is 43 lines so i didn't know what to do so i ask here
Besides the callback issue that #JohnnyMopp notes (+1), this code is poorly constructed. The while True: loop is simply not needed nor desirable. It's not clear why everything is bundled inside importantmoving(). You also don't need to import tkinter. Below is my rework of your code, see if it does what you intend:
from turtle import Screen, Turtle
def a_up():
turtle.sety(turtle.ycor() + 20)
def a_down():
turtle.sety(turtle.ycor() - 20)
def a_right():
turtle.setx(turtle.xcor() + 20)
def a_left():
turtle.setx(turtle.xcor() - 20)
screen = Screen()
screen.title("moving")
screen.bgcolor('black')
screen.setup(width=800, height=800)
turtle = Turtle()
turtle.shape('square')
turtle.shapesize(5)
turtle.color('white')
turtle.speed('fastest')
turtle.penup()
screen.onkeypress(a_up, 'Up')
screen.onkeypress(a_right, 'Right')
screen.onkeypress(a_down, 'Down')
screen.onkeypress(a_left, 'Left')
screen.listen()
screen.mainloop()

Use of ontimer function to make two turtles move at same time

I 've been struggling to make both turtles move at the same time. Either one moves or they are both are frozen. I'm currently using the ontimer() function but still don't understand it completely.
The game is if you are wondering based of the paperio game but two players go against each other on the same keyboard and screen
My code:
from turtle import *
import turtle
p1f = True
p2f = True
title("1v1 Paperio")
p1move = Turtle()
p2move = Turtle()
t1 = Turtle()
t2 = Turtle()
screen = Screen()
def Setup1():
t1.pencolor("aquamarine")
t1.pensize(5)
t1.speed(10)
t1.fillcolor("light sea green")
t1.hideturtle()
t1.penup()
t1.goto(-200, -200)
t1.pendown()
t1.begin_fill()
for i in range(4):
t1.forward(50)
t1.left(90)
t1.end_fill()
p1move.penup()
p1move.goto(-175, -175)
p1move.pendown()
def Setup2():
t2.pencolor("crimson")
t2.pensize(5)
t2.speed(10)
t2.fillcolor("red")
t2.hideturtle()
t2.penup()
t2.goto(200, 200)
t2.pendown()
t2.begin_fill()
for i in range(4):
t2.forward(50)
t2.left(90)
t2.end_fill()
p2move.penup()
p2move.goto(225, 225)
p2move.pendown()
def p1setup():
p1move.pencolor("aquamarine")
p1move.pensize(5)
p1move.speed(10)
p1move.fillcolor("light sea green")
def p2setup():
p2move.pencolor("crimson")
p2move.pensize(5)
p2move.speed(10)
p2move.fillcolor("red")
# ycord
# heading
def p1moving():
def p1k1():
p1x1 = p1move.xcor()
p1y1 = p1move.ycor()
while p1f == True:
p1move.forward(1)
screen.ontimer(p1moving, 1)
def p1k2():
p1move.left(90)
def p1k3():
p1move.right(90)
def p2moving():
def p2k1():
p2f = True
p2x2 = p2move.xcor()
p2y2 = p2move.ycor()
while p2f == True:
p2move.forward(1)
screen.ontimer(p2moving, 1)
def p2k2():
p2move.left(90)
def p2k3():
p2move.right(90)
screen.listen()
screen.onkey(p1k1, "w")
screen.onkey(p1k2, "a")
screen.onkey(p1k3, "d")
screen.onkey(p2k1, "Up")
screen.onkey(p2k2, "Left")
screen.onkey(p2k3, "Right")
if __name__ == "__main__":
Setup1()
Setup2()
p1setup()
p2setup()
screen.mainloop()
Most of your code seems reasonable until you get to the key and timer event functions -- you have unused variables and functions that don't get called. Your functions defined inside functions are particularly problematic. I've reworked your code below to run as you describe. I've also done some speed optimizations to make it "play" a little better:
from turtle import Screen, Turtle
def setup1():
base1.hideturtle()
base1.color("light sea green", "aquamarine")
base1.pensize(5)
base1.penup()
base1.goto(-200, -200)
base1.pendown()
base1.begin_fill()
for _ in range(4):
base1.forward(50)
base1.left(90)
base1.end_fill()
pen1.color("light sea green", "aquamarine")
pen1.pensize(5)
pen1.setheading(0)
pen1.penup()
pen1.goto(-175, -175)
pen1.pendown()
def setup2():
base2.hideturtle()
base2.color("red", "pink")
base2.pensize(5)
base2.penup()
base2.goto(200, 200)
base2.pendown()
base2.begin_fill()
for _ in range(4):
base2.forward(50)
base2.left(90)
base2.end_fill()
pen2.color("red", "pink")
pen2.pensize(5)
pen2.setheading(180)
pen2.penup()
pen2.goto(225, 225)
pen2.pendown()
def p1k1():
screen.onkey(None, 'w')
def p1forward():
pen1.forward(1)
screen.update()
screen.ontimer(p1forward, 10)
p1forward()
def p1k2():
pen1.left(90)
screen.update()
def p1k3():
pen1.right(90)
screen.update()
def p2k1():
screen.onkey(None, 'Up')
def p2forward():
pen2.forward(1)
screen.update()
screen.ontimer(p2forward, 10)
p2forward()
def p2k2():
pen2.left(90)
screen.update()
def p2k3():
pen2.right(90)
screen.update()
screen = Screen()
screen.title("1v1 Paperio")
screen.tracer(False)
base1 = Turtle()
pen1 = Turtle()
setup1()
base2 = Turtle()
pen2 = Turtle()
setup2()
screen.onkey(p1k1, 'w')
screen.onkey(p1k2, 'a')
screen.onkey(p1k3, 'd')
screen.onkey(p2k1, 'Up')
screen.onkey(p2k2, 'Left')
screen.onkey(p2k3, 'Right')
screen.update()
screen.listen()
screen.mainloop()

Is there a way to keep drawing a square with one turtle while, at the same time, moving another turtle with the arrow keys?

I am trying to move a drawing slowly across the screen as I move another turtle with the arrow keys. The problem is that my code only makes the drawing move across the screen, not allowing me to move the other turtle with the keys. I have tried defining the keys inside of the while true statement and it still came out with the same outcome.
Here is my code:
from turtle import *
setup(500, 500)
Screen()
screen = Screen()
title("Turtle Keys")
turtle1 = Turtle()
turtle2 = Turtle()
def moving_square():
turtle1.fillcolor("Red")
turtle1.begin_fill()
for i in range(4):
turtle1.forward(50)
turtle1.right(90)
turtle1.end_fill()
turtle1.goto(-350, 0)
turtle1.pendown()
turtle1.hideturtle()
def k1():
turtle2.forward(50)
def k2():
turtle2.left(45)
def k3():
turtle2.right(45)
def k4():
turtle2.back(25)
onkey(k1, "Up")
onkey(k2, "Left")
onkey(k3, "Right")
onkey(k4, "Down")
while True:
moving_square()
screen.update()
turtle1.forward(5)
It needs listen() to react on pressed keys.
And you have this information even in documentation for onkey()
from turtle import *
# --- functions ---
def moving_square():
turtle1.fillcolor("Red")
turtle1.begin_fill()
for i in range(4):
turtle1.forward(50)
turtle1.right(90)
turtle1.end_fill()
def k1():
turtle2.forward(50)
def k2():
turtle2.left(45)
def k3():
turtle2.right(45)
def k4():
turtle2.back(25)
# -- main ---
setup(500, 500)
Screen()
screen = Screen()
title("Turtle Keys")
turtle1 = Turtle()
turtle2 = Turtle()
turtle1.goto(-350, 0)
turtle1.pendown()
turtle1.hideturtle()
onkey(k1, "Up")
onkey(k2, "Left")
onkey(k3, "Right")
onkey(k4, "Down")
listen()
while True:
moving_square()
screen.update()
turtle1.forward(5)
For more game-like action, I would go about this a different way. First, by not drawing a red square but by making the first turtle into a red square. Second, by using a timed event instead of a while True: loop:
from turtle import Screen, Turtle
WIDTH, HEIGHT = 500, 500
BLOCK_SIZE = 50
CURSOR_SIZE = 20
def k1():
turtle.forward(50)
def k2():
turtle.left(45)
def k3():
turtle.right(45)
def k4():
turtle.back(25)
def move():
block.forward(1)
if block.xcor() < WIDTH/2 + BLOCK_SIZE/2:
screen.ontimer(move, 75) # milliseconds
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.title("Turtle Keys")
block = Turtle()
block.hideturtle()
block.shape('square')
block.fillcolor('red')
block.shapesize(BLOCK_SIZE / CURSOR_SIZE)
block.penup()
block.setx(-WIDTH/2 - BLOCK_SIZE/2)
block.showturtle()
turtle = Turtle()
turtle.shape('turtle')
turtle.penup()
screen.onkey(k1, 'Up')
screen.onkey(k2, 'Left')
screen.onkey(k3, 'Right')
screen.onkey(k4, 'Down')
screen.listen()
move()
screen.mainloop()
You can increase the speed of the block by adjusting block.forward(1) to higher value. And if you need a trailing line, you can put the pen down.

Python turtle not moving on arrow press

I am trying to make my turtle (main_ship) move across the bottom of my screen according to when the user presses the left and right arrow keys but the turtle is not moving. I have used the same code before when making Pong so I'm not sure why it's not working.
import turtle
wn = turtle.Screen()
wn.title("Game")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
main_ship = turtle.Turtle()
main_ship.speed(0)
main_ship.shape("turtle")
main_ship.color("green")
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.penup()
main_ship.goto(0, -290)
main_ship.left(90)
def main_ship_right():
x = main_ship.xcor()
x += 20
main_ship.setx(x)
def main_ship_left():
x = main_ship.xcor()
x -= 20
main_ship.setx(x)
while True:
wn.update()
wn.mainloop()
wn.listen()
wn.onkeypress(main_ship_right, "Right")
wn.onkeypress(main_ship_left, "Left")
When I press the arrow keys, nothing happens but the code still runs and there are no error messages.
You have to assign keys before mainloop() which runs all time till you close window.
You don't need while True because mainloop() already runs internal loop.
You may have to remove wm.tracer(0) or you will have to run wn.update() to refresh elements in window.
import turtle
# --- functions ---
def main_ship_right():
x = main_ship.xcor()
x += 20
main_ship.setx(x)
wn.update()
def main_ship_left():
x = main_ship.xcor()
x -= 20
main_ship.setx(x)
wn.update()
# --- main ---
wn = turtle.Screen()
wn.title("Game")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
main_ship = turtle.Turtle()
main_ship.speed(0)
main_ship.shape("turtle")
main_ship.color("green")
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.penup()
main_ship.goto(0, -290)
main_ship.left(90)
wn.update()
wn.listen()
wn.onkeypress(main_ship_right, "Right")
wn.onkeypress(main_ship_left, "Left")
wn.mainloop()
For this style of motion, there's another way to implement it. The idea is to leave the cursor moving in it's original orientation, but use settiltangle() to make it look like it's facing upward.
This lets us use forward(20) and backward(20) to move our cursor, and not have to write:
x = main_ship.xcor()
x += 20
main_ship.setx(x)
Works great for Space Invader style games, where the player faces upwards but moves sideways:
from turtle import Screen, Turtle
from functools import partial
screen = Screen()
screen.title("Game")
screen.bgcolor('black')
screen.setup(width=800, height=600)
main_ship = Turtle('turtle')
main_ship.speed('fastest')
main_ship.color('green')
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.settiltangle(90)
main_ship.penup()
main_ship.sety(-290)
screen.onkeypress(partial(main_ship.forward, 20), 'Right')
screen.onkeypress(partial(main_ship.backward, 20), 'Left')
screen.listen()
screen.mainloop()
Only works in the turtle library that comes with Python -- online Python development sites usually provide limited turtle implementations that don't include methods like settiltangle().

Categories