ALMOST WORKING

AHH
This commit is contained in:
Julia 2024-05-15 17:10:47 -05:00
parent e3ed625feb
commit 1c4197e864
36 changed files with 366 additions and 307 deletions

View file

@ -60,7 +60,8 @@
"stdbool.h": "c",
"fumoengine.h": "c",
"event.h": "c",
"fumocommon.h": "c"
"fumocommon.h": "c",
"terminal.h": "c"
}
}
}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
["1d6bdf7e8de4ac751252b67027e5d57e", "9df90eabc8908cac60aa774d335a106c", "1420f33d62a8ed8429c8f1a96f1ab33e", "dc6df72158812bc9f6ed484a4cfb046b", "6669fc7fcffc77563f1315cb7710ec82", "333c7211bb2c72ad321495f53d11bff0", "088145536b04ef82517eb93630888dff", "f61af2abe56cd6881a830ae6222483e9", "e09059d1f20c982c6c42a61a0754c102", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "330b6f9493d091e7c340c1434b6f80b4", "e38bd5ea2b554a21849158242a2add8e"]
["f315479de287d3cccdfa665c1e8c58bd", "7d30e573f96a566ed9510833b95d5520", "0eaec40fe47b9cb31ff5a70f7bfee15a", "72e1b62b85eac654ed094a8ecf009416", "5ce28b2bf9d7c5750ea290f80fbd1264", "0d65896ce70d098bdf4cb3587ca74508", "f6611a0f07f78cc4fd52df267e0d3d25", "9f0597e7cacc7c918163affc5f3d9841", "cd22e396133a64303ecae95280f8ba1a", "7d7451ae7d88f4d1f84055180f9e84a7", "29f6d19bcc5a1897b220a192ef6fc3cc", "1d88301163b019760c3dc8396ce2aa4b", "ec4912a725a2bc606bd76ba34159435c"]

View file

@ -1 +1 @@
[]
["4aa55dfc1d038e75d0efbf277e6033a4"]

