ALMOST WORKING
AHH
This commit is contained in:
parent
e3ed625feb
commit
1c4197e864
|
@ -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
|
@ -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"]
|
|
@ -1 +1 @@
|
|||
[]
|
||||
["4aa55dfc1d038e75d0efbf277e6033a4"]
|
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/tetra.o
BIN
objects/tetra.o
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.
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
@ -57,28 +76,17 @@ bool FumoInstanceRun(struct FumoInstance *inst)
|
|||
|
||||
if (!InputRelease(&inst->input_hand))
|
||||
Panic("Release failed");
|
||||
|
||||
|
||||
// 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
|
||||
});
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
|
@ -102,44 +99,4 @@ 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;
|
||||
}*/
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 };
|
|
@ -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;
|
||||
|
||||
tetra->x = 0;
|
||||
tetra->y = 0;
|
||||
tetra->rot = 0;
|
||||
}
|
||||
|
||||
usize rotate_index(usize i, usize wid, u8 rot)
|
||||
{
|
||||
if(rot == 0)
|
||||
return i;
|
||||
|
||||
usize row = i / wid;
|
||||
usize col = i % wid;
|
||||
|
||||
map->x = x;
|
||||
map->y = y;
|
||||
map->rot = 0;
|
||||
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 TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy)
|
||||
bool TetraIsCollision(struct Tetra *t, struct Tetra *board)
|
||||
{
|
||||
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)
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,38 +4,38 @@
|
|||
#include "terminal.h"
|
||||
|
||||
|
||||
struct Tetra {
|
||||
struct TetraTemplate {
|
||||
u8 *blks;
|
||||
|
||||
usize wid;
|
||||
usize hgt;
|
||||
};
|
||||
|
||||
struct Tetra {
|
||||
u8 *blks;
|
||||
|
||||
u16 wid;
|
||||
u16 hgt;
|
||||
|
||||
i16 x;
|
||||
i16 y;
|
||||
|
||||
u8f rot;
|
||||
u8 rot;
|
||||
};
|
||||
|
||||
struct TetraTemplate {
|
||||
u8 *blks;
|
||||
|
||||
u16 wid;
|
||||
u16 hgt;
|
||||
};
|
||||
bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt);
|
||||
|
||||
void FreeTetra(struct Tetra *tetra);
|
||||
|
||||
bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt);
|
||||
void TetraSet(struct Tetra *tetra, struct TetraTemplate *template);
|
||||
|
||||
void FreeTetra(struct Tetra *map);
|
||||
bool TetraIsCollision(struct Tetra *t, struct Tetra *board);
|
||||
|
||||
void SetTetra(struct Tetra *map, struct TetraTemplate *t, i16 x, i16 y);
|
||||
bool TetraMove(struct Tetra *t, struct Tetra *board, i16 dx, i16 dy);
|
||||
|
||||
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);
|
Loading…
Reference in a new issue