gdf
dfg
This commit is contained in:
parent
8b482a0bb6
commit
582b157454
21
.vscode/c_cpp_properties.json
vendored
Normal file
21
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Win32",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE"
|
||||||
|
],
|
||||||
|
"windowsSdkVersion": "10.0.22000.0",
|
||||||
|
"compilerPath": "C:/mingw64/bin/gcc.exe",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "windows-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"compare": "c",
|
||||||
|
"concepts": "c",
|
||||||
|
"cstdlib": "c",
|
||||||
|
"type_traits": "c",
|
||||||
|
"cmath": "c",
|
||||||
|
"limits": "c",
|
||||||
|
"new": "c"
|
||||||
|
}
|
||||||
|
}
|
2
build.py
2
build.py
|
@ -11,7 +11,7 @@ ARGS = "-fdiagnostics-color -pthread -Wall -std=c17 -pedantic -g"
|
||||||
|
|
||||||
SOURCE_DIR = Path("source/")
|
SOURCE_DIR = Path("source/")
|
||||||
OBJECT_DIR = Path("objects/")
|
OBJECT_DIR = Path("objects/")
|
||||||
OUTPUT = Path("build/debug")
|
OUTPUT = Path("debug")
|
||||||
|
|
||||||
|
|
||||||
SRC_CHECKSUMS_TXT = Path("build/src_checksums.txt")
|
SRC_CHECKSUMS_TXT = Path("build/src_checksums.txt")
|
||||||
|
|
BIN
build/debug.exe
BIN
build/debug.exe
Binary file not shown.
|
@ -1 +1 @@
|
||||||
{"tetr": "", "ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "", "vector": ""}
|
{"ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "", "vector": "", "tetra": ""}
|
|
@ -1 +1 @@
|
||||||
["0d7597ffd48812c52d3f02731cbf693f", "6669fc7fcffc77563f1315cb7710ec82", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "1d6bdf7e8de4ac751252b67027e5d57e", "330b6f9493d091e7c340c1434b6f80b4", "a3dca3fbce775b791384bec8abc3f0c3", "f61af2abe56cd6881a830ae6222483e9", "1cdcae043579aa6406b9823b5f52aedd", "088145536b04ef82517eb93630888dff", "1420f33d62a8ed8429c8f1a96f1ab33e", "e38bd5ea2b554a21849158242a2add8e", "9df90eabc8908cac60aa774d335a106c", "333c7211bb2c72ad321495f53d11bff0", "dc6df72158812bc9f6ed484a4cfb046b"]
|
["1d6bdf7e8de4ac751252b67027e5d57e", "9df90eabc8908cac60aa774d335a106c", "1420f33d62a8ed8429c8f1a96f1ab33e", "dc6df72158812bc9f6ed484a4cfb046b", "6669fc7fcffc77563f1315cb7710ec82", "333c7211bb2c72ad321495f53d11bff0", "088145536b04ef82517eb93630888dff", "f61af2abe56cd6881a830ae6222483e9", "e09059d1f20c982c6c42a61a0754c102", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "330b6f9493d091e7c340c1434b6f80b4", "e38bd5ea2b554a21849158242a2add8e"]
|
BIN
objects/ctrl.o
BIN
objects/ctrl.o
Binary file not shown.
Binary file not shown.
BIN
objects/event.o
BIN
objects/event.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
objects/input.o
BIN
objects/input.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
objects/tetr.o
BIN
objects/tetr.o
Binary file not shown.
BIN
objects/tetra.o
Normal file
BIN
objects/tetra.o
Normal file
Binary file not shown.
BIN
objects/vector.o
BIN
objects/vector.o
Binary file not shown.
BIN
objects/win.o
BIN
objects/win.o
Binary file not shown.
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
|
|
||||||
typedef size_t usize;
|
typedef size_t usize;
|
||||||
typedef ptrdiff_t isize;
|
|
||||||
|
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
|
|
|
@ -51,8 +51,9 @@ bool FumoInstanceRun(struct FumoInstance *inst)
|
||||||
|
|
||||||
nsec now = TimeNow();
|
nsec now = TimeNow();
|
||||||
inst->frametime = now - inst->time;
|
inst->frametime = now - inst->time;
|
||||||
EventInvoke(&inst->on_update, inst);
|
|
||||||
inst->time = now;
|
inst->time = now;
|
||||||
|
|
||||||
|
EventInvoke(&inst->on_update, inst);
|
||||||
|
|
||||||
TerminalPrint(&inst->term, buf, buf_n);
|
TerminalPrint(&inst->term, buf, buf_n);
|
||||||
puts(buf);
|
puts(buf);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -74,7 +75,11 @@ void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key)
|
||||||
{
|
{
|
||||||
usize index = key % dict->capacity;
|
usize index = key % dict->capacity;
|
||||||
|
|
||||||
return probe_bkt(T, dict, index, key);
|
void *bkt = probe_bkt(T, dict, index, key);
|
||||||
|
if (bkt == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return get_val(T, bkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val)
|
void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val)
|
||||||
|
@ -82,6 +87,7 @@ void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val)
|
||||||
usize index = key % dict->capacity;
|
usize index = key % dict->capacity;
|
||||||
|
|
||||||
void *bkt = probe_empty_bkt(T, dict, index, key);
|
void *bkt = probe_empty_bkt(T, dict, index, key);
|
||||||
|
|
||||||
if (*get_key(T, bkt) == 0)
|
if (*get_key(T, bkt) == 0)
|
||||||
set_bkt(T, bkt, key, val);
|
set_bkt(T, bkt, key, val);
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,15 @@ DictT BIND_T = DICT_T(struct InputAxis *);
|
||||||
bool CreateController(struct Controller *ctrl)
|
bool CreateController(struct Controller *ctrl)
|
||||||
{
|
{
|
||||||
struct InputAxis *axes = calloc(16, sizeof(struct InputAxis));
|
struct InputAxis *axes = calloc(16, sizeof(struct InputAxis));
|
||||||
|
|
||||||
if (axes == nullptr)
|
if (axes == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CreateDictionary(BIND_T, &ctrl->binds))
|
if (!CreateDictionary(BIND_T, &ctrl->binds))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*ctrl = (struct Controller) {
|
ctrl->pending_len = 0;
|
||||||
.pending_len = 0,
|
ctrl->axes = axes;
|
||||||
.axes = axes,
|
ctrl->axes_len = 0;
|
||||||
.axes_len = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -42,13 +39,11 @@ bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type)
|
||||||
u32 hash = hash_bind(code, type);
|
u32 hash = hash_bind(code, type);
|
||||||
|
|
||||||
struct InputAxis *axis = &ctrl->axes[control];
|
struct InputAxis *axis = &ctrl->axes[control];
|
||||||
struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, axis);
|
struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, &axis);
|
||||||
|
|
||||||
if (bind == nullptr)
|
if (bind == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*bind = axis;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,13 +92,13 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
|
||||||
struct InputRecord *rec = recs->buf + i;
|
struct InputRecord *rec = recs->buf + i;
|
||||||
|
|
||||||
u32 hash = hash_bind(rec->code, rec->type);
|
u32 hash = hash_bind(rec->code, rec->type);
|
||||||
struct InputAxis *axis = DictionaryFind(BIND_T, &ctrl->binds, hash);
|
struct InputAxis **axis = DictionaryFind(BIND_T, &ctrl->binds, hash);
|
||||||
|
|
||||||
if (axis == nullptr)
|
if (axis == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dispatch_update(axis, rec);
|
dispatch_update(*axis, rec);
|
||||||
ctrl->pending[ctrl->pending_len++] = axis;
|
ctrl->pending[ctrl->pending_len++] = *axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
recs->head.len = 0;
|
recs->head.len = 0;
|
||||||
|
|
|
@ -114,9 +114,9 @@ usize TerminalPrint(struct Terminal *term, char *out, usize n)
|
||||||
usize len = 7;
|
usize len = 7;
|
||||||
memcpy(out, "\x1b[H\x1b[0m", 7);
|
memcpy(out, "\x1b[H\x1b[0m", 7);
|
||||||
|
|
||||||
|
usize i = 0;
|
||||||
for (usize y = 0; y < term->hgt; y++) {
|
for (usize y = 0; y < term->hgt; y++) {
|
||||||
for (usize x = 0; x < term->wid; x++) {
|
for (usize x = 0; x < term->wid; x++, i++) {
|
||||||
usize i = y * term->wid + x;
|
|
||||||
struct Char4 *ch4 = &term->buf[i];
|
struct Char4 *ch4 = &term->buf[i];
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
|
@ -2,36 +2,69 @@
|
||||||
|
|
||||||
|
|
||||||
struct Fumotris {
|
struct Fumotris {
|
||||||
struct TetrMap board;
|
struct Tetra board;
|
||||||
struct TetrMap piece;
|
struct Tetra piece;
|
||||||
|
nsec timer;
|
||||||
|
bool is_ground;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void FumotrisStart(void *inst_arg, void *game_arg)
|
void FumotrisStart(struct FumoInstance *inst, struct Fumotris *fumo)
|
||||||
{
|
{
|
||||||
struct FumoInstance *inst = inst_arg;
|
|
||||||
struct Fumotris *game = game_arg;
|
|
||||||
|
|
||||||
ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g);
|
ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g);
|
||||||
|
|
||||||
CreateTetrMap(&game->board, 10, 10);
|
CreateTetra(&fumo->board, 10, 10);
|
||||||
CreateTetrMap(&game->piece, 3, 3);
|
SetTetra(&fumo->piece, T, 3, 3, 0, 0);
|
||||||
game->piece.blks = T;
|
fumo->timer = 0;
|
||||||
|
fumo->is_ground = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FumotrisUpdate(void *inst_arg, void *game_arg)
|
void FumotrisUpdate(struct FumoInstance *inst, struct Fumotris *fumo)
|
||||||
{
|
{
|
||||||
struct FumoInstance *inst = inst_arg;
|
i16 horizontal = 0;
|
||||||
struct Fumotris *game = game_arg;
|
|
||||||
|
|
||||||
if (inst->ctrl.axes[LEFT].is_down)
|
if (inst->ctrl.axes[LEFT].is_down)
|
||||||
game->piece.x -= 1;
|
horizontal -= 1;
|
||||||
|
|
||||||
if (inst->ctrl.axes[RIGHT].is_down)
|
if (inst->ctrl.axes[RIGHT].is_down)
|
||||||
game->piece.x += 1;
|
horizontal += 1;
|
||||||
|
TetraMove(&fumo->piece, &fumo->board, horizontal, 0);
|
||||||
|
|
||||||
TetrMapDraw(&game->board, &inst->term);
|
|
||||||
TetrMapDraw(&game->piece, &inst->term);
|
if (inst->ctrl.axes[SOFT_DROP].is_down)
|
||||||
|
TetraMove(&fumo->piece, &fumo->board, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
|
if (inst->ctrl.axes[HARD_DROP].is_down) {
|
||||||
|
while (TetraMove(&fumo->piece, &fumo->board, 0, 1));
|
||||||
|
|
||||||
|
fumo->timer = 0;
|
||||||
|
TetraOverlay(&fumo->piece, &fumo->board);
|
||||||
|
SetTetra(&fumo->piece, I, 4, 4, 0, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fumo->timer += inst->frametime;
|
||||||
|
while (fumo->timer > 5e8) {
|
||||||
|
fumo->timer -= 5e8;
|
||||||
|
|
||||||
|
if (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) {
|
||||||
|
if (!fumo->is_ground) {
|
||||||
|
fumo->is_ground = true;
|
||||||
|
} else {
|
||||||
|
TetraOverlay(&fumo->piece, &fumo->board);
|
||||||
|
SetTetra(&fumo->piece, I, 4, 4, 0, 0);
|
||||||
|
|
||||||
|
fumo->is_ground = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FumotrisDraw(struct FumoInstance *inst, struct Fumotris *fumo)
|
||||||
|
{
|
||||||
|
TetraTerminalClear(&fumo->board, &inst->term);
|
||||||
|
TetraTerminalDraw(&fumo->board, &inst->term);
|
||||||
|
TetraTerminalDraw(&fumo->piece, &inst->term);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "fumocommon.h"
|
#include "fumocommon.h"
|
||||||
#include "fumoengine.h"
|
#include "fumoengine.h"
|
||||||
#include "tetr.h"
|
#include "tetra.h"
|
||||||
|
|
||||||
#define BINDS_N 12
|
#define BINDS_N 12
|
||||||
|
|
||||||
|
@ -22,6 +22,12 @@ enum FumotrisControls {
|
||||||
MOUSE
|
MOUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TetraTemplate {
|
||||||
|
u8 *blks;
|
||||||
|
u16 wid;
|
||||||
|
u16 hgt;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
u16 controls_g[BINDS_N] = {
|
u16 controls_g[BINDS_N] = {
|
||||||
LEFT,
|
LEFT,
|
||||||
|
@ -74,44 +80,72 @@ u16 types_g[BINDS_N] = {
|
||||||
JOYSTICK
|
JOYSTICK
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 I[16] = {
|
struct TetraTemplate I = {
|
||||||
0, 0, 0, 0,
|
.blks = &(u8) {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
1, 1, 1, 1,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0
|
1, 1, 1, 1,
|
||||||
|
0, 0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 4,
|
||||||
|
.hgt = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 O[4] = {
|
struct TetraTemplate O = {
|
||||||
1, 1,
|
.blks = &(u8) {
|
||||||
1, 1
|
1, 1,
|
||||||
|
1, 1
|
||||||
|
},
|
||||||
|
.wid = 2,
|
||||||
|
.hgt = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 T[9] = {
|
struct TetraTemplate T = {
|
||||||
0, 1, 0,
|
.blks = &(u8) {
|
||||||
1, 1, 1,
|
0, 1, 0,
|
||||||
0, 0, 0
|
1, 1, 1,
|
||||||
|
0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 3,
|
||||||
|
.hgt = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 S[9] = {
|
struct TetraTemplate S = {
|
||||||
0, 1, 1,
|
.blks = &(u8) {
|
||||||
1, 1, 0,
|
0, 1, 1,
|
||||||
0, 0, 0
|
1, 1, 0,
|
||||||
|
0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 3,
|
||||||
|
.hgt = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 Z[9] = {
|
struct TetraTemplate Z = {
|
||||||
1, 1, 0,
|
.blks = &(u8) {
|
||||||
0, 1, 1,
|
1, 1, 0,
|
||||||
0, 0, 0
|
0, 1, 1,
|
||||||
|
0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 3,
|
||||||
|
.hgt = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 J[9] = {
|
struct TetraTemplate J = {
|
||||||
1, 0, 0,
|
.blks = &(u8) {
|
||||||
1, 1, 1,
|
1, 0, 0,
|
||||||
0, 0, 0
|
1, 1, 1,
|
||||||
|
0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 3,
|
||||||
|
.hgt = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 L[9] = {
|
struct TetraTemplate L = {
|
||||||
0, 0, 1,
|
.blks = &(u8) {
|
||||||
1, 1, 1,
|
0, 0, 1,
|
||||||
0, 0, 0
|
1, 1, 1,
|
||||||
|
0, 0, 0
|
||||||
|
},
|
||||||
|
.wid = 3,
|
||||||
|
.hgt = 3
|
||||||
};
|
};
|
|
@ -1,77 +0,0 @@
|
||||||
#include "tetr.h"
|
|
||||||
|
|
||||||
|
|
||||||
bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt)
|
|
||||||
{
|
|
||||||
u8 *blks = calloc(wid * hgt, sizeof(u8));
|
|
||||||
|
|
||||||
if (blks == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*map = (struct TetrMap) {
|
|
||||||
.wid = wid,
|
|
||||||
.hgt = hgt,
|
|
||||||
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
|
|
||||||
.rot = 0,
|
|
||||||
|
|
||||||
.blks = blks
|
|
||||||
};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeTetrMap(struct TetrMap *map)
|
|
||||||
{
|
|
||||||
free(map->blks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TetrMapDraw(struct TetrMap *map, struct Terminal *term)
|
|
||||||
{
|
|
||||||
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
|
||||||
|
|
||||||
for (usize y = 0; y < map->hgt; y++) {
|
|
||||||
for (usize x = 0; x < map->wid; x++) {
|
|
||||||
usize map_i = y * map->wid + x;
|
|
||||||
usize term_i = (y + map->y) * term->wid + (x + map->x) * 2;
|
|
||||||
|
|
||||||
struct Char4 *block = term->buf + term_i;
|
|
||||||
|
|
||||||
if (map->blks[map_i] == 0) {
|
|
||||||
block[0].ch = '(';
|
|
||||||
block[1].ch = ')';
|
|
||||||
} else {
|
|
||||||
block[0].ch = '[';
|
|
||||||
block[1].ch = ']';
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 fg = blk_colors[map->blks[map_i]];
|
|
||||||
block[0].color.fg = fg;
|
|
||||||
block[1].color.fg = fg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
for (size_t y = piece->y + dy; y < piece->y + piece->hgt + dy; y++) {
|
|
||||||
for (size_t x = piece->x + dx; x < piece->x + piece->wid + dx; x++) {
|
|
||||||
if(piece->blks[i] == 0)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
if(y >= board->hgt or x >= board->wid)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
size_t board_i = y * board->wid + x;
|
|
||||||
if(board->blks[board_i] != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
next:
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "fumocommon.h"
|
|
||||||
#include "terminal.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct TetrMap {
|
|
||||||
usize wid;
|
|
||||||
usize hgt;
|
|
||||||
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
u8f rot;
|
|
||||||
|
|
||||||
u8 *blks;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt);
|
|
||||||
|
|
||||||
void FreeTetrMap(struct TetrMap *map);
|
|
||||||
|
|
||||||
void TetrMapDraw(struct TetrMap *map, struct Terminal *term);
|
|
||||||
|
|
||||||
bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy);
|
|
115
source/fumotris/tetra.c
Normal file
115
source/fumotris/tetra.c
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#include "tetra.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt)
|
||||||
|
{
|
||||||
|
u8 *blks = calloc(wid * hgt, sizeof(u8));
|
||||||
|
|
||||||
|
if (blks == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
map->blks = blks;
|
||||||
|
map->wid = wid;
|
||||||
|
map->hgt = hgt;
|
||||||
|
|
||||||
|
map->x = 0;
|
||||||
|
map->y = 0;
|
||||||
|
map->rot = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeTetra(struct Tetra *tetra)
|
||||||
|
{
|
||||||
|
free(tetra->blks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTetra(struct Tetra *map, u8 *blks, u16 wid, u16 hgt, i16 x, i16 y)
|
||||||
|
{
|
||||||
|
map->blks = blks;
|
||||||
|
map->wid = wid;
|
||||||
|
map->hgt = hgt;
|
||||||
|
|
||||||
|
map->x = x;
|
||||||
|
map->y = y;
|
||||||
|
map->rot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
|
||||||
|
{
|
||||||
|
if (TetraIsCollision(piece, board, dx, dy))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
piece->x += dx;
|
||||||
|
piece->y += dy;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
|
||||||
|
{
|
||||||
|
i16 x_start = piece->x + dx;
|
||||||
|
i16 y_start = piece->y + dy;
|
||||||
|
|
||||||
|
usize i = 0;
|
||||||
|
for (i16 y = y_start; y < y_start + piece->hgt; y++) {
|
||||||
|
for (i16 x = x_start; x < x_start + piece->wid; x++, i++) {
|
||||||
|
if(piece->blks[i] == 0)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TetraTerminalClear(struct Tetra *board, struct Terminal *term)
|
||||||
|
{
|
||||||
|
for (usize i = 0; i < board->wid * board->hgt; i++) {
|
||||||
|
struct Char4 *block = term->buf + i * 2;
|
||||||
|
|
||||||
|
block[0] = (struct Char4) { .ch = '(', .color.fg = 8 };
|
||||||
|
block[1] = (struct Char4) { .ch = ')', .color.fg = 8 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TetraTerminalDraw(struct Tetra *tetra, struct Terminal *term)
|
||||||
|
{
|
||||||
|
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
||||||
|
|
||||||
|
usize i = 0;
|
||||||
|
for (usize y = 0; y < tetra->hgt; y++) {
|
||||||
|
for (usize x = 0; x < tetra->wid; x++, i++) {
|
||||||
|
if (tetra->blks[i] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
usize term_i = (y + tetra->y) * term->wid + (x + tetra->x) * 2;
|
||||||
|
struct Char4 *block = term->buf + term_i;
|
||||||
|
|
||||||
|
u8 fg = blk_colors[tetra->blks[i]];
|
||||||
|
block[0] = (struct Char4) { .ch = '[', .color.fg = fg };
|
||||||
|
block[1] = (struct Char4) { .ch = ']', .color.fg = fg };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TetraOverlay(struct Tetra *piece, struct Tetra *board)
|
||||||
|
{
|
||||||
|
usize i = 0;
|
||||||
|
for (usize y = piece->y; y < piece->y + piece->hgt; y++) {
|
||||||
|
for (usize x = piece->x; x < piece->x + piece->wid; x++, i++) {
|
||||||
|
if(piece->blks[i] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
board->blks[board->wid * y + x] = piece->blks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
source/fumotris/tetra.h
Normal file
33
source/fumotris/tetra.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "fumocommon.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct Tetra {
|
||||||
|
u8 *blks;
|
||||||
|
|
||||||
|
u16 wid;
|
||||||
|
u16 hgt;
|
||||||
|
|
||||||
|
i16 x;
|
||||||
|
i16 y;
|
||||||
|
|
||||||
|
u8f rot;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt);
|
||||||
|
|
||||||
|
void FreeTetra(struct Tetra *map);
|
||||||
|
|
||||||
|
void SetTetra(struct Tetra *map, u8 *blks, u16 wid, u16 hgt, i16 x, i16 y);
|
||||||
|
|
||||||
|
void TetraTerminalClear(struct Tetra *board, struct Terminal *term);
|
||||||
|
|
||||||
|
void TetraTerminalDraw(struct Tetra *map, struct Terminal *term);
|
||||||
|
|
||||||
|
bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy);
|
||||||
|
|
||||||
|
bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy);
|
||||||
|
|
||||||
|
void TetraOverlay(struct Tetra *piece, struct Tetra *board);
|
Loading…
Reference in a new issue