BIN
debug.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -2,11 +2,16 @@
#include <time.h>
usize min_usize(usize a, usize b)
usize min(usize a, usize b)
{
return a < b ? a : b;
}
usize max(usize a, usize b)
{
return a > b ? a : b;
}
nsec TimeNow()
{
struct timespec ts;

View file

@ -40,7 +40,8 @@ typedef int_fast64_t i64f;
typedef u64 nsec;
size_t min_usize(usize a, usize b);
size_t min(usize a, usize b);
size_t max(usize a, usize b);
nsec TimeNow();
double TimeNowD();

View file

@ -2,16 +2,35 @@
#include "platform.h"
const VectorT FUMOCO_T = VECTOR_T(struct FumoCoroutine);
void Panic(char *message)
{
printf(message);
exit(1);
}
bool CreateFumoInstance(struct FumoInstance *instance)
bool CoroutineAdd(struct Instance *inst, void *state, coroutine_handler callback)
{
return VectorAdd(&inst->coroutines, &(struct Coroutine) {
.callback = callback,
.state = state,
.next_scheduled = inst->time
});
}
void CoroutineTryInvoke(struct Instance *inst, struct Coroutine *co)
{
while (inst->time > co->next_scheduled) {
nsec wait = co->callback(inst, co->state);
if (wait == 0) {
co->next_scheduled = inst->time;
break;
} else {
co->next_scheduled += wait;
}
}
}
bool CreateFumoInstance(struct Instance *instance)
{
if (!PlatformInit())
Panic("Platform failed to initialize");
@ -22,27 +41,27 @@ bool CreateFumoInstance(struct FumoInstance *instance)
if (!CreateInputThread(&instance->input_hand))
Panic("Input handle failed to initialize");
if (!CreateTerminal(&instance->term, 20, 10))
Panic("Out of memory");
if (!CreateEvent(&instance->on_start))
Panic("Out of memory");
if (!CreateEvent(&instance->on_update))
Panic("Out of memory");
if (!CreateEvent(&instance->on_draw))
Panic("Out of memory");
if (!CreateVector(&instance->coroutines, sizeof(struct Coroutine)))
Panic("Out of memory");
instance->time = TimeNow();
return true;
}
bool FumoInstanceRun(struct FumoInstance *inst)
bool FumoInstanceRun(struct Instance *inst)
{
EventInvoke(&inst->on_start, inst);
usize buf_n = TerminalMaxOut(&inst->term);
char *buf = malloc(buf_n);
while (true) {
// Time
nsec now = TimeNow();
@ -60,25 +79,14 @@ bool FumoInstanceRun(struct FumoInstance *inst)
// Update
EventInvoke(&inst->on_update, inst);
for (usize i = 0; i < inst->coroutines.len; i++) {
struct FumoCoroutine *co = VectorGet(FUMOCO_T, &inst->coroutines, i);
co->callback();
CoroutineTryInvoke(inst, VectorGet(&inst->coroutines, i));
}
// Draw
EventInvoke(&inst->on_draw, inst);
TerminalPrint(&inst->term, buf, buf_n);
puts(buf);
//_sleep(100);
}
}
bool CoroutineAdd(struct FumoInstance *inst, handler callback, nsec period)
{
return VectorAdd(FUMOCO_T, &inst->coroutines, &(struct FumoCoroutine) {
.callback = callback,
.timer = 0,
.period = period
});
}

View file

@ -3,20 +3,21 @@
#include "event.h"
#include "fumocommon.h"
#include "input.h"
#include "terminal.h"
#include "vector.h"
struct FumoCoroutine {
handler callback;
nsec timer;
nsec period;
typedef nsec (*coroutine_handler)(void *state, void *instance);
struct Coroutine {
coroutine_handler callback;
void *state;
nsec next_scheduled;
};
struct FumoInstance {
struct Instance {
struct Controller ctrl;
struct InputHandle input_hand;
struct Terminal term;
struct Event on_start;
struct Event on_update;
@ -31,6 +32,10 @@ struct FumoInstance {
void Panic(char *message);
bool CreateFumoInstance(struct FumoInstance *game);
bool CoroutineAdd(struct Instance *inst, void *state, coroutine_handler callback);
bool FumoInstanceRun(struct FumoInstance *game);
void CoroutineTryInvoke(struct Instance *inst, struct Coroutine *co);
bool CreateFumoInstance(struct Instance *game);
bool FumoInstanceRun(struct Instance *game);

View file

@ -1,21 +1,24 @@
#include "dictionary.h"
#include <stdalign.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool CreateDictionary(DictT T, struct Dictionary *dict)
bool CreateDictionary(struct Dictionary *dict, usize value_size)
{
void *bkts = calloc(16, T->BKT_SIZE);
void *bkts = calloc(16, value_size);
if (bkts == nullptr)
return false;
*dict = (struct Dictionary) {
.filled = 0,
.capacity = 16,
.bkts = bkts
};
dict->value_size = value_size;
dict->value_offset = max(alignof(u32), alignof(u8[dict->value_size]));
dict->bkt_size = dict->value_offset + value_size;
dict->filled = 0;
dict->capacity = 16;
dict->bkts = bkts;
return true;
}
@ -25,45 +28,45 @@ void FreeDictionary(struct Dictionary *dict)
free(dict->bkts);
}
void *index_bkt(DictT T, struct Dictionary *dict, usize i)
void *index_bkt(struct Dictionary *dict, usize i)
{
return (u8 *)dict->bkts + i * T->BKT_SIZE;
return (u8 *)dict->bkts + i * dict->bkt_size;
}
u32 *get_key(DictT T, void *bkt)
u32 *get_key(struct Dictionary *dict, void *bkt)
{
return (u32 *)bkt;
}
void *get_val(DictT T, void *bkt)
void *get_value_ptr(struct Dictionary *dict, void *bkt)
{
return (u8 *)bkt + T->VAL_OFS;
return (u8 *)bkt + dict->value_offset;
}
void set_bkt(DictT T, void *bkt, u32 key, void *val)
void set_bkt(struct Dictionary *dict, void *bkt, u32 key, void *value_ptr)
{
*get_key(T, bkt) = key;
memcpy(get_val(T, bkt), val, T->VAL_SIZE);
*get_key(dict, bkt) = key;
memcpy(get_value_ptr(dict, bkt), value_ptr, dict->value_size);
}
void *probe_bkt(DictT T, struct Dictionary *dict, usize index, u32 key)
void *probe_bkt(struct Dictionary *dict, usize index, u32 key)
{
for (usize i = 0; i < dict->capacity; i++) {
void *bkt = index_bkt(T, dict, (index + i) % dict->capacity);
void *bkt = index_bkt(dict, (index + i) % dict->capacity);
if (*get_key(T, bkt) == key)
if (*get_key(dict, bkt) == key)
return bkt;
}
return nullptr;
}
void *probe_empty_bkt(DictT T, struct Dictionary *dict, usize index, u32 key)
void *probe_empty_bkt(struct Dictionary *dict, usize index, u32 key)
{
for (usize i = 0; i < dict->capacity; i++) {
void *bkt = index_bkt(T, dict, (index + i) % dict->capacity);
void *bkt = index_bkt(dict, (index + i) % dict->capacity);
u32 k = *get_key(T, bkt);
u32 k = *get_key(dict, bkt);
if (k == 0 or k == key)
return bkt;
}
@ -71,25 +74,25 @@ void *probe_empty_bkt(DictT T, struct Dictionary *dict, usize index, u32 key)
return nullptr;
}
void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key)
void *DictionaryFind(struct Dictionary *dict, u32 key)
{
usize index = key % dict->capacity;
void *bkt = probe_bkt(T, dict, index, key);
void *bkt = probe_bkt(dict, index, key);
if (bkt == nullptr)
return false;
return get_val(T, bkt);
return get_value_ptr(dict, bkt);
}
void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val)
void *DictionarySet(struct Dictionary *dict, u32 key, void *value_ptr)
{
usize index = key % dict->capacity;
void *bkt = probe_empty_bkt(T, dict, index, key);
void *bkt = probe_empty_bkt(dict, index, key);
if (*get_key(T, bkt) == 0)
set_bkt(T, bkt, key, val);
if (*get_key(dict, bkt) == 0)
set_bkt(dict, bkt, key, value_ptr);
return bkt;
}

View file

@ -1,31 +1,21 @@
#pragma once
#include "fumocommon.h"
#define DICT_T(DICT_VAL_T) \
(&(struct DictT) { \
.VAL_SIZE = sizeof(DICT_VAL_T), \
.VAL_OFS = offsetof(struct { u32 k; DICT_VAL_T v; }, v), \
.BKT_SIZE = sizeof(struct { u32 k; DICT_VAL_T v; }) \
}) \
typedef const struct DictT {
usize VAL_SIZE;
usize VAL_OFS;
usize BKT_SIZE;
} *const DictT;
struct Dictionary {
usize value_size;
usize value_offset;
usize bkt_size;
usize filled;
usize capacity;
void *bkts;
};
bool CreateDictionary(DictT T, struct Dictionary *dict);
bool CreateDictionary(struct Dictionary *dict, usize value_size);
void FreeDictionary(struct Dictionary *dict);
void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key);
void *DictionaryFind(struct Dictionary *dict, u32 key);
void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val);
void *DictionarySet(struct Dictionary *dict, u32 key, void *value_ptr);

