Stop a moving Python turtle when it's close to another turtle - python

How do I stop a randomly moving turtle using a while loop when it comes with 50 units of another turtle?
I have one turtle that randomly selects a location and creates a large dot or hole, and another turtle that moves around randomly making 90 degree turns and moving forward 50 units every time. The randomly moving turtle stops when it goes off of the end of the screen, but how do I also make the turtle stop when it gets to the hole created by the other turtle?
import random
import turtle
def turtlesClose(t1, t2):
if t1.distance(t2)<50:
return True
else:
return False
def isInScreen(win,turt):
leftBound = -win.window_width() / 2
rightBound = win.window_width() / 2
topBound = win.window_height() / 2
bottomBound = -win.window_height() / 2
turtleX = turt.xcor()
turtleY = turt.ycor()
stillIn = True
if turtleX > rightBound or turtleX < leftBound:
stillIn = False
if turtleY > topBound or turtleY < bottomBound:
stillIn = False
return stillIn
def main():
wn = turtle.Screen()
# Define your turtles here
june = turtle.Turtle()
july = turtle.Turtle()
july.shape('turtle')
july.up()
july.goto(random.randrange(-250, 250, 1), random.randrange(-250, 250, 1))
july.down()
july.dot(100)
june.shape('turtle')
while isInScreen(wn,june):
coin = random.randrange(0, 2)
dist = turtlesClose(july, june)
if coin == 0:
june.left(90)
else:
june.right(90)
june.forward(50)
if dist == 'True':
break
main()

The problem with your code is this statement:
if dist == 'True':
You don't want quotes around True. Although this will work:
if dist == True:
The correct way to express this is:
if dist is True:
or better yet:
if dist:
Otherwise your code seems to work. Below's a rewrite taking advantage of some turtle idioms and other code cleanup:
from random import randrange, choice
from turtle import Screen, Turtle
CURSOR_SIZE = 20
def turtlesClose(t1, t2):
return t1.distance(t2) < 50
def isInScreen(window, turtle):
leftBound = -window.window_width() / 2
rightBound = window.window_width() / 2
topBound = window.window_height() / 2
bottomBound = -window.window_height() / 2
turtleX, turtleY = turtle.position()
return leftBound < turtleX < rightBound and bottomBound < turtleY < topBound
def main():
screen = Screen()
july = Turtle('circle')
july.shapesize(100 / CURSOR_SIZE)
july.up()
july.goto(randrange(-250, 250), randrange(-250, 250))
july.down()
june = Turtle('turtle')
while isInScreen(screen, june):
if turtlesClose(july, june):
break
turn = choice([june.left, june.right])
turn(90)
june.forward(50)
main()

Related

How to prevent Python Turtle from going through lines it has drawn?

