Advertisement

Implementing snake (Slither.io) like movement

Started by December 11, 2021 02:46 AM
2 comments, last by turtlemcnuggets 3 years ago

I am making my own version of the Slither.io game, and I am having trouble figuring out what the approach should be for handling the movement of the player/snake. In data, the player is just an array of vec2's that represent points of the body which make a series of lines that can move in any direction on the 2d plane (NOT in a grid-based system like in the classic Snake game, this is free 360 degree movement on the plane). What I am struggling with is how to move/update those points in order to give the desired movement effects:

  • Every point of the snake is always moving to roughly trace the path taken by the head of the snake
  • When player triggers a speed up, every point of the snake immediately moves at the faster speed

I have tried a few different systems to get these effects but have run into problems with each one. If you know exactly what algorithm games like Slither.io are using to accomplish their movement, I suppose you don't even need to read the next three paragraphs, but I will explain what I have tried anyway:

The most naive approach was to move the head of the snake toward the mouse, then for all subsequent points just set it to be the value of the preceding point. This works well, except that speeding up the whole snake immediately does not work--I move the head a greater magnitude when in fast mode, but this faster movement just gradually gets passed down the chain of points according to that naive algorithm, so there is a speed jump at a certain point on the snake.

The next approach was to move each point some distance in the direction of the point preceding it. This works in that the distance each point travels in an update can be increased in one update, but it has a problem: It essentially creates a series of line segments that are approximating a curve, and that approximation will always be shorter than the curve as it “cuts the corners” of the curve. This results in the points bunching up tightly as the snake makes turns, and generally has poor “collapsing” behavior for loops--the corners keep getting cut and loops shrink very quickly after making them, and often create kinks/spots where the points of the snake are jammed up super close to each other. As this was essentially linear approximation of a curve, I explored implementing a version with a quadratic approximation of the curve such that each point wouldn't necessarily be moving directly toward the point in front of it, but the math ended up getting complicated enough that I know that that is not the answer. It should be noted though that I am okay with some corner cutting, if it doesn't result in the snake getting “bunched up.”

The last approach that I just tried was using inverse kinematics, which has a different problem where, because it is just finding a solution to move the segments in a way that keeps them connected, ends up with the tail often not moving at all because the joints are just able to “wiggle” and gradually dissipate any differences in the position of the head of the snake by the time it trickles down to the later points of the snake, especially when trying to do loops. Essentially, the snake wasn't tracing the path of the head, it was just finding ways to stay together while the head moved. It is a quite naive IK implementation without any additional constraints, maybe adding some would be able to solve the problem but that would be stretching my abilities. I'll go there if needed, but I suspect that the answer is simpler.

So, what would be a good way of handling the movement to get the goals that I said earlier? I feel like this shouldn't be as hard as I have made it am missing some simple way of doing the movement. Thanks for any thoughts, I am happy to give more detail about what I mean by anything I said if it wasn't clear/give my code examples if that would help.

What about the first method, only instead of moving directly to the next point's previous location, you move to an interpolated point along the line from its previous location to the next? In this case, when all velocities are identical, it would be the same as you tried: move to the last location of the next segment. When the head accelerates, the next segment would move to, if \(h_0\) and \(h_t\) are the previous and new locations of the head respectively, a point on \(h_t - h_0\) calculated by the fixed distance between segments.

I hope that makes sense. I could draw you a picture, if you like.

My itch.io page, just game jams so far

Advertisement

I'm not sure if this is exactly what you were suggesting, but I came away from reading your comment with the idea to move each point to the position of the next point when moving fast, and only halfway toward the next point under normal speed. I think this is about what I was looking for, thanks!

This topic is closed to new replies.

Advertisement