mirror of
https://github.com/thepigeongenerator/tetris_clone.git
synced 2025-12-17 05:55:46 +01:00
82 lines
2.1 KiB
C
82 lines
2.1 KiB
C
#include "tetris.h"
|
|
|
|
#include <string.h>
|
|
#include "util/intdef.h"
|
|
|
|
/* Board co-ordinates:
|
|
* 0 1 2 3
|
|
* 4 5 6 7
|
|
* 8 9 A B
|
|
* C D E F */
|
|
const u16 tetromino_shapes[7][4] = {
|
|
/* NONE CW_90 CW_180 CW_270 */
|
|
[TET_I] = {0x159D, 0x89AB, 0x26AE, 0x4567},
|
|
[TET_O] = {0x569A, 0x569A, 0x569A, 0x569A},
|
|
[TET_T] = {0x1456, 0x1569, 0x4569, 0x1459},
|
|
[TET_J] = {0x0456, 0x1259, 0x456A, 0x1589},
|
|
[TET_L] = {0x4536, 0x159A, 0x4568, 0x0159},
|
|
[TET_S] = {0x1245, 0x156A, 0x5689, 0x0459},
|
|
[TET_Z] = {0x0156, 0x2569, 0x459A, 0x1458},
|
|
};
|
|
|
|
void tetris_get_blocks(u8 tetromino, uint *restrict positions) {
|
|
uint shape = tetromino_shapes[tetromino & 7][tetromino >> 3];
|
|
uint *end = positions + 8;
|
|
while (positions < end) {
|
|
*positions += shape & 3;
|
|
shape >>= 2;
|
|
positions++;
|
|
}
|
|
}
|
|
|
|
void tetris_init_rows(const u8 *restrict data, const u8 *restrict *restrict out) {
|
|
const u8 *restrict *end = out + TET_HEIGHT;
|
|
while (out < end) {
|
|
*out = data;
|
|
data += TET_WIDTH;
|
|
out++;
|
|
}
|
|
}
|
|
|
|
int tetris_clear_rows(u8 *restrict *restrict rows) {
|
|
int count = 0;
|
|
u8 *cache[4]; /* the maximum amount of rows the user can clear at once is four */
|
|
|
|
for (int y = 0; y < TET_HEIGHT; y++) {
|
|
int x = 0;
|
|
while (x < TET_WIDTH && rows[y][x] && count < 4) x++;
|
|
if (x >= TET_WIDTH) cache[count++] = rows[y];
|
|
else rows[y - count] = rows[y];
|
|
}
|
|
|
|
if (count) {
|
|
for (int i = 0; i < count; i++) {
|
|
memset(cache[i], 0, TET_WIDTH);
|
|
rows[TET_HEIGHT - 1 - i] = cache[i];
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
int tetris_intersect(const u8 *restrict const *restrict rows, u8 tetromino, uint x, uint y) {
|
|
uint *pos = (uint[8]){x, y, x, y, x, y, x, y};
|
|
uint *end = pos + 8;
|
|
tetris_get_blocks(tetromino, pos);
|
|
for (; pos < end; pos += 2) {
|
|
if (*(pos + 0) >= TET_WIDTH) return 2;
|
|
if (*(pos + 1) >= TET_HEIGHT) return 2;
|
|
if (rows[*(pos + 1)][*pos]) break;
|
|
}
|
|
return pos < end;
|
|
}
|
|
|
|
void tetris_place(u8 *restrict *restrict rows, u8 tetromino, uint x, uint y) {
|
|
uint *pos = (uint[8]){x, y, x, y, x, y, x, y};
|
|
uint *end = pos + 8;
|
|
tetris_get_blocks(tetromino, pos);
|
|
tetromino &= 7; /* strip rotation data */
|
|
tetromino |= TET_NON_EMPTY;
|
|
for (; pos < end; pos += 2)
|
|
rows[*(pos + 1)][*pos] = tetromino;
|
|
}
|