I'm making a game using Turtle in Python 3.
My main problem is that the turtle can move through the "drawn" lines in the game. It's basically a randomized "flappy-bird" game, different each time you run the program.
Is it possible to prevent the Turtle from going through lines it has drawn?
The program creates both walls and holes the player should be able to get through, like flappy bird where it's a pipe-hole-pipe with different lengths on the pipes.
And if I run print(hole) at the end of the program it returns None. Why is this?
Here is my program:
import turtle
import random
GameOver=False
import math
import time
board = turtle.Screen()
board.screensize(50.50)
board.bgcolor("black")
board.title("Labyrinten")
Hast_på_ritande_av_bana= 0
TURTLE_SIZE = 20
playerspeed = 50
n=1 #variabeler som gör att den hoppar ett steg åt höger när den gör raderna t.ex. ((930/8)*n)
b=2 #
global player
#SÄTTER UPP SKÄRM
border = turtle.Turtle()
border.speed(Hast_på_ritande_av_bana)
border.hideturtle()
border.color("white")
border.shape("triangle")
border.penup()
border.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.pendown()
border.showturtle()
border.rt(90)
border.fd(780)
border.penup()
#ritar banan
for rader in range(4): #creating the maze
border.lt(90)
border.fd(930/8)
border.pendown()
border.lt(90)
wall_ett = border.fd(random.randint(50,630)) #lower wall on row 1
border.penup()
hole=border.fd(random.randint(30,70)) #hole on row 1
border.pendown()
wall_ett_ett = border.goto (TURTLE_SIZE/2 - board.window_width()/2 + (930/8*n), board.window_height()/2 - TURTLE_SIZE/2) #higher wall on row 1
border.rt(90)
border.fd(930/8)
border.rt(90)
wall_två_ett = border.fd(random.randint(50, 630)) #lower wall on row 2
border.penup()
hole2 = border.fd(random.randint(30, 70)) #hole on row 2
border.pendown()
wall_två_två = border.goto(TURTLE_SIZE/2 - board.window_width()/2 + (930/8*b), + TURTLE_SIZE/2 - board.window_height()/2 ) # higher wall on row 2
n = n + 2
b = b + 2
border.goto(TURTLE_SIZE/2 - board.window_width()/2 , TURTLE_SIZE/2 - board.window_height()/2 )
border.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.penup()
border.lt(90)
border.fd(930/8)
border.pendown()
border.goto(-TURTLE_SIZE + board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.hideturtle()
player=turtle.Turtle()
player.color("green")
player.shape("turtle")
player.hideturtle()
player.penup()
player.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
player.rt(90)
player.fd(30)
player.lt(90)
player.fd((930/8)/2)
player.rt(90)
player.showturtle()
coordinates = player.pos()
#Skapa spelaren (som går igenom banan)
def spawna_spelare():
spawn = turtle.Turtle()
spawn.color("green")
spawn.shape("turtle")
spawn.hideturtle()
spawn.penup()
spawn.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
spawn.rt(90)
spawn.fd(30)
spawn.lt(90)
spawn.fd((930/8)*(random.randint(1,8)))
spawn.rt(90)
spawn.showturtle()
#Gå med spelaren
def move_left():
x = player.xcor()
x -= playerspeed
if x < -460:
x = -460
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x > 450:
x = 450
player.setx(x)
if x.distance(wall_ett) >20: #or wall_ett_ett or wall_två_ett or wall_två_två) == 1: #
player.shape("triangle")
def move_down():
y = player.ycor()
y -= playerspeed
if y < -375:
y = -375
player.sety(y)
def move_up():
y = player.ycor()
y += playerspeed
if y > 380:
y = 380
player.sety(y)
turtle.listen()
turtle.onkey(spawna_spelare, "space")
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_down, "Down")
turtle.onkey(move_up, "Up")
wall_ett = border.xcor()
wall_två_ett=border.xcor()
print(wall_ett)
print(wall_ett)
print(hole)
board.mainloop()
So you need to draw the walls in a way you can check afterwards if the move the player requested is crossing any wall (or border).
here is a suggestion:
SCREEN_WIDTH = 800
HOLE_HEIGHT = 50
SCREEN_HEIGHT = 600
NUM_WALLS = 8
board = turtle.Screen()
board.setup(SCREEN_WIDTH+10, SCREEN_HEIGHT+10)
board.screensize(SCREEN_WIDTH, SCREEN_HEIGHT)
board.setworldcoordinates(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
border = turtle.Turtle()
border.speed(10) # draw walls as fast as possible
border.color('white')
border.hideturtle()
# list of the drawn walls, each wall is represented by a tuple:
# (wall_x, wall_hole_lower_y, wall_hole_upper_y)
walls = []
for wall_ix in range(NUM_WALLS):
# compute coordinates of wall and store them
wall_x = int((1+wall_ix) * SCREEN_WIDTH / (1+NUM_WALLS))
wall_ybottom = random.randint(0, SCREEN_HEIGHT - HOLE_HEIGHT)
wall_ytop = wall_ybottom + HOLE_HEIGHT
walls.append((wall_x, wall_ytop, wall_ybottom))
# draw wall
border.penup()
border.goto(wall_x, 0)
border.pendown()
border.goto(wall_x, wall_ybottom)
border.penup()
border.goto(wall_x, wall_ytop)
border.pendown()
border.goto(wall_x, SCREEN_HEIGHT)
def move_right():
old_x = player.xcor()
new_x = old_x + playerspeed
y = player.ycor()
for wall_x, wall_ytop, wall_ybottom in walls:
if old_x <= wall_x <= new_x:
# player is possibly moving across the wall, check that y is valid
if wall_ybottom < y < wall_ytop:
# OK ! player moves through the hole
player.setx(new_x)
else:
# invalid, player is crossing a wall line
# resetting to old position, but you might want to stop the game
player.setx(old_x)

Keeping the turtle inside a square, no output and no errors

I wanted turtle not to go out of square
the window comes out and no error but loading keeps and if I click the window, it shuts down.
x, y is turtle's location.
D is to show weather or not turtle is inside square and on line(?).
a is nothing
direction changes
speed changes
location check and change
if turtle's in line, it go along boundary.
import turtle
import msvcrt
turtle.setup(100, 100, 0, 0)
t = turtle.Turtle()
D = 0
a = 1
while True:
if msvcrt.kbhit():
c = msvcrt.getch().decode('UTF - 8')
if c == 'j': # turn left
t.left(10)
if c == 'k':
t.right(10)
if c == 'a':# speed change
a += 1
if a > 10: # speed limitation
a = 10
if c == 'z':
a += -1
if a < 0:
a = 0
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
if x > 100: # if go out of square, go back to the square
t.setx(100)
if x < -100:
t.setx(-100)
if y > 100:
t.sety(100)
if y < -100:
t.sety(-100)
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
h = t.heading() # turtle's direction
#---------------------------------------
if - 100 < x < 100 and -100 < y < 100:
D = 0 # if it's in the square, D = 0
elif x == 100 and -100 < y < 100: # if it's in ~
if 0 <= d <= 90: # direction changes
t.setheading(90) # direction change to 90 degrees
D = 1 # D = 1
elif 270 <= d < 360:
t.setheading(270)
D = 2
elif x == -100 and -100 < y < 100:
if 90 <= d < 180:
t.setheading(90)
D = 2
elif 180 <= d <= 270:
t.setheading(270)
D = 1
elif y == 100 and -100 < x < 100:
if 0 <= d < 90:
t.setheading(0)
D = 2
elif 90 <= d <= 180:
t.setheading(180)
D = 1
elif y == -100 and -100 < x < 100:
if 180 <= d < 270:
t.setheading(180)
D = 2
elif 270 <= d < 360:
t.setheading(0)
D = 1
elif D == 1:
t.left(90)
elif D == 2:
t.right(90)
This code is a mess. First, by setting your window size to 100 x 100 and then moving your turtle between -100 and 100 in both dimensions, only 1/4 of your field of play is visible! Why use the msvcrt module when turtle has perfectly good keyboard events built in? As far as I can tell, your code checks and corrects the turtle's position but never actually moves it! And you have a while True: loop which has no place in an event-driven environment like turtle.
Let's start over with a simple example of motion within a square which can be manipulated via the keyboard:
from turtle import Screen, Turtle
def turn_left():
turtle.left(10)
def turn_right():
turtle.right(10)
def speed_up():
speed = turtle.speed() + 1
if speed > 10: # speed limitation
speed = 10
turtle.speed(speed)
def slow_down():
speed = turtle.speed() - 1
if speed < 1: # speed limitation
speed = 1
turtle.speed(speed)
def move():
# there are two different senses of 'speed' in play, we'll exploit
# both! I.e. as we move faster, we'll draw faster and vice versa
turtle.forward(turtle.speed())
# if we go out of square, go back into the square
if not -100 < turtle.xcor() < 100:
turtle.undo()
turtle.setheading(180 - turtle.heading())
elif not -100 < turtle.ycor() < 100:
turtle.undo()
turtle.setheading(360 - turtle.heading())
screen.ontimer(move, 100)
screen = Screen()
screen.setup(300, 300)
# show turtle's boundary
boundary = Turtle('square', visible=False)
boundary.color('pink')
boundary.shapesize(10)
boundary.stamp()
turtle = Turtle()
move()
screen.onkey(turn_left, 'j')
screen.onkey(turn_right, 'k')
screen.onkey(speed_up, 'a')
screen.onkey(slow_down, 'z')
screen.listen()
screen.mainloop()

When I make 2 turtles collide, Python freezes and crashes

import turtle
import os
import math
ms = turtle.Screen()
ms.bgcolor("grey")
ms.title("ok")
ground = turtle.Turtle()
ground.speed(0)
ground.color("black")
ground.penup()
ground.setposition(-500, -500)
ground.shape("square")
ground.shapesize(20, 200)
player = turtle.Turtle()
player.shape("square")
player.color("blue")
player.penup()
player.speed(0)
player.setposition(-450, -280)
playerspeed = 15
prop = turtle.Turtle()
prop.speed(0)
prop.shape("square")
prop.penup()
prop.color("red")
prop.setposition(-200, -50)
def move_left():
x = player.xcor()
x-= playerspeed
if x <-460:
x = - 460
player.setx(x)
def move_right():
x = player.xcor()
x+= playerspeed
if x >460:
x = 460
player.setx(x)
def move_down():
y = player.ycor()
y-= playerspeed
if y <-290:
y = - 290
player.sety(y)
def move_up():
y = player.ycor()
y+= playerspeed
if y >290:
y = 290
player.sety(y)
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))
if distance < 10:
return True
else:
return False
while True:
if isCollision(player, prop):
player.setposition(100, 100)
If I change the distance to > 10
it works but not as I want it to.
I want it to change the position of the player when prop and player are 10 pixels or less away from each other.
I've tried most things I know about, but I am still new to Python, or any programming language.
But I don't know what would cause it to freeze and crash -- any help is appreciated.
The primary issue I see with your code is while True: which shouldn't be used in an event-based environment. By creating a tight loop, you can keep events (key pressed, cursor movements, window closing) from being processed.
Below is a rework of your code using a timer event instead of while True:. I've also parameterized it as every turtle user sees a different size default window based on the dimensions of their screen. So you either need to use setup() to force a fixed size window or have your code adust to the window size. Now it adjusts to the window size. I've also made prop move to a random location upon collision, just to make the game more fun for me to play. And I've tossed your distance code in favor of turtle's own implementation:
from turtle import Screen, Turtle, mainloop
from random import randint
PLAYER_SPEED = 15
GROUND_HEIGHT = 100
PROXIMITY = 10
CURSOR_SIZE = 20
def move_left():
x = player.xcor() - PLAYER_SPEED
if x < CURSOR_SIZE - width/2:
x = CURSOR_SIZE - width/2
player.setx(x)
def move_right():
x = player.xcor() + PLAYER_SPEED
if x > width/2 - CURSOR_SIZE:
x = width/2 - CURSOR_SIZE
player.setx(x)
def move_down():
y = player.ycor() - PLAYER_SPEED
if y < CURSOR_SIZE/2 + GROUND_HEIGHT - height/2:
y = CURSOR_SIZE/2 + GROUND_HEIGHT - height/2
player.sety(y)
def move_up():
y = player.ycor() + PLAYER_SPEED
if y > height/2 - CURSOR_SIZE:
y = height/2 - CURSOR_SIZE
player.sety(y)
def isCollision(t1, t2):
return t1.distance(t2) < PROXIMITY
def random_position():
x = randint(CURSOR_SIZE - width//2, width//2 - CURSOR_SIZE)
y = randint(CURSOR_SIZE + GROUND_HEIGHT - height//2, height//2 - CURSOR_SIZE)
return x, y
def check():
if isCollision(player, prop):
prop.setposition(random_position())
ms.ontimer(check, 100)
ms = Screen()
ms.bgcolor('grey')
ms.title("ok")
width, height = ms.window_width(), ms.window_height()
ground = Turtle('square')
ground.shapesize(GROUND_HEIGHT / CURSOR_SIZE, width / CURSOR_SIZE)
ground.speed('fastest')
ground.penup()
ground.sety(GROUND_HEIGHT/2 - height/2)
player = Turtle('square')
player.speed('fastest')
player.color('blue')
player.penup()
player.setposition(CURSOR_SIZE/2 - width/2, GROUND_HEIGHT + CURSOR_SIZE/2 - height/2)
prop = Turtle('square')
prop.speed('fastest')
prop.color('red')
prop.penup()
prop.setposition(random_position())
ms.onkey(move_left, 'Left')
ms.onkey(move_right, 'Right')
ms.onkey(move_up, 'Up')
ms.onkey(move_down, 'Down')
ms.listen()
check()
mainloop()

Python while loop with no expressions

Is is possible to have a while loop in Python with no expressions?
I know in other languages you can do something like:
while(flag) {};
I'm trying to do something similar in Python but cannot find an answer.
Here is what I have so far:
import turtle
from random import randrange
def is_in_screen(t, w): #CHECKS TO SEE IF STILL IN SCREEN
flag = True
r = w.window_width() / 2
l = r * -1
u = w.window_height() / 2
d = u * -1
x_cor = t.xcor()
y_cor = t.ycor()
if (x_cor < l or x_cor > r or y_cor < d or y_cor > u):
flag = False
return flag
def move_to(t, w): #MOVE IN RANDOM DIRECTION AND RANDOM DISTANCE
t.forward(randrange(1, 100))
if (randrange(1, 2) == 1):
t.left(randrange(1, 180))
else:
t.right(randrange(1, 180))
return is_in_screen(t, w)
def random_movement(t1, t2, w):
while (move_to(t1, w) and move_to(t2, w)): #<<<<<<<<LOOP IN QUESTION
i = 0
def main():
t1 = turtle.Turtle()
t2 = turtle.Turtle()
w = turtle.Screen()
t1.color("green")
t2.color("purple")
random_movement(t1, t2, w)
w.exitonclick()
main()
The reason I'm trying to do no expressions is because I want the second turtle to not move if the first turtle goes out of bounds. Also, I do not want return statements in the function.
You're looking for the pass keyword.
while (flag):
pass
Below is a rework of your code with the while expr: pass that everyone's suggesting along with some other style and idiom changes to tighten up the code:
from turtle import Screen, Turtle
from random import randrange
def is_in_screen(turtle, screen):
r = screen.window_width() / 2
u = screen.window_height() / 2
x, y = turtle.position()
return -r < x < r and -u < y < u
def move_to(turtle, screen):
turtle.forward(randrange(1, 100))
turtle.left(randrange(-180, 180)) # negative left turn is a right turn
return is_in_screen(turtle, screen)
def random_movement(turtle_1, turtle_2, screen):
while move_to(turtle_1, screen) and move_to(turtle_2, screen): pass
screen = Screen()
t1 = Turtle()
t1.color("green")
t2 = Turtle()
t2.color("purple")
random_movement(t1, t2, screen)
screen.exitonclick()

Making snake in Python, can't get bodies to follow head etc

I wanted to make a snake game in turtle but I can't seem to get the tail segments to follow the leader. As if to say I can't get the first body part to follow the head, and then the second body part to follow the first body, etc.
I tried using what maths I have but I can't seem to get it to calculate where the head just was or where the body in front of it just was.
here is my code:
#libraries
import turtle
import random
import math
#screen
the_screen = turtle.Screen()
the_screen.bgcolor("lightgreen")
the_screen.title("Catapillar")
#border
border_writer = turtle.Turtle()
border_writer.speed(0)
border_writer.color("green")
border_writer.penup()
border_writer.setposition(-275, -275)
border_writer.pendown()
border_writer.pensize(7)
for side in range(4):
border_writer.fd(550)
border_writer.lt(90)
border_writer.hideturtle()
#player
player = turtle.Turtle()
player.color("yellow")
player.shape("circle")
player.penup()
player.speed(0)
player.setposition(0,0)
player.setheading(0)
playerspeed = 2
#fruit
fruit = 1
fruit = turtle.Turtle()
fruit.color("red")
fruit.shape("circle")
fruit.penup()
fruit.speed(0)
fruit.shapesize(0.6, 0.6)
x = random.randint(-200, 200)
y = random.randint(100, 250)
fruit.setposition(x, y)
#moving and collision checker
def turnleft():
player.left(24.5)
def turnright():
player.right(24.5)
def increasespeed():
global playerspeed
playerspeed += 1
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(), 2) + math.pow(t1.ycor()-t2.ycor(), 2))
if distance < 24:
return True
else:
return False
#making the tail(s) and hiding them
tail1 = turtle.Turtle()
tail1.hideturtle()
tail1.color("yellow")
tail1.shape("circle")
tail1.penup()
tail1.speed(0)
tail1.setposition(+700,700)
tail1.shapesize(0.6, 0.6)
tail1state = 'off'
#key presses
turtle.listen()
turtle.onkeypress(turnleft, "Left")
turtle.onkeypress(turnright, "Right")
turtle.onkeypress(increasespeed, "Up")
#main loop player always moves forward, out of bound set, reset fruit
#randomly when collided, create tail1...
while True:
player.forward(playerspeed)
#gameovers'
if (player.xcor() > 275) or (player.xcor() < -275):
playerspeed += 7
print("GAME OVER")
if (player.ycor() > 275) or (player.ycor() < -275):
playerspeed += 7
print("GAME OVER")
#collision check between fruit and head
if isCollision(player, fruit):
#resets the fruit, moves it randomly
fruit.hideturtle()
if tail1state == 'off':
uuu = player.xcor()
vvv = player.ycor()
tail1.setposition(uuu,vvv)
tail1.showturtle()
tail1state = 'on'
#reset the fruit
x = random.randint(-200, 200)
y = random.randint(-100, 250)
fruit.setposition(x, y)
fruit.showturtle()
#playerspeed +=1
If you have any idea on how you think I should approach it, please let me know what you think.
Thank you.
Since this comes up over and over (but effort to effect it is rarely shown) here's my minimal, generic, slithering around a screen effect that you should be able to adapt for your own purposes:
from turtle import Turtle, Screen
SNAKE_LENGTH = 10
SNAKE_SIZE = 15
WIDTH, HEIGHT = 375, 375
CURSOR_SIZE = 20
def slither():
segment = snake[-1].clone() if len(snake) < SNAKE_LENGTH else snake.pop(0)
screen.tracer(False) # segment.hideturtle()
segment.setposition(snake[-1].position())
segment.setheading(snake[-1].heading())
segment.forward(SNAKE_SIZE)
while not -WIDTH/2 < segment.xcor() < WIDTH/2 or not -HEIGHT/2 < segment.ycor() < HEIGHT/2:
segment.undo()
segment.right(95)
segment.forward(SNAKE_SIZE)
screen.tracer(True) # segment.showturtle()
snake.append(segment)
screen.ontimer(slither, 100)
boundary = Turtle(shape='square', visible=False)
boundary.shapesize(HEIGHT / CURSOR_SIZE, WIDTH / CURSOR_SIZE)
boundary.fillcolor("white")
boundary.stamp()
head = Turtle("circle")
head.shapesize(SNAKE_SIZE / CURSOR_SIZE)
head.penup()
snake = [head]
screen = Screen()
slither()
screen.exitonclick()

Categories