Search code examples
pythonpython-3.xcollision-detectionturtle-graphicspython-turtle

Python Turtle Touching Walls Of Maze


I need to make the Turtle in Python print "collision" when the turtle touches the walls of my maze. Here is my code:


maze=turtle.Turtle()
maze.speed(10)
maze.penup()
maze.goto(-12.5, -175)
maze.pendown()
maze.begin_fill()
maze.goto(-12.5, -100)
maze.goto(37.5, -100)
maze.goto(37.5, -75)
maze.goto(-112.5, -75)
maze.goto(-112.5, -37.5)
maze.goto(-125, -37.5)
maze.goto(-125, -87.5)
maze.goto(-87.5, -87.5)
maze.goto(-87.5, -137.5)
maze.goto(-75, -137.5)
maze.goto(-75, -100)
maze.goto(-50, -100)
maze.goto(-50, -162.5)
maze.goto(-150, -162.5)
maze.goto(-150, -137.5)
maze.goto(-112.5, -137.5)
maze.goto(-112.5, -112.5)
maze.goto(-162.5, -112.5)
maze.goto(-162.5, -87.5)
maze.goto(-150, -87.5)
maze.goto(-150, -37.5)
maze.goto(-162.5, -37.5)
maze.goto(-162.5, 12.5)
maze.goto(-137.5, 12.5)
maze.goto(-137.5, -12.5)
maze.goto(-112.5, -12.5)
maze.goto(-112.5, 12.5)
maze.goto(-87.5, 12.5)
maze.goto(-87.5, -50)
maze.goto(-62.5, -50)
maze.goto(-62.5, 25)
maze.goto(-162.5, 25)
maze.goto(-162.5, 137.5)
maze.goto(-112.5, 137.5)
maze.goto(-112.5, 162.5)
maze.goto(-87.5, 162.5)
maze.goto(-87.5, 137.5)
maze.goto(-25, 137.5)
maze.goto(-25, 87.5)
maze.goto(12.5, 87.5)
maze.goto(12.5, 112.5)
maze.goto(37.5, 112.5)
maze.goto(37.5, 87.5)
maze.goto(62.5, 87.5)
maze.goto(62.5, 125)
maze.goto(-12.5, 125)
maze.goto(-12.5, 175)
maze.goto(-175, 175)
maze.goto(-175, -175)
maze.goto(-12.5, -175)
maze.end_fill()
maze.penup()
maze.goto(12.5, -175)
maze.pendown()
maze.begin_fill()
maze.goto(12.5, -125)
maze.goto(87.5, -125)
maze.goto(87.5, -162.5)
maze.goto(150, -162.5)
maze.goto(150, -125)
maze.goto(162.5, -125)
maze.goto(162.5, -100)
maze.goto(125, -100)
maze.goto(125, -137.5)
maze.goto(112.5, -137.5)
maze.goto(112.5, -100)
maze.goto(62.5, -100)
maze.goto(62.5, -75)
maze.goto(150, -75)
maze.goto(150, -12.5)
maze.goto(162.5, -12.5)
maze.goto(162.5, 12.5)
maze.goto(125, 12.5)
maze.goto(125, 37.5)
maze.goto(150, 37.5)
maze.goto(150, 150)
maze.goto(125, 150)
maze.goto(125, 112.5)
maze.goto(100, 112.5)
maze.goto(100, 87.5)
maze.goto(125, 87.5)
maze.goto(125, 62.5)
maze.goto(100, 62.5)
maze.goto(100, 12.5)
maze.goto(37.5, 12.5)
maze.goto(37.5, -50)
maze.goto(-37.5, -50)
maze.goto(-37.5, -25)
maze.goto(25, -25)
maze.goto(25, 25)
maze.goto(0, 25)
maze.goto(0, 0)
maze.goto(-37.5, 0)
maze.goto(-37.5, 50)
maze.goto(-87.5, 50)
maze.goto(-87.5, 75)
maze.goto(-62.5, 75)
maze.goto(-62.5, 100)
maze.goto(-112.5, 100)
maze.goto(-112.5, 50)
maze.goto(-137.5, 50)
maze.goto(-137.5, 112.5)
maze.goto(-50, 112.5)
maze.goto(-50, 62.5)
maze.goto(12.5, 62.5)
maze.goto(12.5, 37.5)
maze.goto(37.5, 37.5)
maze.goto(37.5, 62.5)
maze.goto(87.5, 62.5)
maze.goto(87.5, 150)
maze.goto(12.5, 150)
maze.goto(12.5, 175)
maze.goto(175, 175)
maze.goto(175, -175)
maze.goto(12.5, -175)
maze.end_fill()
maze.penup()
maze.goto(62.5, -50)
maze.pendown()
maze.begin_fill()
maze.goto(125, -50)
maze.goto(125, -12.5)
maze.goto(62.5, -12.5)
maze.goto(62.5, -50)
maze.end_fill()
maze.ht()

