Collision detection does not work when controls are added - python

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()

Related

I have problem with my game, when the ball goes over the block, it is not deleting from my screen

Someone can help me please?
I spent many hours to understand the problem.. (Without success 🤣)
I tried to built a 80s hit game.
The problem is that when the ball goes on one of the stones, I catch the event (shows me in the console) and update the list of blocks but the block is not deleted from the screen as if nothing happened and I did not update any list
this is my code:
import time
from turtle import Screen, Turtle
import random
screen = Screen()
screen.bgcolor("black")
screen.setup(width=800, height=600)
screen.tracer(0)
player = Turtle("square")
player.shapesize(1.0, 4.0, 0)
player.color("blue")
player.penup()
player.goto(0, -250)
screen.tracer(0)
blue_turtle = []
blue_positions = []
for i in range(7):
turtle = Turtle("square")
turtle.shapesize(2.0 ,4.0, 0)
turtle.color("blue")
turtle.penup()
blue_positions.append((-300 + i * 100, 200))
blue_turtle.append(turtle)
def renderBlocks(b):
for i in range(len(b) - 1):
if b[i] == None:
print("Skipped")
continue
else:
x, y= blue_positions[i]
b[i].goto(x=x, y=y)
# total += 100
ball = Turtle("circle")
ball.color("white")
game_on = True
def move():
x = ball.xcor() + 10
y = ball.ycor()+ 10
ball.goto(x=x, y=y)
while game_on:
move()
renderBlocks(blue_turtle)
for i in range(len(blue_turtle) - 1):
if (blue_turtle[i] != None) and ball.distance(blue_turtle[i]) < 20:
blue_turtle[i] = (None)
time.sleep(0.1)
screen.update()
screen.exitonclick()
I believe the problem is here:
blue_turtle[i] = (None)
You tell your code that the turtle has been eliminated but you don't tell turtle graphics that it should be removed. Instead consider:
blue_turtle[i].hideturtle()
blue_turtle[i] = None
My rework of your code addressing this issue and some others:
from turtle import Screen, Turtle
def renderBlocks(b):
for i in range(len(b) - 1):
if b[i]:
x, y = blue_positions[i]
b[i].goto(x, y)
def move():
if game_on:
x = ball.xcor() + 10
y = ball.ycor() + 10
ball.goto(x, y)
renderBlocks(blue_turtles)
for i in range(len(blue_turtles) - 1):
if blue_turtles[i] and ball.distance(blue_turtles[i]) < 20:
blue_turtles[i].hideturtle()
blue_turtles[i] = None
screen.update()
screen.ontimer(move, 100) # milliseconds
screen = Screen()
screen.setup(width=800, height=600)
screen.bgcolor('black')
screen.tracer(0)
player = Turtle('square')
player.shapesize(1, 4, 0)
player.color('blue')
player.penup()
player.sety(-250)
blue_turtles = []
blue_positions = []
for i in range(7):
turtle = Turtle('square')
turtle.shapesize(2, 4, 0)
turtle.color('blue')
turtle.penup()
blue_positions.append((-300 + i * 100, 200))
blue_turtles.append(turtle)
ball = Turtle('circle')
ball.color('white')
game_on = True
move()
screen.exitonclick()

One object gets stuck with two while loops

