Fumofumotris/source/fumotris/tetra.c

183 lines
4.2 KiB
C
Raw Normal View History

2024-05-14 04:20:20 +00:00
#include "tetra.h"
2024-05-15 22:10:47 +00:00
bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt)
2024-05-14 04:20:20 +00:00
{
u8 *blks = calloc(wid * hgt, sizeof(u8));
if (blks == nullptr)
return false;
2024-05-15 22:10:47 +00:00
*tetra = (struct Tetra) {
.blks = blks,
2024-05-14 04:20:20 +00:00
2024-05-15 22:10:47 +00:00
.wid = wid,
.hgt = hgt,
.x = 0,
.y = 0,
.rot = 0
};
2024-05-14 04:20:20 +00:00
return true;
}
void FreeTetra(struct Tetra *tetra)
{
free(tetra->blks);
}
2024-05-15 22:10:47 +00:00
void TetraSet(struct Tetra *tetra, struct TetraTemplate *template)
2024-05-14 04:20:20 +00:00
{
2024-05-15 22:10:47 +00:00
tetra->blks = template->blks;
tetra->wid = template->wid;
tetra->hgt = template->hgt;
tetra->x = 0;
tetra->y = 0;
tetra->rot = 0;
2024-05-14 04:20:20 +00:00
}
2024-05-15 22:10:47 +00:00
usize rotate_index(usize i, usize wid, u8 rot)
2024-05-14 04:20:20 +00:00
{
2024-05-15 22:10:47 +00:00
if(rot == 0)
return i;
2024-05-14 04:20:20 +00:00
2024-05-15 22:10:47 +00:00
usize row = i / wid;
usize col = i % wid;
switch (rot) {
case 1:
return (wid - col - 1) * wid + row;
case 2:
return (wid - row - 1) * wid + (wid - col - 1);
case 3:
return col * wid + (wid - row - 1);
}
return 0;
2024-05-14 04:20:20 +00:00
}
2024-05-19 06:56:14 +00:00
bool TetraIsCollision(struct Tetra *piece, struct Tetra *board)
2024-05-14 04:20:20 +00:00
{
usize i = 0;
2024-05-19 06:56:14 +00:00
for (i16 y = piece->y; y < piece->y + piece->hgt; y++) {
for (i16 x = piece->x; x < piece->x + piece->wid; x++, i++) {
usize rot_i = rotate_index(i, piece->wid, piece->rot);
2024-05-15 22:10:47 +00:00
2024-05-19 06:56:14 +00:00
if(piece->blks[rot_i] == 0)
2024-05-14 04:20:20 +00:00
continue;
if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt)
return true;
if(board->blks[board->wid * y + x] != 0)
return true;
}
}
return false;
}
2024-05-15 22:10:47 +00:00
bool TetraMove(struct Tetra *t, struct Tetra *board, i16 dx, i16 dy)
{
t->x += dx;
t->y += dy;
if (TetraIsCollision(t, board)) {
t->x -= dx;
t->y -= dy;
return false;
}
return true;
}
bool TetraRotate(struct Tetra *t, struct Tetra *board, i8 dr)
{
u8 rot = t->rot;
t->rot = (t->rot + 4 + dr) % 4;
if (TetraIsCollision(t, board)) {
t->rot = rot;
return false;
}
return true;
}
void TetraOverlay(struct Tetra *t, struct Tetra *board)
{
usize i = 0;
for (i16 y = t->y; y < t->y + t->hgt; y++) {
for (i16 x = t->x; x < t->x + t->wid; x++, i++) {
usize rot_i = rotate_index(i, t->wid, t->rot);
if(t->blks[rot_i] == 0)
continue;
if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt)
continue;
board->blks[board->wid * y + x] = t->blks[rot_i];
}
}
}
2024-05-19 06:56:14 +00:00
void TetraTerminalClear(struct Tetra *board, struct Terminal *term, u16 OFS_X, u16 OFS_Y)
2024-05-14 04:20:20 +00:00
{
2024-05-19 06:56:14 +00:00
for (i16 y = board->y; y < board->y + board->hgt; y++) {
for (i16 x = board->x; x < board->x + board->wid; x++) {
struct Char4 *ch4 = TerminalGet(term, (x * 2) + OFS_X, y + OFS_Y);
2024-05-14 04:20:20 +00:00
2024-05-19 06:56:14 +00:00
ch4[0] = (struct Char4) { .ch = '.', .color.fg = 8 };
ch4[1] = (struct Char4) { .ch = ' ', .color.fg = 8 };
}
2024-05-14 04:20:20 +00:00
}
}
2024-05-19 06:56:14 +00:00
void TetraTerminalDraw(struct Tetra *piece, struct Terminal *term, u16 OFS_X, u16 OFS_Y)
2024-05-14 04:20:20 +00:00
{
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
usize i = 0;
2024-05-19 06:56:14 +00:00
for (i16 y = piece->y; y < piece->y + piece->hgt; y++) {
for (i16 x = piece->x; x < piece->x + piece->wid; x++, i++) {
usize rot_i = rotate_index(i, piece->wid, piece->rot);
2024-05-15 22:10:47 +00:00
2024-05-19 06:56:14 +00:00
if (piece->blks[rot_i] == 0)
2024-05-14 04:20:20 +00:00
continue;
2024-05-19 06:56:14 +00:00
struct Char4 *ch4 = TerminalGet(term, (x * 2) + OFS_X, y + OFS_Y);
u8 fg = blk_colors[piece->blks[rot_i]];
ch4[0] = (struct Char4) { .ch = '[', .color.fg = fg };
ch4[1] = (struct Char4) { .ch = ']', .color.fg = fg };
}
}
}
void TetraTerminalDrawGhost(struct Tetra *t, struct Tetra *board, struct Terminal *term, u16 OFS_X, u16 OFS_Y)
{
struct Tetra ghost = *t;
while(TetraMove(&ghost, board, 0, 1));
usize i = 0;
for (i16 y = ghost.y; y < ghost.y + ghost.hgt; y++) {
for (i16 x = ghost.x; x < ghost.x + ghost.wid; x++, i++) {
usize rot_i = rotate_index(i, ghost.wid, ghost.rot);
2024-05-14 04:20:20 +00:00
2024-05-19 06:56:14 +00:00
if (ghost.blks[rot_i] == 0)
continue;
struct Char4 *ch4 = TerminalGet(term, (x * 2) + OFS_X, y + OFS_Y);
ch4[0] = (struct Char4) { .ch = '[', .color.fg = 8 };
ch4[1] = (struct Char4) { .ch = ']', .color.fg = 8 };
2024-05-14 04:20:20 +00:00
}
}
}