Adding physics to puzzle game

Started by
6 comments, last by extralongpants 18 years, 5 months ago
I have created a simple Tetris Attack (or Panel De Pon) clone with SDL. With it I implemented the basic rules, now I've decided to take my game to the next level and make the gameplay flow more like an actual Tetris Attack. Particularly, how to make the blocks fall smoothly over a period of time. Right now, blocks that lie above empty spaces are 'flipped' instantly to that new location, whenever blocks below them disappear. The solution I have thought of is to add simple physics like those you would find in a platform game to detect collision and add some gravity. So after a block collides with another block, it stops falling. For this, I may have to add more parameters to each block than just assigning their color (the blocks are represented as a 1-D array or more specifically, a deque). Should I define the parameters of each block by using a structure, or should I use a class? I haven't done a platform game before so I don't have much of a clue as to how you should iterate each check for collision detection with many objects. I've done it with a small target shooting game but that only involved 5 objects at the most. So if there are 50 blocks on the screen does that mean that the program has to check 50 * 50 times?
Advertisement
Quote:Original post by Just Chris
The solution I have thought of is to add simple physics like those you would find in a platform game to detect collision and add some gravity. So after a block collides with another block, it stops falling. For this, I may have to add more parameters to each block than just assigning their color (the blocks are represented as a 1-D array or more specifically, a deque).


Physics simulation is probably a bit too much for this game. Instead, after a block clears, tell all the blocks direclty above it to start "falling." "Falling" just consists of moving the block down one line over x seconds (just a linear interpolation). Each frame you could traverse all falling blocks, bottom to top. For each falling block: if it hits a new line, check to see if a non-falling block is immediately below it - if there is, stop the block (mark it as "non-moving"), otherwise, tell it to keep on moving down.

In order to have this system work without any hitches, you may have to keep track of lines, which would just be a set of flags corresponding to each place a block could be (like a set of slots). When a block begins moving, you will have to clear out the flag in the appropriate place on the line the block is on.

Also, be sure to use the amount of time passed (not location) since a block started falling to determine when to stop the block, and when that time is reached, place the block exactly where it should be. This will help eliminate any issues caused by jumps in frame-rate, where blocks might stop falling too late (thus miss-align themselves).

Quote:
So if there are 50 blocks on the screen does that mean that the program has to check 50 * 50 times?


Blocks can only fall downward - thus any blocks above or to the left or right of a moving block don't have to be checked for collision. Plus, if you use the method I described above - keeping track of slots in lines - you should only have to perform one collision check each frame for every block, at the very most. Most blocks wont be falling and collision detections only need to take place when a block is done moving down a line. And the collision detection method itself is just a flag check.

I know my method may be a bit much to swallow, but I used it in my last Tetris game and I am very pleased with it. It's a little counter-intuitive, in that blocks are not actually falling and colliding, but it's fast and it makes sense.

Actually simulating gravity and collision, even on a simple level, will complicate your game, and chances are your blocks will have a much greater chance of accidentally becoming misalligned.

Anyway, good luck with your game. Let us know when you finish it - I love tetris attack and I would definately try it out, and I'm sure some others would too.
Quote:Original post by Just Chris
I have created a simple Tetris Attack (or Panel De Pon) clone with SDL. With it I implemented the basic rules, now I've decided to take my game to the next level and make the gameplay flow more like an actual Tetris Attack. Particularly, how to make the blocks fall smoothly over a period of time. Right now, blocks that lie above empty spaces are 'flipped' instantly to that new location, whenever blocks below them disappear.

The solution I have thought of is to add simple physics like those you would find in a platform game to detect collision and add some gravity. So after a block collides with another block, it stops falling. For this, I may have to add more parameters to each block than just assigning their color (the blocks are represented as a 1-D array or more specifically, a deque).

Should I define the parameters of each block by using a structure, or should I use a class? I haven't done a platform game before so I don't have much of a clue as to how you should iterate each check for collision detection with many objects. I've done it with a small target shooting game but that only involved 5 objects at the most. So if there are 50 blocks on the screen does that mean that the program has to check 50 * 50 times?


I doubt that you are wanting physics. Physics tools would include things like impulses and torque forces if the block hit another block while turning, causing both blocks to move and collide into other blocks, etc.

What you describe is interpolated animation. At time 0 you want the block in one place and orientation, at time 1 you want the block in another place and orientation. Rather than rendering the two steps directly, you interpolate the rotation and translation on the block.

Graphically:

What you are doing now:
Step 0                    Step 1Rotation 0                Rotation 90Height 5                  Height 6 |                            |                        ----- |-                       |   


What you want to do:
Step 0       Step 0.5        Step 1Rotation 0    R 45           R 90Height 5      H 5.5          H 6 |              /             |             /             ----- |-           \              |   


Except you'll want to have more steps in the middle giving a smooth rotation.

R 0  R 10     R 23    R 49     R 78    R 90H 5  H 5.11   H 5.25  H 5.53   H 6.86  H 6


If your display is not coupled with your game processing, you can run the game at fixed steps, and run the display as fast as possible interpolating between the steps. If they have a slow display it will look a bit jumpy. If they have a fast dislpay it will be wonderfully smooth.

