简体   繁体   中英

Python Turtle Collision Detection via “not in” list. Why doesn't it work?

The goal of this test code is to make a player that moves with W,A,S,D and starts or stops building a wall with the ENTER key. I would appreciate it if someone could tell me why he only sometimes collides with his walls. Feel free to critique my code in a general sense as well! Thanks in advance.

import turtle

grid_size = 10

t1 = turtle.Pen()
t1.width(grid_size)
t1.up()

walls = [[0,0]]
walls.clear()

def toggle_building():
    if t1.isdown():
        t1.up()
    else:
        t1.down()

def lay_brick():
    if t1.isdown() and t1.pos() not in walls:
        walls.append(t1.pos())
    print("Brick layed.")

def print_pos():
    print(t1.pos())

def move_up():
    t1.setheading(90)
    if t1.pos() + [0, grid_size] not in walls:
        t1.forward(grid_size)
        lay_brick()
    else:
        print("wall")
    print_pos()
def move_left():
    t1.setheading(180)
    if t1.pos() - [grid_size, 0] not in walls:
        t1.forward(grid_size)
        lay_brick()
    else:
        print("wall")
    print_pos()
def move_down():
    t1.setheading(270)
    if t1.pos() - [0, grid_size] not in walls:
        t1.forward(grid_size)
        lay_brick()
    else:
        print("wall")
    print_pos()
def move_right():
    t1.setheading(0)
    if t1.pos() + [grid_size, 0] not in walls:
        t1.forward(grid_size)
        lay_brick()
    else:
        print("wall")
    print_pos()

turtle.onkeypress(move_up, "w")
turtle.onkeypress(move_left, "a")
turtle.onkeypress(move_down, "s")
turtle.onkeypress(move_right, "d")
turtle.onkeypress(toggle_building, "Return")
turtle.listen()

As noted in the comments to your question, the turtle wanders a floating point plane and even though you believe it has returned to the exact same spot as before, there's always a little bit of floating point noise added to the location. Converting positions to int for comparison definitely helps but may not be sufficient.

Below is my attempt to make this robust by changing the coordinate system itself so it appears we're moving by 1 instead of 10. It also attempts to reduce the number of places the floating point to integer conversion needs to occur:

from turtle import Screen, Turtle

GRID_SIZE = 10

def toggle_building():
    if turtle.isdown():
        turtle.penup()
    else:
        turtle.pendown()

def lay_brick(position):
    if turtle.isdown():
        walls.add(position)

def move_up():
    turtle.setheading(90)

    position = int(turtle.xcor()), int(turtle.ycor()) + 1

    if position not in walls:
        turtle.goto(position)
        lay_brick(position)

def move_left():
    turtle.setheading(180)

    position = int(turtle.xcor()) - 1, int(turtle.ycor())

    if position not in walls:
        turtle.goto(position)
        lay_brick(position)

def move_down():
    turtle.setheading(270)

    position = int(turtle.xcor()), int(turtle.ycor()) - 1

    if position not in walls:
        turtle.goto(position)
        lay_brick(position)

def move_right():
    turtle.setheading(0)

    position = int(turtle.xcor()) + 1, int(turtle.ycor())

    if position not in walls:
        turtle.goto(position)
        lay_brick(position)

screen = Screen()
WIDTH, HEIGHT = (screen.window_width() / 2) // GRID_SIZE, (screen.window_height() / 2) // GRID_SIZE
screen.setworldcoordinates(-WIDTH, -HEIGHT, WIDTH, HEIGHT)

turtle = Turtle()
turtle.width(GRID_SIZE)
turtle.fillcolor('red')
turtle.penup()

walls = set()

screen.onkeypress(move_up, "w")
screen.onkeypress(move_left, "a")
screen.onkeypress(move_down, "s")
screen.onkeypress(move_right, "d")
screen.onkeypress(toggle_building, "Return")

screen.listen()

screen.mainloop()

It also uses a set to contain the walls. Since order doesn't matter, this will make the test faster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM