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












2















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









share|improve this question























  • Is pos() a floating-point number?

    – Robert Harvey
    Nov 19 '18 at 21:15











  • If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

    – user9694049
    Nov 19 '18 at 21:17













  • Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

    – Robert Harvey
    Nov 19 '18 at 21:18













  • Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

    – user9694049
    Nov 19 '18 at 21:58
















2















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









share|improve this question























  • Is pos() a floating-point number?

    – Robert Harvey
    Nov 19 '18 at 21:15











  • If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

    – user9694049
    Nov 19 '18 at 21:17













  • Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

    – Robert Harvey
    Nov 19 '18 at 21:18













  • Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

    – user9694049
    Nov 19 '18 at 21:58














2












2








2








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









share|improve this question














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






python python-3.x turtle-graphics






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 21:14









user9694049user9694049

132




132













  • Is pos() a floating-point number?

    – Robert Harvey
    Nov 19 '18 at 21:15











  • If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

    – user9694049
    Nov 19 '18 at 21:17













  • Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

    – Robert Harvey
    Nov 19 '18 at 21:18













  • Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

    – user9694049
    Nov 19 '18 at 21:58



















  • Is pos() a floating-point number?

    – Robert Harvey
    Nov 19 '18 at 21:15











  • If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

    – user9694049
    Nov 19 '18 at 21:17













  • Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

    – Robert Harvey
    Nov 19 '18 at 21:18













  • Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

    – user9694049
    Nov 19 '18 at 21:58

















Is pos() a floating-point number?

– Robert Harvey
Nov 19 '18 at 21:15





Is pos() a floating-point number?

– Robert Harvey
Nov 19 '18 at 21:15













If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

– user9694049
Nov 19 '18 at 21:17







If I'm not mistaken, pos() returns a Vec2D with two floating points, like so: [20.00, 10.00] @RobertHarvey

– user9694049
Nov 19 '18 at 21:17















Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

– Robert Harvey
Nov 19 '18 at 21:18







Floating point numbers cannot be reliably compared using equals. Granted, it shouldn't matter if you're storing pos() directly, but you are doing some arithmetic there, so.

– Robert Harvey
Nov 19 '18 at 21:18















Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

– user9694049
Nov 19 '18 at 21:58





Thank you @RobertHarvey ! I added some code to convert the floating points into ints and then append them to the list, plus some code to make sure the ints are always multiples of 10.

– user9694049
Nov 19 '18 at 21:58












1 Answer
1






active

oldest

votes


















0














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.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382728%2fpython-turtle-collision-detection-via-not-in-list-why-doesnt-it-work%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    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.






    share|improve this answer




























      0














      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.






      share|improve this answer


























        0












        0








        0







        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.






        share|improve this answer













        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 20 '18 at 1:37









        cdlanecdlane

        18.6k21144




        18.6k21144
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382728%2fpython-turtle-collision-detection-via-not-in-list-why-doesnt-it-work%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Anylogic : not able to use stopDelay()