frob.
Actually, I'm pondering upon ways to do something very similar to this. I'm also after a kind of pseudo-physics for my Scorched Earth style game.

The levels will be composed of various objects such as rocks or bubbles or pebbles that fall from the sky and that should reasonably realisically pile on top of one another and fall down if the block beneath is blown apart. I believe this is similar, except that in my case I'm not dealing with blocks.

I also appreciate that accurate physics modelling would not work with this because it would require a heck of a lot of processing work and still not really produce the results we are used to seeing in games of this nature, I've given it a try, just to see, and can confirm this.. the blocks can do all kinds of unexpected things under normal physics simulation if you don't have it modelled absolutely perfectly.

I guess the differences in my case are that
a) I'm not using blocks, but rather circles and possibly other shapes (3d models in a 2d field of play)
b) Blocks don't fall in a grid (I don't want to be restricted to having all my blocks aligned to a grid)

My problem though is that I either seem to end up with too complex a simulation that makes the game too slow, or I end up with too many innaccuracies which is unacceptable for the look of the game.

Anyhoo, I don't want to derail the thread, but I think a similar solution would probably work well for us both.. so any further ideas are welcomed!! (and I really really hope I haven't sent this topic off on a tangent!)

Cheers,

Steve


Cheers,SteveLiquidigital Online
OK, I wasn't aware you were using un-aligned circles. That changes things a bit [smile].

Are you always using circles (or spheres) as bounding volumes? If you don't, the collision detection and prevention code can get really ugly (Just a warning).

Well, you can still put some major limitations on you physics code. If, for instance, pieces do not bounce off of other pieces, then you know for a fact that for any given piece, you will only have to determine if it collides with the pieces whose center is lower than the current piece's.

Secondly, if all of your pieces fall at the same speed (which I recommend), and not under acceleration, you only have to test for collisions between falling objects and non-falling objects (a falling object will never catch up with another falling object until it is stopped and marked as "static", and static objects do not need to be tested for collisions with other static objects).

Given these limitations, each time a block or set of blocks disappears, you could make all blocks with a center above the lowest disappearing block's center start falling (just a simple constant velocity). Then begin testing for collisions from the bottom of the board to the top. Each time a moving block collides with a static block or the game board boundaries, mark it as static and zero-out its velocity.

The algorithm could still be implemented similarly if you need pieces to slide off of other pieces as they fall, except that collisions would need to be detected between falling objects. Once a moving block stops moving, it should be marked as static (collision response code generally becomes simpler when you know that one object isn't going to move).

This should be pretty fast with the given limitations - sphere-sphere intersection tests are relatively cheap (especially if you keep track of each sphere's squared radius and avoid the square root).

Anyway, I hope that helps.
In my game Squarez, I encountered and solved the same problem. As pieces are destroyed, the pieces above need to fall into place. The gameboard is represented internally as a 2D array. Visually, there is one object instance for each grid square. So, each instance knows which spot on the board it belongs to, and thus which image (red, green, or blue) to draw for itself. It also has variables x and y which determine its place onscreen (relative to the board object), and a y-velocity.

The update code for the piece objects is pretty simple. It calculates a "target_y" position based on its position within the grid, and the size of the grid. If the current y is greater than or equal to target_y (either it's not moving, or it just landed) then set y = target_y, and y_velocity to zero. The reason for setting y = target_y is that sometimes it'll overshoot a bit--it actually looks good, like the piece is bouncing into place.

If the current y is less than target_y (it's above where it's supposed to be), then it increases its y-velocity a bit (accelerates downward, like any falling object does).

To destroy a piece, I simply destroy the object instance, make some particles so it looks nice, and tell all the instances above it to move down by one grid square (I also move the values in the 2D array downward). Now their target_y values have increased, and y < target_y for all of them, so they begin moving downward. Then I create a new object instance just above the top edge of the screen, and assign it to the top row of the grid.

There's no need for collision detection. The piece knows how far it's going to fall, since it knows which grid square it belongs to. Deciding where a piece ends up is done at the level of shifting things around in the 2D array, not at the level of onscreen objects colliding with each other.

(You can see Squarez at http://big-brain.org/index.php?option=content&task=view&id=3&Itemid=26)
Quote:OK, I wasn't aware you were using un-aligned circles. That changes things a bit .


I haven't read the reply yet, but thanks for it and I shall in a second! I just wished to point out though that I am not the original poster.... I just chipped in with a similar problem I am having to the OP!

Thanks anyhoo though, I will read through now and I hope I haven't derailed things!!

Cheers,

Steve
Cheers,SteveLiquidigital Online
Quote:Original post by Mephs
Quote:OK, I wasn't aware you were using un-aligned circles. That changes things a bit .


I haven't read the reply yet, but thanks for it and I shall in a second! I just wished to point out though that I am not the original poster.... I just chipped in with a similar problem I am having to the OP!

Thanks anyhoo though, I will read through now and I hope I haven't derailed things!!

Cheers,

Steve


Haha, ah, my brain hurts... Oh well.
At least I'm not confused anymore.

This topic is closed to new replies.

Advertisement