The enemy1, enemy2, and enemy3 functions should run instantaniously using the ontimer function, moving the turtles inside them while running a nested checkcollision function to check if the turtles collide with the user. Along that running a nested checkbullet function to check distance see if they collide with the bullet turtle, and a nested check earth function to check their distance from the earth turtle which is the blue circle in the bottom right of the screen. However these 3 functions are running at hypersonic speed and I can't seem to find out why.
from turtle import Screen, Turtle
import random
from random import randint
#screen setup
screen = Screen()
screen.setup(width=450, height=450)
screen.bgcolor('black')
screen.tracer(3)
#user
player = Turtle()
player.shape('square')
player.color("green")
player.penup()
#First enemy
player2 = Turtle()
player2.color("green")
player2.shape('turtle')
player2.penup()
player2.setpos(random.randint(-200,200), random.randint(-200,200))
player2.setheading(random.randint(1,360))
#Second enemy
player3 = Turtle()
player3.color("green")
player3.shape('square')
player3.penup()
player3.setpos(random.randint(-200,200), random.randint(-200,200))
player3.setheading(random.randint(1,360))
#third enemy
player4 = Turtle()
player4.color("green")
player4.shape('triangle')
player4.penup()
player4.setpos(random.randint(-200,200), random.randint(-200,200))
player4.setheading(random.randint(1,360))
#earth
earth = Turtle()
earth.penup()
earth.shape("circle")
earth.color("blue")
earth.shapesize(stretch_wid = 5.6, stretch_len = 5.6)
earth.setpos(150,-150)
#bullet
bullet = Turtle()
bullet.shape("turtle")
bullet.color("purple")
bullet.hideturtle()
bullet.penup()
bullet.setpos(random.randint(-200,200),random.randint(-200,200))
bullet.hideturtle()
bullet.penup()
px = 0
py = 0
def up():
global px
global py
py = player.ycor() + 5
if py >= 200:
py -= 15
player.sety(py)
def down():
global px
global py
py = player.ycor() - 5
if py < -200:
py += 15
player.sety(py)
def left():
global px
global py
px = player.xcor() - 5
if px <= -200:
px += 15
player.setx(px)
def right():
global px
global py
px = player.xcor() + 5
if px >= 200:
px -= 15
player.setx(px)
#distance calculator
def checkcollision(t1, t2):
while t1.distance(t2) < 10:
t2.setpos(randint(-100, 100), randint(-100, 100))
# the x and y distance that the player2 turtle moves
dx = 5
dy = 5
damage = 0
def checkbullet(bullet,turtle):
while bullet.distance(turtle) < 10:
turtle.hideturtle()
def check_earth(planet,turtle):
global damage
damage+=1
while planet.distance(turtle)>10:
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
#1st enemy(switch heading)
head = 0
def enemy1():
checkcollision(player,player2)
check_earth(earth,player2)
global head
player2.fd(5)
x2, y2 = player2.position()
head = player2.heading()
if y2 <= -200 or y2 >= 200:
player2.fd(0)
player2.backward(7.5)
player2.setheading((head)* -1)
if x2 <= -200 or x2 >= 200:
player2.fd(0)
player2.backward(7.5)
if head < 90:
player2.setheading(0 - ((head) * 2))
if head>90<179:
player2.setheading((head)/2)
if head>179<260:
player2.setheading((head)/3)
if head>260<361:
player2.setheading((head)/2)
screen.ontimer(enemy1,50)
#Second enemy(dx,dy)
def enemy2():
checkcollision(player, player3)
check_earth(earth,player3)
global dx
global dy
x3, y3 = player3.position()
player3.setposition(x3 + dx, y3 + dy)
if y3 <= -200 or y3 >= 200:
dy *= -1
player3.sety(y3 + dy)
if x3 <= -200 or x3 >= 200:
dx *= -1
player3.setx(x3 + dx)
screen.ontimer(enemy2,50)
def enemy3():
checkcollision(player,player4)
check_earth(earth,player4)
player4.fd(5)
x4, y4 = player4.position()
head3 = player4.heading()
if y4 <= -200 or y4 >= 200:
player4.fd(0)
player4.backward(7.5)
player4.fd(0)
player4.setheading((head3)* -1)
if x4 <= -200 or x4 >= 200:
player4.fd(0)
player4.backward(7.5)
player4.fd(0)
if head3 < 90:
player4.setheading(0 - ((head3) * 2))
if head3>90<179:
player4.setheading((head3)/2)
if head3>179<260:
player4.setheading((head3)/3)
if head3>260<361:
player4.setheading((head3)/2)
screen.ontimer(enemy3,50)
#When bullet hits wall
def bullet_end():
screen.listen()
screen.onkeypress(up, 'Up')
screen.onkeypress(left, 'Left')
screen.onkeypress(right, 'Right')
screen.onkeypress(down, 'Down')
screen.onkeyrelease(shoot_key,"w")
def shoot_key():
bullet.setposition(px,py)
bullet.shape("circle")
bullet.showturtle()
bullet.penup()
def shoot():
checkbullet(bullet,player2)
checkbullet(bullet,player3)
checkbullet(bullet,player4)
bx = bullet.xcor()
by = bullet.ycor()
bullet.fd(5)
if bx>=200 or bx<=-200:
bullet.hideturtle()
bullet.backward(7.5)
bullet_end()
if by>=200 or by<=-200:
bullet.hideturtle()
bullet.backward(7.5)
bullet_end()
screen.ontimer(shoot,50)
shoot()
screen.listen()
screen.onkeypress(up, 'Up')
screen.onkeypress(left, 'Left')
screen.onkeypress(right, 'Right')
screen.onkeypress(down, 'Down')
screen.onkeyrelease(shoot_key,"w")
enemy1()
enemy2()
enemy3()
screen.mainloop()
The problem is caused by the function check_earth. As far as I can see, you are trying to prevent the enemy from being too close to earth - if it gets there, it should receive a new, random position. Obviously, this new position also shouldn't be too near to earth, so you are doing it in a loop. However, there are three errors in the loop.
Firstly, the condition for looking for a new position: while planet.distance(turtle)>10: is always met for a valid place.
Secondly, you immediately move the enemy to new random position, without checking the condition, which creates a lot of traffic. Instead, you should set position only when you are sure that it's correct.
Lastly, where did the '10' value come from? To declare your circle's size, you used: earth.shapesize(stretch_wid = 5.6, stretch_len = 5.6). There is a following dependency between earth radius and stretch length: 2*RADIUS/CURSOR_SIZE. As default value of CURSOR_SIZE is 20, it would mean that the radius of your circle is 56. If we want to detect the collision as soon as any part of enemy's turtle touches the earth, we should also add the length of the enemy's cursor.
So, instead of:
def check_earth(planet,turtle):
global damage
damage+=1
while planet.distance(turtle)>10:
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
You should define function check_earth as:
CURSOR_SIZE = 20
EARTH_RADIUS = 56
def check_earth(planet,turtle):
global damage
damage+=1
(turtle_x, turtle_y) = turtle.pos()
while True:
if planet.distance(turtle_x, turtle_y) > EARTH_RADIUS + CURSOR_SIZE:
turtle.setpos(turtle_x,turtle_y)
break
turtle_x = random.randint(-200,200)
turtle_y = random.randint(-200,200)
Not: while planet.distance(turtle)>10:
Yes: while planet.distance(turtle)<10:
The solution was simple and we both overlooked it,
I ask dumb questions sometimes. Anyways thanks for helping
Related
from turtle import Screen, Turtle
import random
from random import randint
#screen setup
screen = Screen()
screen.setup(width=450, height=450)
screen.bgcolor('black')
screen.tracer(3)
#user
player = Turtle()
player.shape('square')
player.color("green")
player.penup()
#First enemy
player2 = Turtle()
player2.color("green")
player2.shape('turtle')
player2.penup()
player2.setpos(random.randint(-200,200), random.randint(-200,200))
player2.setheading(random.randint(1,360))
#Second enemy
player3 = Turtle()
player3.color("green")
player3.shape('square')
player3.penup()
player3.setpos(random.randint(-200,200), random.randint(-200,200))
player3.setheading(random.randint(1,360))
#third enemy
player4 = Turtle()
player4.color("green")
player4.shape('triangle')
player4.penup()
player4.setpos(random.randint(-200,200), random.randint(-200,200))
player4.setheading(random.randint(1,360))
score_board = Turtle()
score_board.pu()
score_board.color("yellow")
score_board.hideturtle()
score_board.goto(0,160)
end_turtle = Turtle()
end_turtle.color("pink")
end_turtle.pu()
end_turtle.hideturtle()
end_turtle.goto(0,200)
score_num= Turtle()
score_num.pu()
score_num.color("yellow")
score_num.pu()
score_num.hideturtle()
score_num.goto(0,150)
#earth
earth = Turtle()
earth.penup()
earth.shape("circle")
earth.color("blue")
earth.shapesize(stretch_wid = 5.6, stretch_len = 5.6)
earth.setpos(150,-150)
#bullet
bullet = Turtle()
bullet.shape("turtle")
bullet.color("purple")
bullet.hideturtle()
bullet.penup()
bullet.setpos(random.randint(-200,200),random.randint(-200,200))
bullet.hideturtle()
bullet.penup()
px = 0
py = 0
def up():
global px
global py
py = player.ycor() + 5
if py >= 200:
py -= 15
player.sety(py)
def down():
global px
global py
py = player.ycor() - 5
if py < -200:
py += 15
player.sety(py)
def left():
global px
global py
px = player.xcor() - 5
if px <= -200:
px += 15
player.setx(px)
def right():
global px
global py
px = player.xcor() + 5
if px >= 200:
px -= 15
player.setx(px)
#distance calculator
def checkcollision(t1, t2):
while t1.distance(t2) < 10:
t2.setpos(randint(-100, 100), randint(-100, 100))
# the x and y distance that the player2 turtle moves
dx = 5
dy = 5
earth_health = 100
def checkbullet(bullet,turtle):
while bullet.distance(turtle) < 10:
turtle.hideturtle()
count = 0
def check_earth(planet,turtle):
global earth_health
global count
if planet.distance(turtle)<40:
if count>1:
score_num.clear()
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
earth_health+=-10
score_board.write("Earth health")
score_num.write(earth_health)
count+=1
if earth_health<90:
end_turtle.write("You lost and humanity lost")
## if planet.distance(turtle_x, turtle_y) > EARTH_RADIUS + CURSOR_SIZE:
## turtle.setpos(turtle_x,turtle_y)
## break
##
## turtle_x = random.randint(-200,200)
## turtle_y = random.randint(-200,200)
## global damage
## while planet.distance(turtle)>10:
## turtle.setpos(random.randint(-200,200),random.randint(-200,200))
#1st enemy(switch heading)
head = 0
def enemy1():
global earth_health
if earth_health<90:
screen.ontimer(enemy1,0)
checkcollision(player,player2)
check_earth(earth,player2)
global head
player2.fd(5)
x2, y2 = player2.position()
head = player2.heading()
if y2 <= -200 or y2 >= 200:
player2.fd(0)
player2.backward(7.5)
player2.setheading((head)* -1)
if x2 <= -200 or x2 >= 200:
player2.fd(0)
player2.backward(7.5)
if head < 90:
player2.setheading(0 - ((head) * 2))
if head>90<179:
player2.setheading((head)/2)
if head>179<260:
player2.setheading((head)/3)
if head>260<361:
player2.setheading((head)/2)
screen.ontimer(enemy1,50)
#Second enemy(dx,dy)
def enemy2():
checkcollision(player, player3)
check_earth(earth,player3)
global dx
global dy
x3, y3 = player3.position()
player3.setposition(x3 + dx, y3 + dy)
if y3 <= -200 or y3 >= 200:
dy *= -1
player3.sety(y3 + dy)
if x3 <= -200 or x3 >= 200:
dx *= -1
player3.setx(x3 + dx)
screen.ontimer(enemy2,50)
def enemy3():
checkcollision(player,player4)
check_earth(earth,player4)
player4.fd(5)
x4, y4 = player4.position()
head3 = player4.heading()
if y4 <= -200 or y4 >= 200:
player4.fd(0)
player4.backward(7.5)
player4.fd(0)
player4.setheading((head3)* -1)
if x4 <= -200 or x4 >= 200:
player4.fd(0)
player4.backward(7.5)
player4.fd(0)
if head3 < 90:
player4.setheading(0 - ((head3) * 2))
if head3>90<179:
player4.setheading((head3)/2)
if head3>179<260:
player4.setheading((head3)/3)
if head3>260<361:
player4.setheading((head3)/2)
screen.ontimer(enemy3,50)
#When bullet hits wall
def bullet_end():
screen.listen()
screen.onkeypress(up, 'Up')
screen.onkeypress(left, 'Left')
screen.onkeypress(right, 'Right')
screen.onkeypress(down, 'Down')
screen.onkeyrelease(shoot_key,"w")
def shoot_key():
bullet.setposition(px,py)
bullet.shape("circle")
bullet.showturtle()
bullet.penup()
def shoot():
checkbullet(bullet,player2)
checkbullet(bullet,player3)
checkbullet(bullet,player4)
bx = bullet.xcor()
by = bullet.ycor()
bullet.fd(5)
if bx>=200 or bx<=-200:
bullet.hideturtle()
bullet.backward(7.5)
bullet_end()
if by>=200 or by<=-200:
bullet.hideturtle()
bullet.backward(7.5)
bullet_end()
screen.ontimer(shoot,50)
shoot()
screen.listen()
screen.onkeypress(up, 'Up')
screen.onkeypress(left, 'Left')
screen.onkeypress(right, 'Right')
screen.onkeypress(down, 'Down')
screen.onkeyrelease(shoot_key,"w")
enemy1()
enemy2()
enemy3()
screen.mainloop()
The problem lies here:
def check_earth(planet,turtle):
global earth_health
global count
if planet.distance(turtle)<40:
if count>1:
score_num.clear()
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
earth_health+=-10
score_board.write("Earth health")
score_num.write(earth_health)
count+=1
if earth_health<90:
end_turtle.write("You lost and humanity lost")
if planet.distance(turtle_x, turtle_y) > EARTH_RADIUS + CURSOR_SIZE:
turtle.setpos(turtle_x,turtle_y)
break
turtle_x = random.randint(-200,200)
turtle_y = random.randint(-200,200)
global damage
while planet.distance(turtle)>10:
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
#1st enemy(switch heading)
head = 0
def enemy1():
global earth_health
if earth_health<90:
screen.ontimer(enemy1,0)
At first the enemy1 function runs on a timer of 50 milliseconds but when When the earth_health variable is less than than 90 this conditional should make the enemy1 function stop running as i set it its timer to 0. Instead the entire program crashes which in a sense is ok relating to my goals with this program but how could I make the enemy1 function stop running its loop on the conditional rather than the entire program?
You can use a conditional statement to see if it should stop running -- if it is you can use "return" with no value. That will breakout of the function.
In the beginning set some value (global)
global enemy1stop
enemy1stop = False
In the check_earth function:
def check_earth(planet,turtle):
global earth_health
global count
if planet.distance(turtle)<40:
if count>1:
score_num.clear()
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
earth_health+=-10
score_board.write("Earth health")
score_num.write(earth_health)
count+=1
if earth_health<90:
end_turtle.write("You lost and humanity lost")
if planet.distance(turtle_x, turtle_y) > EARTH_RADIUS + CURSOR_SIZE:
turtle.setpos(turtle_x,turtle_y)
break
turtle_x = random.randint(-200,200)
turtle_y = random.randint(-200,200)
global damage
while planet.distance(turtle)>10:
turtle.setpos(random.randint(-200,200),random.randint(-200,200))
#1st enemy(switch heading)
head = 0
def enemy1():
global earth_health
if earth_health<90:
enemy1stop=True # <--
And in the enemy1 function:
def enemy1():
global earth_health
if earth_health<90:
screen.ontimer(enemy1,0)
...
if enemy1stop == True:
return # this will stop the function from repeating
screen.ontimer(enemy1,50)
I'm making a basic game. I want the ball to bounce back up ONLY when it hits the platform. So far, I've written code that will make the ball bounce off the top and bottom screen, but I'm having trouble with getting the ball to bounce off the platform.
from tkinter import *
import time
import tkinter
tk = Tk()
canvas = Canvas(tk, bg="white",width=(900),height=(500))
canvas.pack()
platform = canvas.create_rectangle(400,400,500,410)
def ball():
xspeed = 2
yspeed = 2
ball = canvas.create_oval(430,10,470,50)
while True:
canvas.move(ball, xspeed, yspeed)
pos = canvas.coords(ball)
if pos[2] >=900 or pos[0] <0:
xspeed = -xspeed
tk.update()
time.sleep(0.01)
def board():
board_right()
board_left()
def board_right(event):
xspeed = 5
yspeed = 0
canvas.move(platform,xspeed,yspeed)
tk.update
time.sleep(0.01)
def board_left(event):
xspeed = 5
yspeed = 0
canvas.move(platform,-xspeed,yspeed)
tk.update()
time.sleep(0.01)
canvas.bind_all("<Right>",board_right)
canvas.bind_all("<Left>",board_left)
ball()
tk.mainloop()
Do not use time.sleep() as it will block the tkinter mainloop, use after() instead.
To check whether the ball hits the platform, you need to get the center x of the ball and the lower y of the ball. If center x is within the left and right of platform and the ball lower y is the platform upper y, then reverse the ball y speed. Otherwise game over!
Below is sample code based on yours:
import tkinter as tk
root = tk.Tk()
width = 900
height = 500
canvas = tk.Canvas(root, bg='white', width=width, height=height)
canvas.pack()
ball = canvas.create_oval(430, 10, 470, 50, fill='green')
platform_y = height - 20
platform = canvas.create_rectangle(width//2-50, platform_y, width//2+50, platform_y+10, fill='black')
# ball moving speed
xspeed = yspeed = 2
def move_ball():
global xspeed, yspeed
x1, y1, x2, y2 = canvas.coords(ball)
if x1 <= 0 or x2 >= width:
# hit wall, reverse x speed
xspeed = -xspeed
if y1 <= 0:
# hit top wall
yspeed = 2
elif y2 >= platform_y:
# calculate center x of the ball
cx = (x1 + x2) // 2
# check whether platform is hit
px1, _, px2, _ = canvas.coords(platform)
if px1 <= cx <= px2:
yspeed = -2
else:
canvas.create_text(width//2, height//2, text='Game Over', font=('Arial Bold', 32), fill='red')
return
canvas.move(ball, xspeed, yspeed)
canvas.after(20, move_ball)
def board_right(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond right wall
if x2 < width:
dx = min(width-x2, 10)
canvas.move(platform, dx, 0)
def board_left(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond left wall
if x1 > 0:
dx = min(x1, 10)
canvas.move(platform, -dx, 0)
canvas.bind_all('<Right>', board_right)
canvas.bind_all('<Left>', board_left)
move_ball()
root.mainloop()
I have a code that kind of detects collision, it works if I set the x and y away from the object which it detects collision from (I need to set it straight away from the code before I run the script)
If I add controls into it, and move it around while its running, it doesn't detect the collision.
Here is the code:
import time
import random
import sys
import turtle
wn = turtle.Screen()
wn.title('collision')
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(0)
p_s = 20
e_s = 20
px = 0
py = 0
ex = 0
ey = 0
pec = 0
def collision():
global pec
pupc = px + p_s / 2
pdownc = px - p_s / 2
pupcy = py + p_s / 2
pdowncy = py - p_s / 2
if ex == px or ex > px and ex < pupc or ex == px or ex < px and ex > pdownc:
if ey == py or ey > py and ey < pupcy or ey == py or ey < py and ey > pdowncy:
pec = 1
else:
pec = 0
else:
pec = 0
if pec == 1:
print ('collision')
elif pec == 0:
print ('nope')
#enemy
e = turtle.Turtle()
e.goto(ex, ey)
e.speed(0)
e.color('red')
e.penup()
#player
p = turtle.Turtle()
p.goto(px, py)
p.speed(0)
p.shape('square')
p.color('blue')
p.penup()
print('move')
def p_up():
py = p.ycor()
py += 20
p.sety(py)
print(py)
wn.update()
collision()
def p_down():
py = p.ycor()
py -= 20
p.sety(py)
print(py)
wn.update()
collision()
def p_right():
px = p.xcor()
px += 20
p.setx(px)
print(px)
wn.update()
collision()
def p_left():
px = p.xcor()
px -= 20
p.setx(px)
print(px)
wn.update()
collision()
#keyboard binding
wn.listen()
wn.onkeypress(p_up, "Up")
wn.onkeypress(p_down, "Down")
wn.onkeypress(p_right, "Right")
wn.onkeypress(p_left, "Left")
#main part
while True:
wn.update()
I believe you're making this problem more difficult than necessary. First, turtle provides basic collision detection with the .distance() method. Second, the only globals necessary are constants as we can always interrogate the turtle about it's current position (and heading, etc.):
from turtle import Screen, Turtle
from random import randrange
CURSOR_SIZE = 20
WIDTH, HEIGHT = 800, 600
def player_up():
player.sety(player.ycor() + 20)
check_collision()
def player_down():
player.sety(player.ycor() - 20)
check_collision()
def player_right():
player.setx(player.xcor() + 20)
check_collision()
def player_left():
player.setx(player.xcor() - 20)
check_collision()
def enemy_relocate():
enemy.hideturtle()
x = randrange(CURSOR_SIZE - WIDTH/2, WIDTH/2 - CURSOR_SIZE)
y = randrange(CURSOR_SIZE - HEIGHT/2, HEIGHT/2 - CURSOR_SIZE)
enemy.goto(x, y)
enemy.showturtle()
def check_collision():
if player.distance(enemy) < CURSOR_SIZE:
print("Collision!")
enemy_relocate()
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.title("Collision!")
screen.bgcolor('black')
# enemy
enemy = Turtle()
enemy.shape('circle')
enemy.color('red')
enemy.speed('fastest')
enemy.penup()
enemy_relocate()
# player
player = Turtle()
player.shape('square')
player.color('blue')
player.speed('fastest')
player.penup()
# keyboard binding
screen.onkeypress(player_up, 'Up')
screen.onkeypress(player_down, 'Down')
screen.onkeypress(player_right, 'Right')
screen.onkeypress(player_left, 'Left')
screen.listen()
# main part
screen.mainloop()
I am trying to create a game where a turtle is confined in a box. A ball bounces around the box, and if it collides with the turtle, or if the turtle touches the perimeter of the box, the game is over. A red dot spawns in a random location in the box, and when the turtle runs over that dot, the dot is supposed to disappear and respawn somewhere else. However, this only works sometimes. Sometimes the dot will randomly disappear and spawn somewhere else even though the turtle isn't even close to it. How can I fix this?
from turtle import Screen, Turtle, mainloop
wn = Screen()
wn.bgcolor("light blue")
#CONTROLLABLE TURTLE
t = Turtle()
t.color('black')
t.pensize(10)
t.shape("turtle")
t.speed("fastest")
t.penup()
t.goto(-130,-200)
t.pendown()
global hit
global score
hit = False
score = 0
#MAKE SQUARE
for i in range(4):
t.forward(400)
t.left(90)
t.penup()
t.goto(50,0)
speed = 2
t.color("black")
#BALL
ball1 = turtle.Turtle()
ball1.color("blue")
ball1.speed(0)
ball1.penup()
ball1.shape("circle")
A = random.randint(30,60)
B = random.randint(120,150)
C = random.randint(210,240)
D = random.randint(300,330)
Directions = [A, B, C, D]
direct = random.choice(Directions)
def tDirection(direct):
ball1.right(direct)
tDirection(direct)
angle = 90
#DOT TURTLE
dot = turtle.Turtle()
dot.color("black")
dot.speed(0)
dot.hideturtle()
def createDot():
dotx = random.randint(-10,230)
doty = random.randint(-160,200)
dot.penup()
dot.goto(dotx,doty)
dot.pendown()
dot.pensize(3)
dot.fillcolor("Red")
dot.begin_fill()
dot.circle(7)
dot.end_fill()
createDot()
#make score function
while True:
if hit == False:
#moving ball
ty = ball1.ycor()
tx = ball1.xcor()
if ty < -183:
angleCurr = ball1.heading()
if(270>angleCurr>180):
ball1.right(angle)
else:
ball1.left(angle)
ball1.forward(2)
elif ty > 185:
angleCurr = ball1.heading()
if(0<angleCurr<90):
ball1.right(angle)
else:
ball1.left(angle)
ball1.forward(2)
elif tx < -115:
angleCurr = ball1.heading()
if(180<angleCurr<270):
ball1.left(angle)
else:
ball1.right(angle)
ball1.forward(2)
elif tx > 251:
angleCurr = ball1.heading()
if(0<angleCurr<90):
ball1.left(angle)
else:
ball1.right(angle)
ball1.forward(9)
wn.onkey(lambda: t.setheading(180), 'Left')
wn.onkey(lambda: t.setheading(0), 'Right')
wn.onkey(lambda: t.setheading(90), 'Up')
wn.onkey(lambda: t.setheading(270), 'Down')
w = turtle.Turtle()
w.hideturtle()
w.penup()
w.speed("fastest")
def end():
w.goto(-95,-20)
w.pendown()
w.write("GAME OVER", font=("Arial", 40, "normal"))
t.hideturtle()
ball1.hideturtle()
dot.hideturtle()
dot.clear()
speed = 2
def turtleMove():
t.forward(speed)
wn.ontimer(turtleMove, 10)
dodx = dot.xcor()
dody = dot.ycor()
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
hit = True
dot.clear()
elif abs(t.xcor() - tx) < 5 and abs(t.ycor() - ty) < 5:
end()
if t.xcor() > 253 or t.xcor() < -115 or t.ycor() > 185 or t.ycor() < -183:
end()
turtleMove()
wn.mainloop()
wn.listen()
if hit == True:
createDot()
score+=1
print(score)
hit = False
I think it might just be a typo:
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
Your collision detection is doing a comparison with the y coordinates instead of subtracting like you did with the x coordinates.
So this should fix it:
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() - dody) < 5:
I would avoid code like this:
dodx = dot.xcor()
dody = dot.ycor()
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
hit = True
dot.clear()
elif abs(t.xcor() - tx) < 5 and abs(t.ycor() - ty) < 5:
end()
And instead use turtle's distance() method:
if t.distance(dot) < 5:
hit = True
dot.clear()
elif t.distance(ball1) < 5:
end()
However, this only works sometimes. Sometimes the dot will randomly
disappear and spawn somewhere else even though the turtle isn't even
close to it.
Are you pretending that this code runs? It doesn't even start up due to two different import issues. Fixing those, the turtle controls don't work at all. And the ball doesn't bounce around the box!
This appears to be a random collection of bits of code borrowed from other programs patched together with wishful thinking. It simply doesn't work.
Below I've taken apart your code and put it back together again such that it basically runs. The blue ball does bounce around the box; you can move the turtle with the arrow keys; the red dot does disappear and reappear elsewhere when the turtle touches it:
from turtle import Screen, Turtle
from random import randint, choice
CURSOR_SIZE = 20
def tDirection(direct):
ball.right(direct)
def turtleMove():
turtle.forward(speed)
screen.ontimer(turtleMove, 10)
def createDot():
x, y = randint(CURSOR_SIZE - 200, 200 - CURSOR_SIZE), randint(CURSOR_SIZE - 200, 200 - CURSOR_SIZE)
dot.goto(x, y)
def end():
marker.write("GAME OVER", align='center', font=("Arial", 40, "normal"))
turtle.hideturtle()
ball.hideturtle()
dot.hideturtle()
screen = Screen()
screen.bgcolor("light blue")
score = 0
speed = 2
# CONTROLLABLE TURTLE
turtle = Turtle("turtle")
turtle.color('black')
turtle.pensize(10)
turtle.speed("fastest")
turtle.penup()
turtle.goto(-200, -200)
turtle.pendown()
# MAKE SQUARE
for i in range(4):
turtle.forward(400)
turtle.left(90)
turtle.penup()
turtle.goto(50, 0)
# BALL
ball = Turtle("circle")
ball.color("blue")
ball.speed('fastest')
ball.penup()
A = randint(30, 60)
B = randint(120, 150)
C = randint(210, 240)
D = randint(300, 330)
directions = [A, B, C, D]
direct = choice(directions)
tDirection(direct)
angle = 90
# DOT TURTLE
dot = Turtle('circle')
dot.color("red")
dot.speed('fastest')
dot.pensize(3)
dot.penup()
createDot()
marker = Turtle(visible=False)
marker.penup()
marker.sety(-20)
screen.onkey(lambda: turtle.setheading(0), 'Right')
screen.onkey(lambda: turtle.setheading(90), 'Up')
screen.onkey(lambda: turtle.setheading(180), 'Left')
screen.onkey(lambda: turtle.setheading(270), 'Down')
screen.listen()
turtleMove()
while True:
# moving ball
tx, ty = ball.position()
if ty < CURSOR_SIZE - 200:
angleCurr = ball.heading()
if 270 > angleCurr > 180:
ball.right(angle)
else:
ball.left(angle)
ball.forward(2)
elif ty > 200 - CURSOR_SIZE:
angleCurr = ball.heading()
if 0 < angleCurr < 90:
ball.right(angle)
else:
ball.left(angle)
ball.forward(2)
elif tx < CURSOR_SIZE - 200:
angleCurr = ball.heading()
if 180 < angleCurr < 270:
ball.left(angle)
else:
ball.right(angle)
ball.forward(2)
elif tx > 200 - CURSOR_SIZE:
angleCurr = ball.heading()
if 0 < angleCurr < 90:
ball.left(angle)
else:
ball.right(angle)
ball.forward(2)
ball.forward(9)
if turtle.distance(dot) < CURSOR_SIZE/2:
score += 1
dot.hideturtle()
createDot()
dot.showturtle()
elif turtle.distance(ball) < CURSOR_SIZE/2:
end()
if not CURSOR_SIZE - 200 < turtle.xcor() < 200 - CURSOR_SIZE or not CURSOR_SIZE - 200 < turtle.ycor() < 200 - CURSOR_SIZE:
end()
screen.mainloop()
When asking for help on SO, please be honest about the state of your code.
The above code isn't complete, there is still work to do. E.g. the while True: loop should be converted to a function and ontimer() event; the score needs to be displayed; the game should be made restartable.
I was working on fixing up some code to make it look better and when I finished copying the code over and finishing fixing it, I ran it and nothing happened. Two things loaded then everything clears. I can't find the problem.
Original code works
import turtle
from random import randint
import time
"""-------------"""
t=turtle.Turtle()
s=turtle.Screen()
cube=turtle.Turtle()
title=turtle.Turtle()
"""--------------"""
WIDTH, HEIGHT=300, 300
LENGTH=(5)
"""--------------"""
x1 = randint(cube.xcor()/2 - WIDTH/2, WIDTH/2 - cube.xcor()/2)
y1 = randint(cube.ycor()/2 - HEIGHT/2, HEIGHT/2 - cube.ycor()/2)
"""------------"""
s.setup(WIDTH,HEIGHT)
"""------------"""
t.width(1)
s.bgcolor("dark green")
"""-----------------"""
#Title
title.color("Red")
title.hideturtle()
title.penup()
title.goto(0,130)
title.pendown()
title.write("SNAK3",align="center", font=("Lobster", 20, "Bold"))
"""-------------"""
class Food():
def block():
cube.hideturtle()
cube.color("red")
cube.penup()
cube.goto(x1,y1)
cube.speed(0)
cube.begin_fill()
for i in range(4):
cube.pendown()
cube.forward(10)
cube.right(90)
cube.end_fill()
"""---------------"""
t.shape("square")
class Player():
def move_up():
player=False
while player==False:
for i in range(10):
t.forward(LENGTH)
t.delay(25)
t.clear()
x, y = t.position()
if not -WIDTH / 2 < x < WIDTH / 2 or not -HEIGHT / 2 < y < HEIGHT / 2:
player=True
t.hideturtle()
cube.clear()
title.clear()
title.penup()
title.goto(0,0)
title.pendown()
title.write("GAMEOVER", align="center", font=("lobster", 18, "bold"))
def move_left():
t.speed(0)
t.left(90)
t.speed(3)
def move_right():
t.speed(0)
t.right(90)
t.speed(3)
"""------------"""
food=Food.block()
player1=Player()
"""----------------"""
s.onkey(Player.move_up,"up")
s.onkey(Player.move_left,"left")
s.onkey(Player.move_right,"right")
s.listen()
"""--------------"""
collision=Collision_check.check()
"""--------------------"""
t1=t.xcor(),t.ycor()
cube1=cube.xcor(),cube.ycor()
class Collision_check():
def check():
crash=True
if t1.xcor()>=cube.xcor() and t1.xcor()<=cube.xcor()+10 and t1.ycor>=cube.ycor() and t1.ycor()<=cube.ycor+10:
cube.clear()
cube.goto(x1,y1)
LENGTH=+1
elif t1!=cube1:
crash=False
return crash
Fixed code with slight changes
import turtle
from random import randint
t=turtle.Turtle()
s=turtle.Screen()
cube=turtle.Turtle()
title=turtle.Turtle()
t.width(1)
s.bgcolor("dark green")
#Title
title.color("red")
title.hideturtle()
title.penup()
title.goto(0,130)
title.write("SNAK3",align="center",font=("lobster",20,"Bold"))
WIDTH, HEIGHT=300, 300
LENGTH=[5]
s.setup(WIDTH,HEIGHT)
#Random cords
x1=randint(cube.xcor()/2-WIDTH/2, WIDTH/2-cube.xcor()/2)
y1=randint(cube.ycor()/2-HEIGHT/2, HEIGHT/2-cube.ycor()/2)
class Food():
def block():
cube.hideturtle()
cube.color("red")
cube.penup()
cube.goto(x1,y1)
cube.speed(0)
cube.begin_fill()
cube.pendown()
for i in range(4):
cube.forward(10)
cube.right(90)
cube.end_fill()
t.shape("square")
class Player():
def forward():
player=False
while player==False:
for i in range(10):
t.forward(LENGTH)
t.delay(25)
t.clear
x, y=t.position()
if not -WIDTH / 2 < x < WIDTH / 2 or not -HEIGHT / 2 < y < HEIGHT/2:
player=True
cube.clear()
t.hideturtle()
title.clear()
title.penup()
title.goto(0,0)
title.pendown()
title.write("GAMEOVER", align="center", font=("lobster",18,"bold"))
def left():
t.speed(0)
t.left(90)
t.speed(3)
def right():
t.speed(0)
t.right(90)
t.speed(3)
food=Food.block()
player1=Player()
s.onkey(player1.forward,("up"))
s.onkey(player1.left,("left"))
s.onkey(player1.left,("right"))
class Collision_check():
def check():
crash=True
if t.xcor()>=cube.xcor() and t.xcor()<=cube.xcor()+10 and t.ycor()>=cube.ycor() and t.ycor()<=cube.ycor()+10:
cube.clear()
cube.goto(x1,y1)
LENGTH+=1
if cube.xcor()>=t.xcor() and cube.xcor()<=t.xcor()+10 and cube.ycor()>=t.ycor() and cube.ycor()<=t.ycor()+10:
cube.clear()
cube.goto(x1,y1)
LENGTH+=1
else:
crash=False
return crash
collision=Collision_check.check()
Everything in the code above is nearly exactly the same as the original. Ive gone over the code several times and can not find the problem.
I've ruled out that the collision_check is not the problem, all the classes are in order and aligned. The only other thing I could think of is that i have spelled something wrong.
Let's first address some basic facts:
Neither version of this code works
The slight changes to make it look better don't make it look better
and aren't slight, there are significant differences
Neither version of the code uses Python classes correctly
repl.it provides its own implementation of turtle which is generally
a subset of the original
A program is like a story, you first explain the background of events and then you proceed to tell the story in an order that makes logical sense.
Here's my rework of your code to try to tell a better story, but it still doesn't work completely as there are parts of the story missing:
from turtle import Turtle, Screen
from random import randint
WIDTH, HEIGHT = 300, 300
class Food():
def block():
cube.penup()
cube.goto(x1, y1)
cube.pendown()
cube.begin_fill()
for _ in range(4):
cube.forward(10)
cube.right(90)
cube.end_fill()
class Player():
def forward():
for _ in range(10):
t.forward(LENGTH)
# t.delay(25) # no such turtle method, perhaps repl.it addition
t.clear()
x, y = t.position()
if not -WIDTH / 2 < x < WIDTH / 2 or not -HEIGHT / 2 < y < HEIGHT/2:
cube.clear()
t.hideturtle()
title.clear()
title.penup()
title.goto(0, 0)
title.pendown()
title.write("GAMEOVER", align='center', font=('lobster', 18, 'bold'))
def left():
t.speed(0)
t.left(90)
t.speed(3)
def right():
t.speed(0)
t.right(90)
t.speed(3)
class Collision_check():
def check():
global LENGTH
crash = True
if t.xcor() >= cube.xcor() and t.xcor() <= cube.xcor() + 10 and t.ycor() >= cube.ycor() and t.ycor() <= cube.ycor() + 10:
cube.clear()
cube.goto(x1, y1)
LENGTH += 1
if cube.xcor() >= t.xcor() and cube.xcor() <= t.xcor()+10 and cube.ycor() >= t.ycor() and cube.ycor() <= t.ycor()+10:
cube.clear()
cube.goto(x1, y1)
LENGTH += 1
else:
crash = False
return crash
s = Screen()
s.setup(WIDTH, HEIGHT)
s.bgcolor('dark green')
t = Turtle()
t.shape('square')
t.width(1)
cube = Turtle()
cube.hideturtle()
cube.color('red')
cube.speed('fastest')
# Title
title = Turtle()
title.hideturtle()
title.color('red')
title.penup()
title.goto(0, 130)
title.write("SNAK3", align='center', font=('lobster', 20, 'bold'))
LENGTH = 5
# Random cords
x1 = randint(cube.xcor()/2 - WIDTH/2, WIDTH/2 - cube.xcor()/2)
y1 = randint(cube.ycor()/2 - HEIGHT/2, HEIGHT/2 - cube.ycor()/2)
food = Food.block()
player1 = Player()
s.onkey(Player.forward, 'Up')
s.onkey(Player.left, 'Left')
s.onkey(Player.right, 'Right')
s.listen()
# this makes no sense here, needs to happen on a regular basis after moves
collision = Collision_check.check()
s.mainloop()