Need help fixing bug in Raylib Tetris Game Port

Hello all!

i tried to port the classic game tetris from the raylib website to zig. It works fine, except for a bug where a part of a piece gets stuck when you move right after the piece appears…
I really can’t figure out how to fix this bug and i need help/pointers on how to go about fixing such a bug.
I think it might have something to do with some while loops in the ResolveFallingMovement and/or ResolveLateralMovement functions, but i am not sure.

You can find the repo here: tetris.zig/src/tetris.zig at main - talvdav/tetris.zig - Codeberg.org

Thanks.

The issue is with these loops:

var j: usize = GRID_VERTICAL_SIZE - 2;
while (j > 0) : (j -= 1) {
    // ...
}

They miss the case j=0. You fixed this in one place:

var j: usize = GRID_VERTICAL_SIZE - 1;
while (j > 0) {
    j -= 1;
    // ...
}

So one fix to this issue would be to do this change for all such loops.

I ran into one other issue where the game would sometimes panic if I held left when a piece hit the ground up against the left wall. This occurs because immediately after a piece sets into place there are no longer any moving squares. Thus the collision detection fails and lets the piece move left even when it is against the wall, resulting in unsigned integer overflow when the x position goes “negative”. A kind of hacky way to fix this is to make sure pieceActive is true before doing any piece movement.

All of these issues stem from the ways that Zig is more strict/verbose about integer types and overflow.

1 Like

Hi @permutationlock thank you for your reply!

I tried what you have written but it did not work for me, did you implement your suggestions, do you have a gist or paste bin?

To fix the integer overflow: would it make sense to make sure that x can’t be negative or would the “be sure pieceActive is true before movement” the better choice?

Hi talvdav,

I reproduced your issue and permutationlock’s changes to the while loops work for me.

I had to see the problem with my step debugger for it to make sense. Because the boundary of your grid is filled with non-moving blocks, some of the loops can start with -2 instead of -1 for the verticals, since the last vertical row never has moving blocks to consider in ResolveLateralMovement()

Now, for my vscode setup, I was not able to inspect the grid because it was a global variable, I had to make it local to see it in the debugger. I also setup a conditional breakpoint to stop right in the middle and 3 rows from the top (i == 5 and j == 2). Maybe setting up step debugging can help you see the why the while loop is failing.

fn ResolveLateralMovement() bool {
    var collision: bool = false;

    // make static grid a local var for debugger inspecting
    const _my_grid = &grid;
    _ = _my_grid;

    // Piece movement
    if (rl.isKeyDown(rl.KeyboardKey.key_left)) // Move left
    {
       /// ... 

2 Likes

Hi @mark3,

can you explain to me in more detail how you setup you debugging stuff?

I tried changeing the while loops but it seem to introduce more bugs, did you only change the while loops in ResolveLateralMovement?

Yes, I only changed the while loops in ResolveLateralMovement.

The problem is that

var j: usize = GRID_VERTICAL_SIZE - 2;
while (j > 0) : (j -= 1) {
    // ...
}

will never execute for j=0.

  • when j=1, the loop executes
  • then (j-=1) evaluates
  • then while(j > 0) evaluates to false, because j =0
var j: usize = GRID_VERTICAL_SIZE - 2;
while (j >= 0) : (j -= 1) {
    // ...
}

This will execute when j=0, but then (j -= 1) will execute and cause j to be -1, which is out of bounds for an unsigned value.

This will execute when j=0, because it is changed at the beginning of the loop, not after the loop completes, like the above examples.

while (j > 0) {
    j -= 1;
    // ...
}
1 Like