Search code examples
pythoncollision-detectionturtle-graphics

Collision detection does not work when controls are added


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

Solution

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