I'm trying to add physics to the paddle object whenever I press "w", but the ball object gets stuck until the while loop is finished in the paddle_up() function. How do I make the ball keep moving while the paddle is jumping?
The point of this game is avoiding the ball coming from the right. Whenever the user avoids the ball he or she gets one point, but whenever it collide's with the paddle, they lose one point:
import random
import turtle
# window setup
wn = turtle.Screen()
wn.title("Jump Game")
wn.bgcolor("black")
wn.setup(width=1000, height=750)
wn.tracer(0)
# Key Biding Functions
def paddle_up():
paddle_a.dy = -0.1
while paddle_a.ycor() < 0:
paddle_a.sety(paddle_a.ycor() - paddle_a.dy)
wn.update()
def paddle_down():
y = paddle_a.ycor()
y -= 10
paddle_a.sety(y)
def paddle_left():
x = paddle_a.xcor()
x -= 10
paddle_a.setx(x)
def paddle_right():
x = paddle_a.xcor()
x += 10
paddle_a.setx(x)
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(1)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=2, stretch_len=2, outline=1)
paddle_a.penup()
paddle_a.goto(-480, -350)
# Ball
ball = turtle.Turtle()
ball.shape("circle")
ball.color("white")
ball.penup()
ball.goto(-350, 0)
ball_speed = random.random()
ball_position_y = random.randint(-350, -300)
# Score System
Score = 0
Scr = turtle.Turtle()
Scr.goto(0, 360)
Scr.color("white")
Scr.penup()
Scr.hideturtle()
wn.listen()
wn.onkeypress(paddle_up, "w")
wn.onkeypress(paddle_down, "s")
wn.onkeypress(paddle_left, "a")
wn.onkeypress(paddle_right, "d")
# Main Game Loop
while True:
wn.update()
ball.setx(ball.xcor() - ball_speed * 0.3)
if ball_speed <= 0.3:
ball_speed = 0.3
if ball.xcor() < paddle_a.xcor() + 20 and ball.xcor() > paddle_a.xcor() - 20 and ball.ycor() < paddle_a.ycor() +20 and ball.ycor() > paddle_a.ycor() - 20:
Score = Score - 1
Scr.clear()
Scr.write("Score{}".format(Score), align="center", font=("Courier", 24))
ball.setx(490)
ball_position_y = random.randint(-350, -300)
ball.sety(ball_position_y)
elif ball.xcor() <= -490 and ball.ycor() != paddle_a.ycor():
Score = Score + 1
Scr.clear()
Scr.write("Score{}".format(Score), align="center", font=("Courier", 24))
ball.setx(490)
ball_position_y = random.randint(-350, -300)
ball.sety(ball_position_y)
You're using while loops where you should be using timer events. SO is full of Python turtle game answers that say, "while True: has no business in an event-driven world like turtle." How could you miss them?
I've reworked your code below to make it basically playable:
from random import randint
from turtle import Screen, Turtle
FONT = ('Courier', 24)
# Key Biding Functions
def paddle_up():
def paddle_rise():
if paddle.ycor() < 0:
paddle.sety(paddle.ycor() + paddle.dy)
screen.update()
screen.ontimer(paddle_rise, 10)
paddle_rise()
def paddle_down():
paddle.sety(paddle.ycor() - 10)
def paddle_left():
paddle.setx(paddle.xcor() - 10)
def paddle_right():
paddle.setx(paddle.xcor() + 10)
def update_score():
global ball_speed
scorer.clear()
scorer.write("Score: {}".format(score), align='center', font=FONT)
ball.setposition(490, randint(-350, -300))
ball_speed = randint(1, 3)
# Main Game Loop
def play():
global score
ball.setx(ball.xcor() - ball_speed)
if ball.distance(paddle) <= 20:
score -= 1
update_score()
elif ball.xcor() <= -490 and ball.ycor() != paddle.ycor():
score += 1
update_score()
screen.update()
screen.ontimer(play, 10)
# window setup
screen = Screen()
screen.title("Jump Game")
screen.bgcolor('black')
screen.setup(width=1000, height=800)
screen.tracer(0)
# Paddle A
paddle = Turtle()
paddle.shape('square')
paddle.color('white')
paddle.shapesize(stretch_wid=2, stretch_len=2, outline=1)
paddle.speed('slowest')
paddle.penup()
paddle.goto(-480, -350)
paddle.dy = 2
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.setposition(490, randint(-350, -300))
ball_speed = randint(1, 3)
# Score System
score = 0
scorer = Turtle()
scorer.hideturtle()
scorer.sety(360)
scorer.color('white')
scorer.penup()
scorer.write("Score: {}".format(score), align='center', font=FONT)
screen.onkeypress(paddle_up, 'w')
screen.onkeypress(paddle_down, 's')
screen.onkeypress(paddle_left, 'a')
screen.onkeypress(paddle_right, 'd')
screen.listen()
play()
screen.mainloop()

How do you stop a timer for a function?

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)

Why do my functions run a million miles an hour?

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

When press a key to move the turtle up, my other turtles freeze

