ALMOST WORKING
AHH
This commit is contained in:
parent
e3ed625feb
commit
1c4197e864
|
@ -60,7 +60,8 @@
|
||||||
"stdbool.h": "c",
|
"stdbool.h": "c",
|
||||||
"fumoengine.h": "c",
|
"fumoengine.h": "c",
|
||||||
"event.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>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
usize min_usize(usize a, usize b)
|
usize min(usize a, usize b)
|
||||||
{
|
{
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usize max(usize a, usize b)
|
||||||
|
{
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
nsec TimeNow()
|
nsec TimeNow()
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
|
@ -40,7 +40,8 @@ typedef int_fast64_t i64f;
|
||||||
typedef u64 nsec;
|
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();
|
nsec TimeNow();
|
||||||
double TimeNowD();
|
double TimeNowD();
|
||||||
|
|
|
@ -2,16 +2,35 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
|
||||||
const VectorT FUMOCO_T = VECTOR_T(struct FumoCoroutine);
|
|
||||||
|
|
||||||
|
|
||||||
void Panic(char *message)
|
void Panic(char *message)
|
||||||
{
|
{
|
||||||
printf(message);
|
printf(message);
|
||||||
exit(1);
|
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())
|
if (!PlatformInit())
|
||||||
Panic("Platform failed to initialize");
|
Panic("Platform failed to initialize");
|
||||||
|
@ -22,27 +41,27 @@ bool CreateFumoInstance(struct FumoInstance *instance)
|
||||||
if (!CreateInputThread(&instance->input_hand))
|
if (!CreateInputThread(&instance->input_hand))
|
||||||
Panic("Input handle failed to initialize");
|
Panic("Input handle failed to initialize");
|
||||||
|
|
||||||
if (!CreateTerminal(&instance->term, 20, 10))
|
|
||||||
Panic("Out of memory");
|
|
||||||
|
|
||||||
if (!CreateEvent(&instance->on_start))
|
if (!CreateEvent(&instance->on_start))
|
||||||
Panic("Out of memory");
|
Panic("Out of memory");
|
||||||
|
|
||||||
if (!CreateEvent(&instance->on_update))
|
if (!CreateEvent(&instance->on_update))
|
||||||
Panic("Out of memory");
|
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();
|
instance->time = TimeNow();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FumoInstanceRun(struct FumoInstance *inst)
|
bool FumoInstanceRun(struct Instance *inst)
|
||||||
{
|
{
|
||||||
EventInvoke(&inst->on_start, inst);
|
EventInvoke(&inst->on_start, inst);
|
||||||
|
|
||||||
usize buf_n = TerminalMaxOut(&inst->term);
|
|
||||||
char *buf = malloc(buf_n);
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Time
|
// Time
|
||||||
nsec now = TimeNow();
|
nsec now = TimeNow();
|
||||||
|
@ -60,25 +79,14 @@ bool FumoInstanceRun(struct FumoInstance *inst)
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
EventInvoke(&inst->on_update, inst);
|
EventInvoke(&inst->on_update, inst);
|
||||||
|
|
||||||
for (usize i = 0; i < inst->coroutines.len; i++) {
|
for (usize i = 0; i < inst->coroutines.len; i++) {
|
||||||
struct FumoCoroutine *co = VectorGet(FUMOCO_T, &inst->coroutines, i);
|
CoroutineTryInvoke(inst, VectorGet(&inst->coroutines, i));
|
||||||
co->callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
EventInvoke(&inst->on_draw, inst);
|
EventInvoke(&inst->on_draw, inst);
|
||||||
TerminalPrint(&inst->term, buf, buf_n);
|
|
||||||
puts(buf);
|
|
||||||
|
|
||||||
//_sleep(100);
|
//_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 "event.h"
|
||||||
#include "fumocommon.h"
|
#include "fumocommon.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "terminal.h"
|
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
|
|
||||||
struct FumoCoroutine {
|
typedef nsec (*coroutine_handler)(void *state, void *instance);
|
||||||
handler callback;
|
|
||||||
nsec timer;
|
|
||||||
nsec period;
|
struct Coroutine {
|
||||||
|
coroutine_handler callback;
|
||||||
|
void *state;
|
||||||
|
nsec next_scheduled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FumoInstance {
|
struct Instance {
|
||||||
struct Controller ctrl;
|
struct Controller ctrl;
|
||||||
struct InputHandle input_hand;
|
struct InputHandle input_hand;
|
||||||
struct Terminal term;
|
|
||||||
|
|
||||||
struct Event on_start;
|
struct Event on_start;
|
||||||
struct Event on_update;
|
struct Event on_update;
|
||||||
|
@ -31,6 +32,10 @@ struct FumoInstance {
|
||||||
|
|
||||||
void Panic(char *message);
|
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 "dictionary.h"
|
||||||
|
#include <stdalign.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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)
|
if (bkts == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*dict = (struct Dictionary) {
|
dict->value_size = value_size;
|
||||||
.filled = 0,
|
dict->value_offset = max(alignof(u32), alignof(u8[dict->value_size]));
|
||||||
.capacity = 16,
|
dict->bkt_size = dict->value_offset + value_size;
|
||||||
.bkts = bkts
|
|
||||||
};
|
dict->filled = 0;
|
||||||
|
dict->capacity = 16;
|
||||||
|
dict->bkts = bkts;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -25,45 +28,45 @@ void FreeDictionary(struct Dictionary *dict)
|
||||||
free(dict->bkts);
|
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;
|
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;
|
*get_key(dict, bkt) = key;
|
||||||
memcpy(get_val(T, bkt), val, T->VAL_SIZE);
|
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++) {
|
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 bkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
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++) {
|
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)
|
if (k == 0 or k == key)
|
||||||
return bkt;
|
return bkt;
|
||||||
}
|
}
|
||||||
|
@ -71,25 +74,25 @@ void *probe_empty_bkt(DictT T, struct Dictionary *dict, usize index, u32 key)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key)
|
void *DictionaryFind(struct Dictionary *dict, u32 key)
|
||||||
{
|
{
|
||||||
usize index = key % dict->capacity;
|
usize index = key % dict->capacity;
|
||||||
|
|
||||||
void *bkt = probe_bkt(T, dict, index, key);
|
void *bkt = probe_bkt(dict, index, key);
|
||||||
if (bkt == nullptr)
|
if (bkt == nullptr)
|
||||||
return false;
|
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;
|
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)
|
if (*get_key(dict, bkt) == 0)
|
||||||
set_bkt(T, bkt, key, val);
|
set_bkt(dict, bkt, key, value_ptr);
|
||||||
|
|
||||||
return bkt;
|
return bkt;
|
||||||
}
|
}
|
|
@ -1,31 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "fumocommon.h"
|
#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 {
|
struct Dictionary {
|
||||||
|
usize value_size;
|
||||||
|
usize value_offset;
|
||||||
|
usize bkt_size;
|
||||||
|
|
||||||
usize filled;
|
usize filled;
|
||||||
usize capacity;
|
usize capacity;
|
||||||
void *bkts;
|
void *bkts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool CreateDictionary(struct Dictionary *dict, usize value_size);
|
||||||
bool CreateDictionary(DictT T, struct Dictionary *dict);
|
|
||||||
|
|
||||||
void FreeDictionary(struct Dictionary *dict);
|
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);
|
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) {
|
if (event->len == event->capacity) {
|
||||||
usize new_size = event->capacity * 2 * sizeof(struct Method);
|
usize new_size = event->capacity * 2 * sizeof(struct Method);
|
||||||
|
|
|
@ -21,6 +21,6 @@ struct Event {
|
||||||
|
|
||||||
bool CreateEvent(struct Event *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);
|
void EventInvoke(struct Event *event, void *state);
|
|
@ -37,7 +37,7 @@ void RingBufferTransfer(
|
||||||
struct RingBufferHead *dest,
|
struct RingBufferHead *dest,
|
||||||
struct RingBufferHead *tmp
|
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++) {
|
for (usize i = 0; i < copy_max; i++) {
|
||||||
void *to = RingBufferGet(T, dest, dest->len + i);
|
void *to = RingBufferGet(T, dest, dest->len + i);
|
||||||
|
@ -55,7 +55,7 @@ usize RingBufferOut(
|
||||||
void *dest,
|
void *dest,
|
||||||
struct RingBufferHead *src
|
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++) {
|
for (usize i = 0; i < copy_max; i++) {
|
||||||
void *to = (u8 *)dest + i * T->SIZE;
|
void *to = (u8 *)dest + i * T->SIZE;
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
#include <string.h>
|
#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)
|
if (array == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
vec->value_size = value_size;
|
||||||
|
|
||||||
vec->len = 0;
|
vec->len = 0;
|
||||||
vec->capacity = 16;
|
vec->capacity = 16;
|
||||||
vec->array = array;
|
vec->array = array;
|
||||||
|
@ -22,16 +24,16 @@ void FreeVector(struct Vector *vec)
|
||||||
free(vec->array);
|
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) {
|
if (vec->len == vec->capacity) {
|
||||||
usize new_capacity = vec->capacity * 2;
|
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)
|
if (new_array == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -39,7 +41,7 @@ bool VectorAdd(VectorT T, struct Vector *vec, void *item)
|
||||||
vec->capacity = new_capacity;
|
vec->capacity = new_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(VectorGet(T, vec, vec->len++), item, T->SIZE);
|
memcpy(VectorGet(vec, vec->len++), item, vec->value_size);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -1,26 +1,19 @@
|
||||||
#include "fumocommon.h"
|
#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 {
|
struct Vector {
|
||||||
|
usize value_size;
|
||||||
|
|
||||||
usize len;
|
usize len;
|
||||||
usize capacity;
|
usize capacity;
|
||||||
void *array;
|
void *array;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool CreateVector(VectorT T, struct Vector *vec);
|
bool CreateVector(struct Vector *vec, usize value_size);
|
||||||
|
|
||||||
void FreeVector(struct Vector *vec);
|
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
|
#define INIT_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
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(&ctrl->binds, sizeof(struct InputAxis*)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ctrl->pending_len = 0;
|
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);
|
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(&ctrl->binds, hash, &axis);
|
||||||
|
|
||||||
if (bind == nullptr)
|
if (bind == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -92,7 +89,7 @@ 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(&ctrl->binds, hash);
|
||||||
|
|
||||||
if (axis == nullptr)
|
if (axis == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
@ -103,43 +100,3 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
|
||||||
|
|
||||||
recs->head.len = 0;
|
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
|
#define MAX_CH4_LEN 11
|
||||||
|
|
||||||
|
|
||||||
usize TerminalMaxOut(struct Terminal *term)
|
usize TerminalMaxOut(usize wid, usize hgt)
|
||||||
{
|
{
|
||||||
return RESET_STR_LEN
|
return RESET_STR_LEN
|
||||||
+ MAX_CH4_LEN * term->wid * term->hgt
|
+ MAX_CH4_LEN * wid * hgt
|
||||||
+ term->hgt
|
+ hgt
|
||||||
+ 1;
|
+ 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt)
|
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt)
|
||||||
{
|
{
|
||||||
struct Char4 *ch4s = calloc(wid * hgt, sizeof(struct Char4));
|
struct Char4 *ch4s = calloc(wid * hgt, sizeof(struct Char4));
|
||||||
|
|
||||||
if (ch4s == nullptr)
|
if (ch4s == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*term = (struct Terminal) {
|
char *str = malloc(TerminalMaxOut(wid, hgt));
|
||||||
.wid = wid,
|
if (str == nullptr)
|
||||||
.hgt = hgt,
|
return false;
|
||||||
|
|
||||||
.buf = ch4s
|
*term = (struct Terminal) {
|
||||||
|
.buf = ch4s,
|
||||||
|
.str = str,
|
||||||
|
|
||||||
|
.wid = wid,
|
||||||
|
.hgt = hgt
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -107,12 +111,12 @@ usize ch4_dif_to_str(char *out, struct Color4 *dif, struct Char4 *ch4)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize TerminalPrint(struct Terminal *term, char *out, usize n)
|
usize TerminalPrint(struct Terminal *term)
|
||||||
{
|
{
|
||||||
struct Color4 dif = { 0, 0 };
|
struct Color4 dif = { 0, 0 };
|
||||||
|
|
||||||
usize len = 7;
|
usize len = 7;
|
||||||
memcpy(out, "\x1b[H\x1b[0m", 7);
|
memcpy(term->str, "\x1b[H\x1b[0m", 7);
|
||||||
|
|
||||||
usize i = 0;
|
usize i = 0;
|
||||||
for (usize y = 0; y < term->hgt; y++) {
|
for (usize y = 0; y < term->hgt; y++) {
|
||||||
|
@ -124,11 +128,11 @@ usize TerminalPrint(struct Terminal *term, char *out, usize n)
|
||||||
ch4->ch = '#';
|
ch4->ch = '#';
|
||||||
// DEBUG
|
// 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;
|
return len;
|
||||||
}
|
}
|
|
@ -1,10 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <iso646.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "fumocommon.h"
|
#include "fumocommon.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,16 +15,18 @@ struct Char4 {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Terminal {
|
struct Terminal {
|
||||||
|
struct Char4 *buf;
|
||||||
|
char *str;
|
||||||
|
|
||||||
usize wid;
|
usize wid;
|
||||||
usize hgt;
|
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);
|
bool CreateTerminal(struct Terminal *term, usize wid, usize hgt);
|
||||||
|
|
||||||
void FreeTerminal(struct Terminal *term);
|
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 Fumotris {
|
||||||
|
struct Terminal term;
|
||||||
|
|
||||||
|
struct TetraTemplate *bag[7];
|
||||||
|
usize bag_i;
|
||||||
|
|
||||||
struct Tetra board;
|
struct Tetra board;
|
||||||
struct Tetra piece;
|
struct Tetra piece;
|
||||||
|
|
||||||
bool is_ground;
|
bool is_ground;
|
||||||
|
|
||||||
|
nsec last_moved;
|
||||||
|
nsec last_dropped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void shuffle(struct Fumotris *fumo)
|
||||||
struct TetraTemplate *bag[7] = { &I, &O, &T, &S, &Z, &J, &L };
|
|
||||||
usize bag_i = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void shuffle()
|
|
||||||
{
|
{
|
||||||
for (usize i = 6; i >= 0; i--) {
|
for (usize i = 6; i > 0; i--) {
|
||||||
usize swap = rand() % i;
|
usize swap = rand() % i;
|
||||||
|
|
||||||
struct TetraTemplate *tmp = bag[swap];
|
struct TetraTemplate *tmp = fumo->bag[swap];
|
||||||
bag[swap] = bag[i];
|
fumo->bag[swap] = fumo->bag[i];
|
||||||
bag[i] = tmp;
|
fumo->bag[i] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void place_piece(struct Fumotris *fumo)
|
void check_clear()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void place(struct Fumotris *fumo)
|
||||||
{
|
{
|
||||||
TetraOverlay(&fumo->piece, &fumo->board);
|
TetraOverlay(&fumo->piece, &fumo->board);
|
||||||
SetTetra(&fumo->piece, bag[bag_i++], 0, 0);
|
|
||||||
|
|
||||||
if (bag_i == 7) {
|
usize lines_cleared = fumo->piece.hgt;
|
||||||
shuffle();
|
|
||||||
bag_i = 0;
|
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)
|
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);
|
ControllerBindMulti(&inst->ctrl, BINDS_N, CONTROLS, CODES, TYPES);
|
||||||
CreateTetra(&fumo->board, 10, 10);
|
|
||||||
|
|
||||||
|
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;
|
fumo->is_ground = false;
|
||||||
|
fumo->last_moved = 0;
|
||||||
SetTetra(&fumo->piece, bag[bag_i++], 0, 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);
|
TetraMove(&fumo->piece, &fumo->board, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->ctrl.axes[HARD_DROP].is_down) {
|
if (inst->ctrl.axes[HARD_DROP].is_down) {
|
||||||
while (TetraMove(&fumo->piece, &fumo->board, 0, 1));
|
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 (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) {
|
||||||
if (!fumo->is_ground)
|
if (!fumo->is_ground)
|
||||||
fumo->is_ground = true;
|
fumo->is_ground = true;
|
||||||
else
|
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);
|
TetraTerminalClear(&fumo->board, &fumo->term);
|
||||||
TetraTerminalDraw(&fumo->board, &inst->term);
|
TetraTerminalDraw(&fumo->board, &fumo->term);
|
||||||
TetraTerminalDraw(&fumo->piece, &inst->term);
|
TetraTerminalDraw(&fumo->piece, &fumo->term);
|
||||||
|
|
||||||
|
TerminalPrint(&fumo->term);
|
||||||
|
puts(fumo->term.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
struct FumoInstance inst;
|
struct Instance inst;
|
||||||
CreateFumoInstance(&inst);
|
CreateFumoInstance(&inst);
|
||||||
|
|
||||||
struct Fumotris game;
|
struct Fumotris game;
|
||||||
|
|
||||||
EventAdd(&inst.on_start, FumotrisStart, &game);
|
EventAdd(&inst.on_start, &game, FumotrisStart);
|
||||||
EventAdd(&inst.on_update, FumotrisUpdate, &game);
|
EventAdd(&inst.on_update, &game, FumotrisUpdate);
|
||||||
EventAdd(&inst.on_draw, FumotrisDraw, &game);
|
EventAdd(&inst.on_draw, &game, FumotrisDraw);
|
||||||
|
|
||||||
VectorAdd(FUMOCO_T, &inst.coroutines, );
|
CoroutineAdd(&inst, &game, FumotrisFall);
|
||||||
|
|
||||||
FumoInstanceRun(&inst);
|
FumoInstanceRun(&inst);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "fumocommon.h"
|
#include "fumocommon.h"
|
||||||
#include "fumoengine.h"
|
#include "fumoengine.h"
|
||||||
|
#include "terminal.h"
|
||||||
#include "tetra.h"
|
#include "tetra.h"
|
||||||
|
|
||||||
#define BINDS_N 12
|
#define BINDS_N 12
|
||||||
|
@ -23,7 +24,7 @@ enum FumotrisControls {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
u16 controls_g[BINDS_N] = {
|
u16 CONTROLS[BINDS_N] = {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT,
|
RIGHT,
|
||||||
SOFT_DROP,
|
SOFT_DROP,
|
||||||
|
@ -40,7 +41,7 @@ u16 controls_g[BINDS_N] = {
|
||||||
MOUSE,
|
MOUSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
u16 codes_g[BINDS_N] = {
|
u16 CODES[BINDS_N] = {
|
||||||
0x25,
|
0x25,
|
||||||
0x27,
|
0x27,
|
||||||
0x28,
|
0x28,
|
||||||
|
@ -57,7 +58,7 @@ u16 codes_g[BINDS_N] = {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
u16 types_g[BINDS_N] = {
|
u16 TYPES[BINDS_N] = {
|
||||||
BUTTON,
|
BUTTON,
|
||||||
BUTTON,
|
BUTTON,
|
||||||
BUTTON,
|
BUTTON,
|
||||||
|
@ -75,7 +76,7 @@ u16 types_g[BINDS_N] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate I = {
|
struct TetraTemplate I = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[16]) {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
1, 1, 1, 1,
|
1, 1, 1, 1,
|
||||||
|
@ -86,18 +87,18 @@ struct TetraTemplate I = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate O = {
|
struct TetraTemplate O = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[4]) {
|
||||||
1, 1,
|
2, 2,
|
||||||
1, 1
|
2, 2
|
||||||
},
|
},
|
||||||
.wid = 2,
|
.wid = 2,
|
||||||
.hgt = 2
|
.hgt = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate T = {
|
struct TetraTemplate T = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[9]) {
|
||||||
0, 1, 0,
|
0, 3, 0,
|
||||||
1, 1, 1,
|
3, 3, 3,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
.wid = 3,
|
.wid = 3,
|
||||||
|
@ -105,9 +106,9 @@ struct TetraTemplate T = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate S = {
|
struct TetraTemplate S = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[9]) {
|
||||||
0, 1, 1,
|
0, 4, 4,
|
||||||
1, 1, 0,
|
4, 4, 0,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
.wid = 3,
|
.wid = 3,
|
||||||
|
@ -115,9 +116,9 @@ struct TetraTemplate S = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate Z = {
|
struct TetraTemplate Z = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[9]) {
|
||||||
1, 1, 0,
|
5, 5, 0,
|
||||||
0, 1, 1,
|
0, 5, 5,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
.wid = 3,
|
.wid = 3,
|
||||||
|
@ -125,9 +126,9 @@ struct TetraTemplate Z = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate J = {
|
struct TetraTemplate J = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[9]) {
|
||||||
1, 0, 0,
|
6, 0, 0,
|
||||||
1, 1, 1,
|
6, 6, 6,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
.wid = 3,
|
.wid = 3,
|
||||||
|
@ -135,11 +136,13 @@ struct TetraTemplate J = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate L = {
|
struct TetraTemplate L = {
|
||||||
.blks = &(u8) {
|
.blks = (u8[9]) {
|
||||||
0, 0, 1,
|
0, 0, 7,
|
||||||
1, 1, 1,
|
7, 7, 7,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
.wid = 3,
|
.wid = 3,
|
||||||
.hgt = 3
|
.hgt = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TetraTemplate *templates[7] = { &I, &O, &T, &S, &Z, &J, &L };
|
|
@ -1,20 +1,24 @@
|
||||||
#include "tetra.h"
|
#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));
|
u8 *blks = calloc(wid * hgt, sizeof(u8));
|
||||||
|
|
||||||
if (blks == nullptr)
|
if (blks == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
map->blks = blks;
|
*tetra = (struct Tetra) {
|
||||||
map->wid = wid;
|
.blks = blks,
|
||||||
map->hgt = hgt;
|
|
||||||
|
|
||||||
map->x = 0;
|
.wid = wid,
|
||||||
map->y = 0;
|
.hgt = hgt,
|
||||||
map->rot = 0;
|
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
|
||||||
|
.rot = 0
|
||||||
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -24,37 +28,45 @@ void FreeTetra(struct Tetra *tetra)
|
||||||
free(tetra->blks);
|
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;
|
tetra->blks = template->blks;
|
||||||
map->wid = t->wid;
|
tetra->wid = template->wid;
|
||||||
map->hgt = t->hgt;
|
tetra->hgt = template->hgt;
|
||||||
|
|
||||||
map->x = x;
|
tetra->x = 0;
|
||||||
map->y = y;
|
tetra->y = 0;
|
||||||
map->rot = 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))
|
if(rot == 0)
|
||||||
return false;
|
return i;
|
||||||
|
|
||||||
piece->x += dx;
|
usize row = i / wid;
|
||||||
piece->y += dy;
|
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;
|
usize i = 0;
|
||||||
for (i16 y = y_start; y < y_start + piece->hgt; y++) {
|
for (i16 y = t->y; y < t->y + t->hgt; y++) {
|
||||||
for (i16 x = x_start; x < x_start + piece->wid; x++, i++) {
|
for (i16 x = t->x; x < t->x + t->wid; x++, i++) {
|
||||||
if(piece->blks[i] == 0)
|
usize rot_i = rotate_index(i, t->wid, t->rot);
|
||||||
|
|
||||||
|
if(t->blks[rot_i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt)
|
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;
|
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)
|
void TetraTerminalClear(struct Tetra *board, struct Terminal *term)
|
||||||
{
|
{
|
||||||
for (usize i = 0; i < board->wid * board->hgt; i++) {
|
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 };
|
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
||||||
|
|
||||||
usize i = 0;
|
usize i = 0;
|
||||||
for (usize y = 0; y < tetra->hgt; y++) {
|
for (usize y = 0; y < t->hgt; y++) {
|
||||||
for (usize x = 0; x < tetra->wid; x++, i++) {
|
for (usize x = 0; x < t->wid; x++, i++) {
|
||||||
if (tetra->blks[i] == 0)
|
usize rot_i = rotate_index(i, t->wid, t->rot);
|
||||||
|
|
||||||
|
if (t->blks[rot_i] == 0)
|
||||||
continue;
|
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;
|
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[0] = (struct Char4) { .ch = '[', .color.fg = fg };
|
||||||
block[1] = (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,6 +4,13 @@
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct TetraTemplate {
|
||||||
|
u8 *blks;
|
||||||
|
|
||||||
|
usize wid;
|
||||||
|
usize hgt;
|
||||||
|
};
|
||||||
|
|
||||||
struct Tetra {
|
struct Tetra {
|
||||||
u8 *blks;
|
u8 *blks;
|
||||||
|
|
||||||
|
@ -12,30 +19,23 @@ struct Tetra {
|
||||||
|
|
||||||
i16 x;
|
i16 x;
|
||||||
i16 y;
|
i16 y;
|
||||||
|
u8 rot;
|
||||||
u8f rot;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetraTemplate {
|
bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt);
|
||||||
u8 *blks;
|
|
||||||
|
|
||||||
u16 wid;
|
void FreeTetra(struct Tetra *tetra);
|
||||||
u16 hgt;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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 TetraTerminalClear(struct Tetra *board, struct Terminal *term);
|
||||||
|
|
||||||
void TetraTerminalDraw(struct Tetra *map, struct Terminal *term);
|
void TetraTerminalDraw(struct Tetra *t, 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