View file

@ -22,7 +22,7 @@ void FreeEvent(struct Event *event)
free(event->methods);
}
bool EventAdd(struct Event *event, handler callback, void *instance)
bool EventAdd(struct Event *event, void *instance, handler callback)
{
if (event->len == event->capacity) {
usize new_size = event->capacity * 2 * sizeof(struct Method);

View file

@ -21,6 +21,6 @@ struct Event {
bool CreateEvent(struct Event *event);
bool EventAdd(struct Event *event, handler callback, void *instance);
bool EventAdd(struct Event *event, void *instance, handler callback);
void EventInvoke(struct Event *event, void *state);

View file

@ -37,7 +37,7 @@ void RingBufferTransfer(
struct RingBufferHead *dest,
struct RingBufferHead *tmp
) {
usize copy_max = min_usize(T->LEN - dest->len, tmp->len);
usize copy_max = min(T->LEN - dest->len, tmp->len);
for (usize i = 0; i < copy_max; i++) {
void *to = RingBufferGet(T, dest, dest->len + i);
@ -55,7 +55,7 @@ usize RingBufferOut(
void *dest,
struct RingBufferHead *src
) {
usize copy_max = min_usize(n, src->len);
usize copy_max = min(n, src->len);
for (usize i = 0; i < copy_max; i++) {
void *to = (u8 *)dest + i * T->SIZE;

View file

@ -3,13 +3,15 @@
#include <string.h>
bool CreateVector(VectorT T, struct Vector *vec)
bool CreateVector(struct Vector *vec, usize value_size)
{
void *array = malloc(16 * T->SIZE);
void *array = malloc(16 * value_size);
if (array == nullptr)
return false;
vec->value_size = value_size;
vec->len = 0;
vec->capacity = 16;
vec->array = array;
@ -22,16 +24,16 @@ void FreeVector(struct Vector *vec)
free(vec->array);
}
void *VectorGet(VectorT T, struct Vector *vec, usize i)
void *VectorGet(struct Vector *vec, usize i)
{
return (u8 *)vec->array + i * T->SIZE;
return (u8 *)vec->array + i * vec->value_size;
}
bool VectorAdd(VectorT T, struct Vector *vec, void *item)
bool VectorAdd(struct Vector *vec, void *item)
{
if (vec->len == vec->capacity) {
usize new_capacity = vec->capacity * 2;
void *new_array = realloc(vec->array, new_capacity * T->SIZE);
void *new_array = realloc(vec->array, new_capacity * vec->value_size);
if (new_array == nullptr)
return false;
@ -39,7 +41,7 @@ bool VectorAdd(VectorT T, struct Vector *vec, void *item)
vec->capacity = new_capacity;
}
memcpy(VectorGet(T, vec, vec->len++), item, T->SIZE);
memcpy(VectorGet(vec, vec->len++), item, vec->value_size);
return true;
}

View file

@ -1,26 +1,19 @@
#include "fumocommon.h"
#define VECTOR_T(VEC_ITEM_T) \
(&(struct VectorT) { \
.SIZE = sizeof(VEC_ITEM_T) \
}) \
typedef const struct VectorT {
usize SIZE;
} *const VectorT;
struct Vector {
usize value_size;
usize len;
usize capacity;
void *array;
};
bool CreateVector(VectorT T, struct Vector *vec);
bool CreateVector(struct Vector *vec, usize value_size);
void FreeVector(struct Vector *vec);
void *VectorGet(VectorT T, struct Vector *vec, usize i);
void *VectorGet(struct Vector *vec, usize i);
bool VectorAdd(VectorT T, struct Vector *vec, void *item);
bool VectorAdd(struct Vector *vec, void *item);

View file

@ -4,16 +4,13 @@
#define INIT_SIZE 16
DictT BIND_T = DICT_T(struct InputAxis *);
bool CreateController(struct Controller *ctrl)
{
struct InputAxis *axes = calloc(16, sizeof(struct InputAxis));
if (axes == nullptr)
return false;
if (!CreateDictionary(BIND_T, &ctrl->binds))
if (!CreateDictionary(&ctrl->binds, sizeof(struct InputAxis*)))
return false;
ctrl->pending_len = 0;
@ -39,7 +36,7 @@ bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type)
u32 hash = hash_bind(code, type);
struct InputAxis *axis = &ctrl->axes[control];
struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, &axis);
struct InputAxis **bind = DictionarySet(&ctrl->binds, hash, &axis);
if (bind == nullptr)
return false;
@ -92,7 +89,7 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
struct InputRecord *rec = recs->buf + i;
u32 hash = hash_bind(rec->code, rec->type);
struct InputAxis **axis = DictionaryFind(BIND_T, &ctrl->binds, hash);
struct InputAxis **axis = DictionaryFind(&ctrl->binds, hash);
if (axis == nullptr)
continue;
@ -103,43 +100,3 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
recs->head.len = 0;
}
/*int main()
{
struct Controller ctrl;
if (!CreateController(&ctrl))
return 1;
ControllerMap(&ctrl, 123, 111, BUTTON);
ControllerMap(&ctrl, 0, 8, BUTTON);
struct RecordBuffer recs = { .head.len = 0, .head.start = 0 };
recs.buf[recs.head.len++] = (struct InputRecord) {
.but.value = 69,
.is_down = true,
.id.bind = 111,
.id.type = BUTTON
};
recs.buf[recs.head.len++] = (struct InputRecord) {
.but.value = 1000,
.is_down = true,
.id.bind = 8,
.id.type = BUTTON
};
ControllerPoll(&ctrl, &recs);
struct InputAxis *a = ControllerGet(&ctrl, 123, BUTTON);
printf("%u\n", a->but.value);
struct InputAxis *b = ControllerGet(&ctrl, 0, BUTTON);
printf("%u\n", b->but.value);
printf("success");
return 0;
}*/

View file

@ -5,26 +5,30 @@
#define MAX_CH4_LEN 11
usize TerminalMaxOut(struct Terminal *term)
usize TerminalMaxOut(usize wid, usize hgt)
{
return RESET_STR_LEN
+ MAX_CH4_LEN * term->wid * term->hgt
+ term->hgt
+ MAX_CH4_LEN * wid * hgt
+ hgt
+ 1;
}
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt)
{
struct Char4 *ch4s = calloc(wid * hgt, sizeof(struct Char4));
if (ch4s == nullptr)
return false;
*term = (struct Terminal) {
.wid = wid,
.hgt = hgt,
char *str = malloc(TerminalMaxOut(wid, hgt));
if (str == nullptr)
return false;
.buf = ch4s
*term = (struct Terminal) {
.buf = ch4s,
.str = str,
.wid = wid,
.hgt = hgt
};
return true;
@ -107,12 +111,12 @@ usize ch4_dif_to_str(char *out, struct Color4 *dif, struct Char4 *ch4)
return len;
}
usize TerminalPrint(struct Terminal *term, char *out, usize n)
usize TerminalPrint(struct Terminal *term)
{
struct Color4 dif = { 0, 0 };
usize len = 7;
memcpy(out, "\x1b[H\x1b[0m", 7);
memcpy(term->str, "\x1b[H\x1b[0m", 7);
usize i = 0;
for (usize y = 0; y < term->hgt; y++) {
@ -124,11 +128,11 @@ usize TerminalPrint(struct Terminal *term, char *out, usize n)
ch4->ch = '#';
// DEBUG
len += ch4_dif_to_str(out + len, &dif, ch4);
len += ch4_dif_to_str(term->str + len, &dif, ch4);
}
out[len++] = '\n';
term->str[len++] = '\n';
}
out[len] = 0;
term->str[len] = 0;
return len;
}

View file

@ -1,10 +1,6 @@
#pragma once
#include <iso646.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "fumocommon.h"
@ -19,16 +15,18 @@ struct Char4 {
};
struct Terminal {
struct Char4 *buf;
char *str;
usize wid;
usize hgt;
struct Char4 *buf;
};
usize TerminalMaxOut(struct Terminal *term);
usize TerminalMaxOut(usize wid, usize hgt);
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt);
void FreeTerminal(struct Terminal *term);
usize TerminalPrint(struct Terminal *term, char *out, usize n);
usize TerminalPrint(struct Terminal *term);

View file

@ -3,99 +3,143 @@
struct Fumotris {
struct Terminal term;
struct TetraTemplate *bag[7];
usize bag_i;
struct Tetra board;
struct Tetra piece;
bool is_ground;
nsec last_moved;
nsec last_dropped;
};
struct TetraTemplate *bag[7] = { &I, &O, &T, &S, &Z, &J, &L };
usize bag_i = 0;
void shuffle()
void shuffle(struct Fumotris *fumo)
{
for (usize i = 6; i >= 0; i--) {
for (usize i = 6; i > 0; i--) {
usize swap = rand() % i;
struct TetraTemplate *tmp = bag[swap];
bag[swap] = bag[i];
bag[i] = tmp;
struct TetraTemplate *tmp = fumo->bag[swap];
fumo->bag[swap] = fumo->bag[i];
fumo->bag[i] = tmp;
}
}
void place_piece(struct Fumotris *fumo)
void check_clear()
{
}
void place(struct Fumotris *fumo)
{
TetraOverlay(&fumo->piece, &fumo->board);
SetTetra(&fumo->piece, bag[bag_i++], 0, 0);
if (bag_i == 7) {
shuffle();
bag_i = 0;
usize lines_cleared = fumo->piece.hgt;
for (usize y = fumo->piece.y; y < fumo->piece.y + fumo->piece.hgt; y++) {
for (usize x = 0; x < fumo->board.wid; x++) {
if (fumo->board.blks[fumo->board.wid * y + x] == 0) {
lines_cleared -= 1;
break;
}
}
}
TetraSet(&fumo->piece, fumo->bag[fumo->bag_i++]);
if (fumo->bag_i == 7) {
shuffle(fumo);
fumo->bag_i = 0;
}
}
i16 get_horizontal(struct Controller *ctrl)
{
return (-(i16)ctrl->axes[LEFT].is_down) + ctrl->axes[RIGHT].is_down;
return (-(i16)ctrl->axes[LEFT].is_held) + ctrl->axes[RIGHT].is_held;
}
void FumotrisStart(struct FumoInstance *inst, struct Fumotris *fumo)
void FumotrisStart(struct Instance *inst, struct Fumotris *fumo)
{
ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g);
CreateTetra(&fumo->board, 10, 10);
ControllerBindMulti(&inst->ctrl, BINDS_N, CONTROLS, CODES, TYPES);
CreateTerminal(&fumo->term, 20, 20);
for (usize i = 0; i < 7; i++)
fumo->bag[i] = templates[i];
fumo->bag_i = 1;
CreateTetra(&fumo->board, 10, 20);
TetraSet(&fumo->piece, fumo->bag[0]);
fumo->is_ground = false;
SetTetra(&fumo->piece, bag[bag_i++], 0, 0);
fumo->last_moved = 0;
fumo->last_dropped = 0;
}
void FumotrisUpdate(struct FumoInstance *inst, struct Fumotris *fumo)
void FumotrisUpdate(struct Instance *inst, struct Fumotris *fumo)
{
TetraMove(&fumo->piece, &fumo->board, get_horizontal(&inst->ctrl), 0);
i16 horizontal = get_horizontal(&inst->ctrl);
if (inst->ctrl.axes[SOFT_DROP].is_down) {
if (horizontal != 0 and fumo->last_moved < inst->time) {
fumo->last_moved = inst->time + 5e7;
TetraMove(&fumo->piece, &fumo->board, horizontal, 0);
}
if (inst->ctrl.axes[ROTATE_CCW].is_down)
TetraRotate(&fumo->piece, &fumo->board, 1);
if (inst->ctrl.axes[ROTATE_CW].is_down)
TetraRotate(&fumo->piece, &fumo->board, -1);
if (inst->ctrl.axes[SOFT_DROP].is_held and fumo->last_dropped < inst->time) {
fumo->last_dropped = inst->time + 5e7;
TetraMove(&fumo->piece, &fumo->board, 0, 1);
}
if (inst->ctrl.axes[HARD_DROP].is_down) {
while (TetraMove(&fumo->piece, &fumo->board, 0, 1));
place_piece(fumo);
place(fumo);
}
}
void FumotrisOnFall(struct FumoInstance *inst, struct Fumotris *fumo)
nsec FumotrisFall(struct Instance *inst, struct Fumotris *fumo)
{
if (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) {
if (!fumo->is_ground)
fumo->is_ground = true;
else
place_piece(fumo);
place(fumo);
}
return 5e8;
}
void FumotrisDraw(struct FumoInstance *inst, struct Fumotris *fumo)
void FumotrisDraw(struct Instance *inst, struct Fumotris *fumo)
{
TetraTerminalClear(&fumo->board, &inst->term);
TetraTerminalDraw(&fumo->board, &inst->term);
TetraTerminalDraw(&fumo->piece, &inst->term);
TetraTerminalClear(&fumo->board, &fumo->term);
TetraTerminalDraw(&fumo->board, &fumo->term);
TetraTerminalDraw(&fumo->piece, &fumo->term);
TerminalPrint(&fumo->term);
puts(fumo->term.str);
}
int main()
{
struct FumoInstance inst;
struct Instance inst;
CreateFumoInstance(&inst);
struct Fumotris game;
EventAdd(&inst.on_start, FumotrisStart, &game);
EventAdd(&inst.on_update, FumotrisUpdate, &game);
EventAdd(&inst.on_draw, FumotrisDraw, &game);
EventAdd(&inst.on_start, &game, FumotrisStart);
EventAdd(&inst.on_update, &game, FumotrisUpdate);
EventAdd(&inst.on_draw, &game, FumotrisDraw);
VectorAdd(FUMOCO_T, &inst.coroutines, );
CoroutineAdd(&inst, &game, FumotrisFall);
FumoInstanceRun(&inst);

View file

@ -1,5 +1,6 @@
#include "fumocommon.h"
#include "fumoengine.h"
#include "terminal.h"
#include "tetra.h"
#define BINDS_N 12
@ -23,7 +24,7 @@ enum FumotrisControls {
};
u16 controls_g[BINDS_N] = {
u16 CONTROLS[BINDS_N] = {
LEFT,
RIGHT,
SOFT_DROP,
@ -40,7 +41,7 @@ u16 controls_g[BINDS_N] = {
MOUSE,
};
u16 codes_g[BINDS_N] = {
u16 CODES[BINDS_N] = {
0x25,
0x27,
0x28,
@ -57,7 +58,7 @@ u16 codes_g[BINDS_N] = {
0
};
u16 types_g[BINDS_N] = {
u16 TYPES[BINDS_N] = {
BUTTON,
BUTTON,
BUTTON,
@ -75,7 +76,7 @@ u16 types_g[BINDS_N] = {
};
struct TetraTemplate I = {
.blks = &(u8) {
.blks = (u8[16]) {
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
@ -86,18 +87,18 @@ struct TetraTemplate I = {
};
struct TetraTemplate O = {
.blks = &(u8) {
1, 1,
1, 1
.blks = (u8[4]) {
2, 2,
2, 2
},
.wid = 2,
.hgt = 2
};
struct TetraTemplate T = {
.blks = &(u8) {
0, 1, 0,
1, 1, 1,
.blks = (u8[9]) {
0, 3, 0,
3, 3, 3,
0, 0, 0
},
.wid = 3,
@ -105,9 +106,9 @@ struct TetraTemplate T = {
};
struct TetraTemplate S = {
.blks = &(u8) {
0, 1, 1,
1, 1, 0,
.blks = (u8[9]) {
0, 4, 4,
4, 4, 0,
0, 0, 0
},
.wid = 3,
@ -115,9 +116,9 @@ struct TetraTemplate S = {
};
struct TetraTemplate Z = {
.blks = &(u8) {
1, 1, 0,
0, 1, 1,
.blks = (u8[9]) {
5, 5, 0,
0, 5, 5,
0, 0, 0
},
.wid = 3,
@ -125,9 +126,9 @@ struct TetraTemplate Z = {
};
struct TetraTemplate J = {
.blks = &(u8) {
1, 0, 0,
1, 1, 1,
.blks = (u8[9]) {
6, 0, 0,
6, 6, 6,
0, 0, 0
},
.wid = 3,
@ -135,11 +136,13 @@ struct TetraTemplate J = {
};
struct TetraTemplate L = {
.blks = &(u8) {
0, 0, 1,
1, 1, 1,
.blks = (u8[9]) {
0, 0, 7,
7, 7, 7,
0, 0, 0
},
.wid = 3,
.hgt = 3
};
struct TetraTemplate *templates[7] = { &I, &O, &T, &S, &Z, &J, &L };

View file

@ -1,20 +1,24 @@
#include "tetra.h"
bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt)
bool CreateTetra(struct Tetra *tetra, 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;
*tetra = (struct Tetra) {
.blks = blks,
map->x = 0;
map->y = 0;
map->rot = 0;
.wid = wid,
.hgt = hgt,
.x = 0,
.y = 0,
.rot = 0
};
return true;
}
@ -24,37 +28,45 @@ void FreeTetra(struct Tetra *tetra)
free(tetra->blks);
}
void SetTetra(struct Tetra *map, struct TetraTemplate *t, i16 x, i16 y)
void TetraSet(struct Tetra *tetra, struct TetraTemplate *template)
{
map->blks = t->blks;
map->wid = t->wid;
map->hgt = t->hgt;
tetra->blks = template->blks;
tetra->wid = template->wid;
tetra->hgt = template->hgt;
map->x = x;
map->y = y;
map->rot = 0;
tetra->x = 0;
tetra->y = 0;
tetra->rot = 0;
}
bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
usize rotate_index(usize i, usize wid, u8 rot)
{
if (TetraIsCollision(piece, board, dx, dy))
return false;
if(rot == 0)
return i;
piece->x += dx;
piece->y += dy;
usize row = i / wid;
usize col = i % wid;
return true;
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;
}
bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
bool TetraIsCollision(struct Tetra *t, struct Tetra *board)
{
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)
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)
@ -68,6 +80,53 @@ bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
return false;
}
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];
}
}
}
void TetraTerminalClear(struct Tetra *board, struct Terminal *term)
{
for (usize i = 0; i < board->wid * board->hgt; i++) {
@ -78,38 +137,24 @@ void TetraTerminalClear(struct Tetra *board, struct Terminal *term)
}
}
void TetraTerminalDraw(struct Tetra *tetra, struct Terminal *term)
void TetraTerminalDraw(struct Tetra *t, 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)
for (usize y = 0; y < t->hgt; y++) {
for (usize x = 0; x < t->wid; x++, i++) {
usize rot_i = rotate_index(i, t->wid, t->rot);
if (t->blks[rot_i] == 0)
continue;
usize term_i = (y + tetra->y) * term->wid + (x + tetra->x) * 2;
usize term_i = (y + t->y) * term->wid + (x + t->x) * 2;
struct Char4 *block = term->buf + term_i;
u8 fg = blk_colors[tetra->blks[i]];
u8 fg = blk_colors[t->blks[rot_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];
}
}
}

View file

@ -4,6 +4,13 @@
#include "terminal.h"
struct TetraTemplate {
u8 *blks;
usize wid;
usize hgt;
};
struct Tetra {
u8 *blks;
@ -12,30 +19,23 @@ struct Tetra {
i16 x;
i16 y;
u8f rot;
u8 rot;
};
struct TetraTemplate {
u8 *blks;
bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt);
u16 wid;
u16 hgt;
};
void FreeTetra(struct Tetra *tetra);
void TetraSet(struct Tetra *tetra, struct TetraTemplate *template);
bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt);
bool TetraIsCollision(struct Tetra *t, struct Tetra *board);
void FreeTetra(struct Tetra *map);
bool TetraMove(struct Tetra *t, struct Tetra *board, i16 dx, i16 dy);
void SetTetra(struct Tetra *map, struct TetraTemplate *t, i16 x, i16 y);
bool TetraRotate(struct Tetra *t, struct Tetra *board, i8 dr);
void TetraOverlay(struct Tetra *t, struct Tetra *board);
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);
void TetraTerminalDraw(struct Tetra *t, struct Terminal *term);