When I run my code and I move my turtle up with the space bar, all the obstacles, that are supposed to be moving, stop moving. What causes the problem and how do I fix this?
I have no idea what can cause this problem and I've tried Googling but can't find anything. Since this is my first week of trying out Python, or programming in general, I have no idea what I've done wrong.
import turtle
import math
import random
#starting conditions
player = turtle.Turtle()
player.hideturtle()
player.penup()
player.shape("turtle")
player.setheading(90)
player.setpos(-200,0)
player.speed(1)
player.color("yellow")
canvas = turtle.Screen()
canvas.bgcolor("black")
canvas.title("gamescreen")
gameover = turtle.Turtle()
gameover.penup()
gameover.hideturtle()
gameover.color("red")
gameover.speed(0)
gameover.setpos(-150, 330)
scoreboard = turtle.Turtle()
scoreboard.hideturtle()
scoreboard.color("blue")
scoreboard.penup()
scoreboard.setpos(-300,320)
#borders
box = turtle.Turtle()
box.speed(0)
box.hideturtle()
box.setheading(0)
box.color("blue")
box.pensize(3)
box.penup()
box.setpos(-300,-300)
for i in range(4):
box.pendown()
box.forward(600)
box.left(90)
player.showturtle()
#movement
spd = 50
def playerup():
player.sety(player.ycor()+ spd)
if (player.ycor()+ spd) > 287:
player.speed(0)
player.sety(287)
player.speed(1)
def playerdown():
player.sety(player.ycor()- spd)
if (player.ycor()+ spd) < -287:
player.speed(0)
player.sety(-287)
player.speed(1)
turtle.listen()
gravity = 3
obsspd = 3
#collision
def hit(t1, t2):
xdistance = t1.xcor()-t2.xcor()
ydistance = t1.ycor()-t2.ycor()
if (abs(xdistance) < 20) and (abs(ydistance) < 130):
return True
else:
return False
#obstacle list
number_obstacles = 2
obstacles = []
numberslistx = list(range(-100,280))
numberslisty = list(range(143,190))
for i in range(number_obstacles):
obstacles.append(turtle.Turtle())
for obstacle in obstacles:
obstacle.hideturtle()
obstacle.speed(0)
obstacle.color("green")
obstacle.penup()
obstacle.shape("square")
obstacle.turtlesize(12,3)
xobs = random.choice(numberslistx)
yobs = random.choice(numberslisty)
obstacle.setposition(xobs,yobs)
obstacle.showturtle()
#obstacle2 list
number_obstacles2 = 2
obstacles2 = []
numberslistx = list(range(-100,280))
numberslisty = list(range(160,190))
for i in range (number_obstacles2):
obstacles2.append(turtle.Turtle())
for obstacle2 in obstacles2:
obstacle2.hideturtle()
obstacle2.speed(0)
obstacle2.color("green")
obstacle2.penup()
obstacle2.shape("square")
xobs = random.choice(numberslistx)
yobs = random.choice(numberslisty)
obstacle2.turtlesize(12,3)
obstacle2.setposition(xobs,-yobs)
obstacle2.showturtle()
if(obstacle.xcor()-obstacle2.xcor())> 10:
obstacle.setposition(xobs,yobs)
obstacle2.setposition(xobs,-yobs)
#border
def fall():
if (player.ycor()< -300):
return True
def ceiling():
if (player.ycor() > 300):
return True
colors = ["red", "green","yellow","blue","purple","pink"]
points = 1
while True:
player.sety(player.ycor()-gravity)
xresetpos = random.choice(range(230,300))
yresetpos = random.choice(range(140,190))
for obstacle in obstacles:
obstacle.setx(obstacle.xcor()-obsspd)
if (obstacle.xcor()-obsspd) < -270:
obstacle.hideturtle()
obstacle.setx(xresetpos)
obstacle.sety(yresetpos)
obstacle.showturtle()
obsspd+=1
points += 1
display = points
scoreboard.clear()
scoreboard.write(display)
player.color(random.choice(colors))
obstacle.color(random.choice(colors))
for obstacle2 in obstacles2:
obstacle2.setx(obstacle2.xcor()-(obsspd))
if (obstacle2.xcor()-obsspd) < -270:
obstacle2.hideturtle()
obstacle2.setx(xresetpos)
obstacle2.sety(-(int(yresetpos))-15)
obstacle2.showturtle()
player.color(random.choice(colors))
obstacle2.color(random.choice(colors))
if hit(player, obstacle):
player.hideturtle()
player.setpos(400,0)
gameover.color("red")
gameover.setpos(-150,-20)
gameover.write("Game over",False,"left",("Arial",50,))
gameover.setpos(-160,-200)
gameover.write("Press x to play again",False,"left",("Arial",30,))
break
if hit(player, obstacle2):
player.hideturtle()
player.setpos(400,0)
gameover.setpos(-150,-20)
gameover.write("Game over",False,"left",("Arial",50,))
gameover.setpos(-160,-200)
gameover.write("Press x to play again",False,"left",("Arial",30,))
break
if fall():
player.hideturtle()
player.setpos(400,0)
gameover.setpos(-150,-20)
gameover.write("Game over",False,"left",("Arial",50,))
gameover.setpos(-160,-200)
gameover.write("Press x to play again",False,"left",("Arial",30,))
break
if ceiling():
player.setycor(280)
#if score(player,obstacle1):
# points += 1
# display = points
# scoreboard.clear()
# scoreboard.write(display)
turtle.onkeypress(playerup, "space")
#turtle.onkeypress(playerdown, "Down")
#if player.xcor() is obstacle1.xcor():
# points += 1
# scoreboard.clear()
# scoreboard.write(points)
#balken stoppen niet als jij beweegt
One problem is that your horizontal motion is controlled, out of sync, by a while True: loop but your vertical motion is controlled, in sync, by a keyboard event. We need to get both motions in sync using events via replacing your while True: with an ontimer() event. Here's my complete rework of your code along these lines with a few simplifications for example purposes:
from turtle import Screen, Turtle
from random import choice, randrange
COLORS = ["red", "green", "yellow", "blue", "purple", "pink"]
PLAYER_SPEED = 50
GRAVITY = 3
NUMBER_OBSTACLES_UPPER = 2
NUMBER_OBSTACLES_LOWER = 2
# movement
def playerup():
screen.onkeypress(None, 'space') # disable handler inside handler
player.sety(player.ycor() + PLAYER_SPEED)
if player.ycor() > 287:
player.speed('fastest')
player.sety(287)
player.speed('slowest')
screen.onkeypress(playerup, 'space')
# collision
def hit(t1, t2):
xdistance = abs(t1.xcor() - t2.xcor())
if xdistance >= 20:
return False
ydistance = abs(t1.ycor() - t2.ycor())
return ydistance < 130
# border
def fall():
return player.ycor() < -300
def ceiling():
return player.ycor() > 300
# main program loop
def move():
global points, obstacle_speed_upper, obstacle_speed_lower
player.sety(player.ycor() - GRAVITY)
for obstacle in obstacles_upper:
obstacle.setx(obstacle.xcor() - obstacle_speed_upper)
if obstacle.xcor() < -270:
obstacle.hideturtle()
obstacle.setposition(randrange(230, 300), randrange(140, 190))
obstacle.showturtle()
obstacle_speed_upper += 1
points += 1
scoreboard.clear()
scoreboard.write(points, font=('Arial', 30,))
if hit(player, obstacle):
player.hideturtle()
gameover.write("Game Over", align='center', font=('Arial', 50,))
return
for obstacle in obstacles_lower:
obstacle.setx(obstacle.xcor() - obstacle_speed_lower)
if obstacle.xcor() < -270:
obstacle.hideturtle()
obstacle.setposition(randrange(230, 300), - randrange(160, 190))
obstacle.showturtle()
obstacle_speed_lower += 1
points += 1
scoreboard.clear()
scoreboard.write(points, font=('Arial', 30,))
if hit(player, obstacle):
player.hideturtle()
gameover.write("Game Over", align='center', font=('Arial', 50,))
return
if ceiling() or fall():
player.hideturtle()
gameover.write("Game Over", align='center', font=('Arial', 50,))
return
screen.ontimer(move, 100)
# starting conditions
screen = Screen()
screen.setup(750, 750)
screen.bgcolor('black')
screen.title("Game Screen")
# borders
box = Turtle()
box.hideturtle()
box.color('blue')
box.speed('fastest')
box.pensize(3)
box.penup()
box.setpos(-300, -300)
box.pendown()
for _ in range(4):
box.forward(600)
box.left(90)
gameover = Turtle()
gameover.hideturtle()
gameover.color('red')
gameover.penup()
gameover.sety(-25)
points = 0
scoreboard = Turtle()
scoreboard.hideturtle()
scoreboard.color('blue')
scoreboard.penup()
scoreboard.setpos(-300, 320)
scoreboard.write(points, font=('Arial', 30,))
player = Turtle()
player.hideturtle()
player.shape('turtle')
player.speed('slowest')
player.color('yellow')
player.setheading(90)
player.penup()
player.setx(-200)
player.showturtle()
# obstacle list
obstacle_speed_upper = 3
obstacles_upper = []
for _ in range(NUMBER_OBSTACLES_UPPER):
obstacle = Turtle()
obstacle.hideturtle()
obstacle.shape('square')
obstacle.turtlesize(12, 3)
obstacle.speed('fastest')
obstacle.color(choice(COLORS))
obstacle.penup()
xobs = randrange(-100, 280)
yobs = randrange(145, 190)
obstacle.setposition(xobs, yobs)
obstacle.showturtle()
obstacles_upper.append(obstacle)
# lower obstacles list
obstacle_speed_lower = 3
obstacles_lower = []
for _ in range(NUMBER_OBSTACLES_LOWER):
obstacle = Turtle()
obstacle.hideturtle()
obstacle.shape('square')
obstacle.turtlesize(12, 3)
obstacle.speed('fastest')
obstacle.color(choice(COLORS))
obstacle.penup()
xobs = randrange(-100, 280)
yobs = randrange(160, 190)
obstacle.setposition(xobs, -yobs)
obstacle.showturtle()
obstacles_lower.append(obstacle)
screen.onkeypress(playerup, 'space')
screen.listen()
move()
screen.mainloop()

Categories

Resources