myPen=turtle.Turtle()
myPen.penup()
myPen.goto(0,-180)
myPen.pendown()
myPen.color("#DB148E")
myPen.width(4)
myPen.left(90)

#Start of maze

myPen.forward(70)
myPen.right(90)

from turtle import Turtle, Screen

wn = Screen()


speed = 0.5
myPen.speed(10)
myPen.ht()

def travel():
    myPen.forward(speed)
    wn.ontimer(travel, 10)

wn.onkey(lambda: myPen.setheading(90), 'w')
wn.onkey(lambda: myPen.setheading(180), 'a')
wn.onkey(lambda: myPen.setheading(0), 'd')
wn.onkey(lambda: myPen.setheading(270), 's')

wn.listen()

travel()



wn.mainloop()

What is happening now is I can control the turtle with W A S D and draw the maze, but I can just go over the maze and it does not do anything. I was thinking that it could be done either by detecting where the turtle is, or maybe detecting the color of the turtle. Thanks!


Solution

  • Normally, I wouldn't have good news for you. But, because you created your maze as a set of three closed polygons:

    enter image description here

    there is a relatively easy fix! First, download the Python code from Geeks for Geeks article "How to check if a given point lies inside or outside a polygon?". Save this code to a file, I'll call it "poly_util.py" but you can call it anything you wish. Edit this file to remove the code:

    # Driver code
    if __name__ == '__main__':
    

    and everything that follows it. We don't need this code, and it's buggy indentation-wise. Next, edit your own code to import this file, and wrap your begin_fill() and end_fill() segments with begin_poly() and end_poly() calls so we can capture the polygons with get_poly():

    from turtle import Screen, Turtle
    from poly_util import is_inside_polygon
    
    screen = Screen()
    
    maze = Turtle()
    maze.hideturtle()
    maze.speed('fastest')
    maze.penup()
    
    maze.goto(-12.5, -175)
    
    maze.pendown()
    maze.begin_fill()
    maze.begin_poly()
    
    maze.goto(-12.5, -100)
    maze.goto(37.5, -100)
    maze.goto(37.5, -75)
    maze.goto(-112.5, -75)
    maze.goto(-112.5, -37.5)
    maze.goto(-125, -37.5)
    maze.goto(-125, -87.5)
    maze.goto(-87.5, -87.5)
    maze.goto(-87.5, -137.5)
    maze.goto(-75, -137.5)
    maze.goto(-75, -100)
    maze.goto(-50, -100)
    maze.goto(-50, -162.5)
    maze.goto(-150, -162.5)
    maze.goto(-150, -137.5)
    maze.goto(-112.5, -137.5)
    maze.goto(-112.5, -112.5)
    maze.goto(-162.5, -112.5)
    maze.goto(-162.5, -87.5)
    maze.goto(-150, -87.5)
    maze.goto(-150, -37.5)
    maze.goto(-162.5, -37.5)
    maze.goto(-162.5, 12.5)
    maze.goto(-137.5, 12.5)
    maze.goto(-137.5, -12.5)
    maze.goto(-112.5, -12.5)
    maze.goto(-112.5, 12.5)
    maze.goto(-87.5, 12.5)
    maze.goto(-87.5, -50)
    maze.goto(-62.5, -50)
    maze.goto(-62.5, 25)
    maze.goto(-162.5, 25)
    maze.goto(-162.5, 137.5)
    maze.goto(-112.5, 137.5)
    maze.goto(-112.5, 162.5)
    maze.goto(-87.5, 162.5)
    maze.goto(-87.5, 137.5)
    maze.goto(-25, 137.5)
    maze.goto(-25, 87.5)
    maze.goto(12.5, 87.5)
    maze.goto(12.5, 112.5)
    maze.goto(37.5, 112.5)
    maze.goto(37.5, 87.5)
    maze.goto(62.5, 87.5)
    maze.goto(62.5, 125)
    maze.goto(-12.5, 125)
    maze.goto(-12.5, 175)
    maze.goto(-175, 175)
    maze.goto(-175, -175)
    maze.goto(-12.5, -175)
    
    maze.end_poly()
    maze.end_fill()
    
    poly_left = maze.get_poly()
    
    maze.penup()
    maze.goto(12.5, -175)
    maze.pendown()
    
    maze.begin_fill()
    maze.begin_poly()
    
    maze.goto(12.5, -125)
    maze.goto(87.5, -125)
    maze.goto(87.5, -162.5)
    maze.goto(150, -162.5)
    maze.goto(150, -125)
    maze.goto(162.5, -125)
    maze.goto(162.5, -100)
    maze.goto(125, -100)
    maze.goto(125, -137.5)
    maze.goto(112.5, -137.5)
    maze.goto(112.5, -100)
    maze.goto(62.5, -100)
    maze.goto(62.5, -75)
    maze.goto(150, -75)
    maze.goto(150, -12.5)
    maze.goto(162.5, -12.5)
    maze.goto(162.5, 12.5)
    maze.goto(125, 12.5)
    maze.goto(125, 37.5)
    maze.goto(150, 37.5)
    maze.goto(150, 150)
    maze.goto(125, 150)
    maze.goto(125, 112.5)
    maze.goto(100, 112.5)
    maze.goto(100, 87.5)
    maze.goto(125, 87.5)
    maze.goto(125, 62.5)
    maze.goto(100, 62.5)
    maze.goto(100, 12.5)
    maze.goto(37.5, 12.5)
    maze.goto(37.5, -50)
    maze.goto(-37.5, -50)
    maze.goto(-37.5, -25)
    maze.goto(25, -25)
    maze.goto(25, 25)
    maze.goto(0, 25)
    maze.goto(0, 0)
    maze.goto(-37.5, 0)
    maze.goto(-37.5, 50)
    maze.goto(-87.5, 50)
    maze.goto(-87.5, 75)
    maze.goto(-62.5, 75)
    maze.goto(-62.5, 100)
    maze.goto(-112.5, 100)
    maze.goto(-112.5, 50)
    maze.goto(-137.5, 50)
    maze.goto(-137.5, 112.5)
    maze.goto(-50, 112.5)
    maze.goto(-50, 62.5)
    maze.goto(12.5, 62.5)
    maze.goto(12.5, 37.5)
    maze.goto(37.5, 37.5)
    maze.goto(37.5, 62.5)
    maze.goto(87.5, 62.5)
    maze.goto(87.5, 150)
    maze.goto(12.5, 150)
    maze.goto(12.5, 175)
    maze.goto(175, 175)
    maze.goto(175, -175)
    maze.goto(12.5, -175)
    
    maze.end_poly()
    maze.end_fill()
    
    poly_right = maze.get_poly()
    
    maze.penup()
    maze.goto(62.5, -50)
    maze.pendown()
    
    maze.begin_fill()
    maze.begin_poly()
    
    maze.goto(125, -50)
    maze.goto(125, -12.5)
    maze.goto(62.5, -12.5)
    maze.goto(62.5, -50)
    
    maze.end_poly()
    maze.end_fill()
    
    poly_inner = maze.get_poly()
    
    pen = Turtle()
    pen.hideturtle()
    pen.speed('fastest')
    pen.color("#DB148E")
    pen.width(4)
    
    pen.penup()
    pen.sety(-180)
    pen.pendown()
    
    pen.left(90)
    pen.forward(70)
    pen.right(90)
    
    #  Start of maze
    
    distance = 0.5
    
    def travel():
        pen.forward(distance)
    
        position = pen.position()
    
        if is_inside_polygon(poly_left, position) or is_inside_polygon(poly_right, position) or is_inside_polygon(poly_inner, position):
            pen.undo()
    
        screen.ontimer(travel, 50)
    
    screen.onkey(lambda: pen.setheading(90), 'w')
    screen.onkey(lambda: pen.setheading(180), 'a')
    screen.onkey(lambda: pen.setheading(0), 'd')
    screen.onkey(lambda: pen.setheading(270), 's')
    
    screen.listen()
    
    travel()
    
    screen.mainloop()
    

    Now detecting collisions is simply a matter of calling is_inside_polygon() on each of your three polygon components, as shown in the code above. The pen will stop at a wall until you turn and/or back up to move in a legal direction. The code may need some fine tuning but because you used polygons, this is a relatively easy fix to what is normally a difficult problem.

    enter image description here

    Make sure to credit Vikas Chitturi for this great polygon library.