Grid Movement
There is a few different ways to do this and each way gives you slightly different results.
I wanted a method that would detect when I crossed the center of a tile or landed on it.
I came up with this for going left - I could have started with right, up, or down I guess.
This is debug code and simply prints out position and if center was crossed. If you tried this you’d likely come up with a different solution.
|
|
in the code above we are looking at the x axis and at the current frame
-
d is a distance in any direction (x axis)
-
p is the player center at the start of the move (frame)
-
t is the center of the tile the player is on (x axis)
-
e is end point of the move (frame)
-
o is how far we will be from the current tile center point or overflow on trigger
Note: I had to explain what each variable was for. Insufficient naming can require extra explaining.
This test sees if we land on or go past the center point. If you wanted to include start from you’d need to change “p > t” to “p >= t”
So for all directions we can reuse some code
|
|
It can be called from move using:
|
|
The code above doesn’t do anything for the player yet, but gives the ‘coder’ some useful feedback. I broke up move for more clarity.
The output looks like this
|
|
This kind of debugging gives a clear view of what is happening in the code.
The next thing we want to do is to use this to make the grid movement work.
- When we cross a point, but direction hasn’t changed, we want to keep moving.
- When direction has changed once we meet the tile center, we want to move from the tile center to the next point by the “o” amount or overflow in the new direction. i.e. no random delays in turns.
NOTE:
If we wanted our player to stop on center we would ignore the overflow.
For Grid movement to work we need to keep track of the last direction moved
last_dir = [0,0]
We want to have a way to use that tile center calculation, when we adjust player for overflow.
def calc_current_tile_axis_center(self, pos_axis):
return int(pos_axis/40) * 40 + 20
Looking at the git changes we can see what I did just a little better


The full changes of Kinematic Object
|
|
Great that seems to work surprisingly well. This code breaks when moving on the other side of X or Y axis (i.e. graph or quadrant position).
Create the tail
The first step is to simply create a tailpiece wherever the player eats food.
We create a basic “GameObject” Tail class
|
|
Because the snake/player ‘owns’ the tail we modify player with a list
|
|
and we need to add a function to add tailpieces (in player)
def grow_tail(self, initial_pos):
t = Tail(initial_pos, self.speed)
self.tailpieces.append(t)
and finally we need to draw the new objects (in player)
def draw(self):
super().draw()
for t in self.tailpieces:
t.draw()
Now in the game loop we just need to call the function every time the player collides with food
if Rect.collidepoint(food.rect, player.rect.center):
player.grow_tail(food.rect.center)
food.reposition()
Run this, and you will see tailpieces be left behind eat time we eat food.
