Sign in to follow this  
clockwise

Tetris Clones: Movement & Collision

Recommended Posts

OK, I've been wanting to write my own(tada!) tetris clone fore awhile now but when I try, I cant seem to figure out exactly what the best way to move the blocks around is and how to do collision on them. Basically I have the idea to use a 4x4 array which will suffice for each piece. Example: 0000 1000 0000 0000 0100 1000 0110 0110 1110 1000 0011 0110 0000 1000 0000 0000 The hard part comes in when I try to figure out how to keep track of it inside the game board(also an array). Then doing collision, since I store my blocks as arrays I'm thinking I'd have to check each indice against the board to figure out if its touch something, and is inside the boundaries. Once I get this part figured out I'm sure I can write the rest with no trouble, but just when I sit down to try and figure it out, I cant seem to come up with a solution that I can translate into code. How did you guys do it? I just think I need a little direction thats all. Thanks P.S. I haven't written any code yet this time, I'm just brainstorming, and searching for ideas.

Share this post


Link to post
Share on other sites
Well, you have your array for the block, and an array for the game board. In addition you need to keep track of the position and rotation of the current active block. When it's time to move the block one step down, check the blocks array against the boards array, and if it collides, add the active block to the board, move it back up and change the type.

Something like this should work for detecting the collision:

activeblock.y --;
for(xl = 0; xl < 4; xl++){
for(yl = 0; yl < 4; yl++){
if(activeblock[xl][yl] && board[activeblock.x + xl][activeblock.y + yl]) collide();
}}

if it collides, set the correct blocks on the board to true and reset the active block.

Share this post


Link to post
Share on other sites
A neat trick is to make the board huge enough so you won't have to check if the stone lies outside of the board. My board usually looks something like this:

0000000000000000
0000000000000000
0000000000000000
0000000000000000
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0010000000000100
0011111111111100
0000000000000000
0000000000000000
0000000000000000
0000000000000000

This way, any block will collide with the border before it can get out of the board, thus no index checking required.

Another hint I can give you is to use another data structure for your stones.
If you store them as a 4x4 matrix you have to do 16 collision tests, because theoretically any of the 16 entries could be set to 1 (allowing for grotesquely formed blocks). When you look at the nested for loops, it seems like you are "searching for the 1s", yet you already know precisely where they are and that there's exactly four of them. So why not simply store the 4 coordinates?

In my previous tetris clone, I stored the data for the O block as follows:

const char stone[] = {0x11, 0x12, 0x21, 0x22}; // of course there are more stones, this is just an example

0x21 means y is 2 and x is 1. Now remember the board being a little larger than the visible 10 blocks? It's no accident I chose 16 as the width, because this way you can simply use each of the four stone[] values as an index into the board after adding the the current coordinates to it. That's how my collision method looked like:


int collision()
{
int res = 0;
const int current = current_y<<4 + current_x;
for (int i=0; i<4; i++)
{
res |= board[current + stone[i]];
}
return res;
}



Of course you can also unroll the loop quite easily:


int collision()
{
const int current = current_y<<4 + current_x;
return board[current + stone[0]]
|board[current + stone[1]]
|board[current + stone[2]]
|board[current + stone[3]];
}




I think this is a great example why you should choose the appropriate data structure carefully. Just because every stone fits in a 4x4 matrix it does not mean this is the best solution to store them.

Share this post


Link to post
Share on other sites
Hey! I never thought about doing it that way, some good tips. The only problem is somehow I have survived as a programmer without ever learning hex or bit operations(was going to ask about that in another thread), where might I learn about those things so I can use these techniques?

Share this post


Link to post
Share on other sites
Quote:
Original post by clockwise
I have survived as a programmer without ever learning hex or bit operations

Hex is just another way to present your numbers. Additionally to the ten digits you already know from the decimal system there are six more digits: A, B, C, D, E and F.

Thus, the first sixteen numbers in hex are:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

The same numbers in decimal are:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

In order to mark a number as hex you usually put 0x or $ in front of it (or h at the end).
Here is a table for the first 256 numbers:


0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
0x00 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0x10 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0x20 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
0x30 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
0x40 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
0x50 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
0x60 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
0x70 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
0x80 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
0x90 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
0xa0 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
0xb0 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
0xc0 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
0xd0 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
0xe0 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
0xf0 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255


To get the right hexadecimal representation, you simply add what's in the first column of the corresponding line and the first line of the column. For example, 200 is 0xc0+0x08 = 0xc8.

Since 16 is a power of 2, every hex digit can be represented by four binary digits:


0x0 = 0000b
0x1 = 0001b
0x2 = 0010b
0x3 = 0011b
0x4 = 0100b
0x5 = 0101b
0x6 = 0110b
0x7 = 0111b
0x8 = 1000b
0x9 = 1001b
0xA = 1010b
0xB = 1011b
0xC = 1100b
0xD = 1101b
0xE = 1110b
0xF = 1111b


I assume you know how to add numbers in decimal with pen and paper. Try the same in hex.

What is 5+5, 6+A, F+F, 2C+D4 ? What is 100-2?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this