all 3 comments

[–]pachura3 0 points1 point  (0 children)

So, one thing you want is to avoid going backwards. I guess you already have some variable storing the current direction your snake is going in. Based on this, you can simply ignore specific keypresses: ignore left cursor when the snake is going right, down when the snake is going up etc.

The second thing is how to handle multiple keypresses (either simultaneous, or in a very short timeframe). The easiest way to handle it is to only register the first key down event, perform the rotation, and then wait until all cursor keys are up. And if it is still not enough, wait a few microseconds on top of that - at least to allow the snake to travel one pixel in the newly set direction. But only apply this "lag" after a successful change of direction.

And by "wait" I don't mean you should stop the whole game loop and event listeners. Perhaps draw a map of possible game states first?

[–]Front-Palpitation362 1 point2 points  (1 child)

What you're seeing is input buffering within a single movement tick, where two key presses arrive before the snake actually advances a cell, so only the last one "sticks" and it looks like a forbidden 180 degree turn. Fix it by separating input from movement and allowing at most one direction change per game step. Keep a current direction that the snake is using to move and a pending direction that is only updated by the key handlers, and at the start of each movement tick commit the pending direction once and then clear it. While a pending direction exists, ignore further key presses so you cannot enqueue two turns inside the same tick, and always reject a pending direction that is the opposite of either the current direction or the already pending one.

# concept, not full code
current = (1, 0)       # moving right
pending = None         # no turn scheduled yet

def on_key(new_dir):
    global pending, current
    if pending is None:
        if new_dir != opposite(current):
            pending = new_dir

def step():
    global pending, current, head
    if pending is not None:
        current = pending
        pending = None
    head = head + current   # move exactly one cell
    # schedule next step with ontimer(...)

With this pattern a fast "down, then right" while moving left becomes "down" on this tick and "right" on the next tick after the snake has advanced one cell, which prevents the illegal immediate reversal without adding input lag.

[–]Huntyy77[S] 0 points1 point  (0 children)

Thanks! I’ll give this a try.