gaming
th j
This commit is contained in:
parent
599c41ef1b
commit
8ad3bf1f22
|
@ -1,51 +1,58 @@
|
|||
#include <iso646.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "event.h"
|
||||
|
||||
#include "fumotris.h"
|
||||
#define INIT_CAPACITY 16
|
||||
|
||||
struct Delegate {
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
void (**events)(void *args);
|
||||
};
|
||||
|
||||
size_t delegate_size(size_t capacity)
|
||||
{
|
||||
return sizeof(void(*)(void *)) * capacity;
|
||||
size_t clbks_size(size_t capacity) {
|
||||
return sizeof(union func) * capacity;
|
||||
}
|
||||
|
||||
bool NewDelegate(struct Delegate *d, size_t capacity)
|
||||
bool CreateEvent(struct Event *event)
|
||||
{
|
||||
void (**events)(void *args) = malloc(delegate_size(capacity));
|
||||
union func *callbacks = malloc(clbks_size(INIT_CAPACITY));
|
||||
|
||||
if (events == nullptr)
|
||||
if (callbacks == nullptr)
|
||||
return false;
|
||||
|
||||
*d = (struct Delegate) {
|
||||
*event = (struct Event) {
|
||||
.clbks = callbacks,
|
||||
.len = 0,
|
||||
.capacity = capacity,
|
||||
.events = malloc(delegate_size(capacity))
|
||||
.capacity = INIT_CAPACITY,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
void Subscribe(struct Delegate *d, void (*event)(void *args))
|
||||
void FreeEvent(struct Event *event)
|
||||
{
|
||||
if (d->len == d->capacity) {
|
||||
d->capacity *= 2;
|
||||
d->events = realloc(d->events, delegate_size(d->capacity));
|
||||
free(event->clbks);
|
||||
}
|
||||
|
||||
d->events[d->len] = event;
|
||||
d->len += 1;
|
||||
bool EventSubscribe(struct Event *event, union func callback)
|
||||
{
|
||||
if (event->len == event->capacity) {
|
||||
size_t new_cap = event->capacity * 2;
|
||||
union func *new_clbks = realloc(event->clbks, clbks_size(new_cap));
|
||||
|
||||
if (new_clbks == nullptr)
|
||||
return false;
|
||||
|
||||
event->clbks = new_clbks;
|
||||
event->capacity = new_cap;
|
||||
}
|
||||
|
||||
void Invoke(struct Delegate *d, void *args)
|
||||
event->clbks[event->len++] = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventInvoke(struct Event *event, void *arg)
|
||||
{
|
||||
for (size_t i = 0; i < d->len; i++) {
|
||||
d->events[i](args);
|
||||
for (size_t i = 0; i < event->len; i++) {
|
||||
event->clbks[i].generic(arg);
|
||||
}
|
||||
}
|
||||
|
||||
void EventInvokeUpdate(struct Event *event, u64 dt)
|
||||
{
|
||||
for (size_t i = 0; i < event->len; i++) {
|
||||
event->clbks[i].update(dt);
|
||||
}
|
||||
}
|
|
@ -6,15 +6,23 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "fumotris.h"
|
||||
#include "gametime.h"
|
||||
|
||||
struct Delegate {
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
void (**events)(void *args);
|
||||
union func {
|
||||
void (*generic)(void *arg);
|
||||
void (*update)(Time dt);
|
||||
};
|
||||
|
||||
bool NewDelegate(struct Delegate *d, size_t capacity);
|
||||
struct Event {
|
||||
union func *clbks;
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
void Subscribe(struct Delegate *d, void (*event)(void *args));
|
||||
bool CreateEvent(struct Event *event);
|
||||
|
||||
void Invoke(struct Delegate *d, void *args);
|
||||
bool EventSubscribe(struct Event *event, union func callback);
|
||||
|
||||
void EventInvoke(struct Event *event, void *arg);
|
||||
|
||||
void EventInvokeUpdate(struct Event *event, Time dt);
|
|
@ -1,24 +1,17 @@
|
|||
#include "gametime.h"
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "win.h"
|
||||
#endif
|
||||
#define ONE_E_9 1000000000
|
||||
|
||||
struct Time {
|
||||
u32 sec;
|
||||
u32 nsec;
|
||||
};
|
||||
|
||||
struct Time TimeNow()
|
||||
Time TimeNow()
|
||||
{
|
||||
struct timespec ts;
|
||||
// Need to check for failiure
|
||||
timespec_get(&ts, TIME_UTC);
|
||||
return (struct Time) { ts.tv_sec, ts.tv_nsec };
|
||||
|
||||
return ts.tv_nsec + ts.tv_sec * ONE_E_9;
|
||||
}
|
||||
|
||||
double TimeNowDouble()
|
||||
double TimeNowD()
|
||||
{
|
||||
struct timespec ts;
|
||||
timespec_get(&ts, TIME_UTC);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct Time {
|
||||
u32 sec;
|
||||
u32 nsec;
|
||||
};
|
||||
#include "fumotris.h"
|
||||
|
||||
struct Time TimeNow();
|
||||
typedef u64 Time;
|
||||
|
||||
double TimeNowDouble();
|
||||
Time TimeNow();
|
||||
|
||||
double TimeNowD();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "ctrl.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define INIT_SIZE 16
|
||||
|
||||
bool CreateCtrl(struct Controller *ctrl)
|
||||
|
@ -142,7 +144,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
|
|||
axis->data = rec->data;
|
||||
}
|
||||
|
||||
bool CtrlPoll(struct Controller *ctrl)
|
||||
bool read_input_buf(struct Controller *ctrl)
|
||||
{
|
||||
for (size_t i = 0; i < ctrl->pending_buf.len; i++) {
|
||||
struct InputAxis *axis = ctrl->pending_buf.axes[i];
|
||||
|
@ -150,21 +152,37 @@ bool CtrlPoll(struct Controller *ctrl)
|
|||
axis->is_up = false;
|
||||
axis->is_down = false;
|
||||
}
|
||||
ctrl->pending_buf.len = ctrl->buf.len;
|
||||
ctrl->pending_buf.len = 0;
|
||||
|
||||
for (size_t i = 0; i < ctrl->buf.len; i++) {
|
||||
struct InputRecord *rec = &ctrl->buf.recs[i];
|
||||
|
||||
union InputID rec_id = to_id(rec->bind, rec->type);
|
||||
struct InputAxis *axis = find_axis(&ctrl->binds, rec_id);
|
||||
|
||||
if (axis == nullptr)
|
||||
continue;
|
||||
|
||||
dispatch_update(axis, rec);
|
||||
|
||||
ctrl->pending_buf.axes[i] = axis;
|
||||
ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis;
|
||||
}
|
||||
|
||||
ctrl->buf.len = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand)
|
||||
{
|
||||
if (pthread_mutex_lock(&hand->mutex) != 0)
|
||||
return false;
|
||||
|
||||
read_input_buf(ctrl);
|
||||
|
||||
if (pthread_cond_signal(&hand->buf_read) != 0)
|
||||
return false;
|
||||
|
||||
if (pthread_mutex_unlock(&hand->mutex) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include <iso646.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
@ -11,8 +10,8 @@
|
|||
#include "input.h"
|
||||
|
||||
struct InputAxis {
|
||||
struct Time last_pressed;
|
||||
struct Time last_released;
|
||||
Time last_pressed;
|
||||
Time last_released;
|
||||
|
||||
union {
|
||||
struct Button but;
|
||||
|
@ -46,15 +45,18 @@ struct ctrl_axis_vec {
|
|||
|
||||
struct Controller {
|
||||
struct InputBuffer buf;
|
||||
struct {
|
||||
struct InputAxis *axes[IO_BUF_SIZE];
|
||||
u16f len;
|
||||
} pending_buf;
|
||||
|
||||
struct InputAxis *pending_axes[IO_BUF_SIZE];
|
||||
char string_input[IO_BUF_SIZE];
|
||||
|
||||
u8f pending_axes_len;
|
||||
u8f string_input_len;
|
||||
|
||||
struct ctrl_axis_vec axis_vec;
|
||||
struct ctrl_dict codes;
|
||||
struct ctrl_dict binds;
|
||||
};
|
||||
size_t a = sizeof(struct Controller);
|
||||
|
||||
bool CreateCtrl(struct Controller *ctrl);
|
||||
|
||||
|
@ -64,7 +66,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind);
|
|||
|
||||
struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u16f type);
|
||||
|
||||
bool CtrlPoll(struct Controller *ctrl);
|
||||
bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand);
|
||||
|
||||
enum ControlCode {
|
||||
LEFT,
|
||||
|
|
|
@ -6,13 +6,13 @@ struct InputRecord *buf_get(struct InputBuffer *buf, size_t i) {
|
|||
return buf->recs + (buf->start + i) % IO_BUF_SIZE;
|
||||
}
|
||||
|
||||
size_t max_size(size_t a, size_t b) {
|
||||
return a > b ? a : b;
|
||||
size_t min_size(size_t a, size_t b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
void InputBufferTransfer(struct InputBuffer *dest, struct InputBuffer *src)
|
||||
{
|
||||
size_t copy_amt = IO_BUF_SIZE - max_size(dest->len, src->len);
|
||||
size_t copy_amt = min_size(IO_BUF_SIZE - dest->len, src->len);
|
||||
|
||||
for (size_t i = 0; i < copy_amt; i++)
|
||||
*buf_get(dest, dest->len + i) = *buf_get(src, i);
|
||||
|
@ -35,7 +35,6 @@ void *input_thread_loop(void *arg)
|
|||
struct InputBuffer tmp_buf = { .len = 0, .start = 0 };
|
||||
|
||||
while (!hand->is_terminating) {
|
||||
printf("\tinput cycle");
|
||||
if (!PlatformReadInput(&tmp_buf)) {
|
||||
hand->err = true;
|
||||
return nullptr;
|
||||
|
@ -45,7 +44,13 @@ void *input_thread_loop(void *arg)
|
|||
if (hand->err)
|
||||
return nullptr;
|
||||
|
||||
InputBufferTransfer(&tmp_buf, hand->buf);
|
||||
while (tmp_buf.len == IO_BUF_SIZE) {
|
||||
hand->err = pthread_cond_wait(&hand->buf_read, &hand->mutex);
|
||||
if (hand->err)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputBufferTransfer(hand->buf, &tmp_buf);
|
||||
|
||||
hand->err = pthread_mutex_unlock(&hand->mutex);
|
||||
if (hand->err)
|
||||
|
@ -57,7 +62,11 @@ void *input_thread_loop(void *arg)
|
|||
|
||||
bool BeginInputThread(struct InputThreadHandle *hand, struct InputBuffer *buf)
|
||||
{
|
||||
hand->buf = buf;
|
||||
hand->mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
hand->buf_read = PTHREAD_COND_INITIALIZER;
|
||||
hand->err = 0;
|
||||
|
||||
return pthread_create(&hand->thread, nullptr, input_thread_loop, hand) == 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ union InputData {
|
|||
};
|
||||
|
||||
struct InputRecord {
|
||||
struct Time time;
|
||||
Time time;
|
||||
|
||||
union {
|
||||
struct Button but;
|
||||
|
@ -76,6 +76,7 @@ struct InputThreadHandle {
|
|||
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t buf_read;
|
||||
|
||||
int err;
|
||||
bool is_terminating;
|
||||
|
|
|
@ -20,4 +20,4 @@ bool PlatformReadInput(struct InputBuffer *buf);
|
|||
|
||||
bool PlatformStopInput();
|
||||
|
||||
bool PlatformWait(struct Time relative);
|
||||
bool PlatformWait(Time duration);
|
|
@ -6,13 +6,7 @@
|
|||
#include "input.h"
|
||||
|
||||
struct windows {
|
||||
union {
|
||||
HANDLE input_hands[2];
|
||||
struct {
|
||||
HANDLE input_hand;
|
||||
HANDLE early_exit_hand;
|
||||
};
|
||||
};
|
||||
HANDLE timer;
|
||||
} win;
|
||||
|
||||
|
@ -26,10 +20,6 @@ bool init_handles()
|
|||
if (win.timer == NULL)
|
||||
return false;
|
||||
|
||||
win.early_exit_hand = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
if (win.early_exit_hand == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -68,7 +58,7 @@ bool PlatformGetRefreshRate(u16f *out)
|
|||
return true;
|
||||
}
|
||||
|
||||
void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
|
||||
void read_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
|
||||
{
|
||||
rec->type = BUTTON;
|
||||
rec->bind = win_key->wVirtualKeyCode;
|
||||
|
@ -77,7 +67,7 @@ void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
|
|||
rec->is_up = !win_key->bKeyDown;
|
||||
}
|
||||
|
||||
bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
|
||||
bool read_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
|
||||
{
|
||||
if (win_mouse->dwEventFlags == MOUSE_MOVED) {
|
||||
rec->type = JOYSTICK;
|
||||
|
@ -99,15 +89,15 @@ bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
|
||||
bool read_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
|
||||
{
|
||||
switch (win_rec->EventType) {
|
||||
case KEY_EVENT:
|
||||
copy_key_event(rec, &win_rec->Event.KeyEvent);
|
||||
read_key_event(rec, &win_rec->Event.KeyEvent);
|
||||
return true;
|
||||
|
||||
case MOUSE_EVENT:
|
||||
return copy_mouse_event(rec, &win_rec->Event.MouseEvent);
|
||||
return read_mouse_event(rec, &win_rec->Event.MouseEvent);
|
||||
|
||||
case WINDOW_BUFFER_SIZE_EVENT:
|
||||
return false;
|
||||
|
@ -120,11 +110,6 @@ bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
|
|||
|
||||
bool PlatformReadInput(struct InputBuffer *buf)
|
||||
{
|
||||
DWORD wait_status = WaitForMultipleObjects(2, win.input_hands, FALSE, 0);
|
||||
|
||||
if (wait_status != 0)
|
||||
return wait_status == 1;
|
||||
|
||||
DWORD max_records = IO_BUF_SIZE - buf->len;
|
||||
INPUT_RECORD win_buf[max_records];
|
||||
DWORD filled;
|
||||
|
@ -135,7 +120,7 @@ bool PlatformReadInput(struct InputBuffer *buf)
|
|||
struct InputRecord rec = { .time = TimeNow() };
|
||||
|
||||
for (size_t i = 0; i < filled; i++) {
|
||||
if (!copy_rec(&rec, win_buf + i))
|
||||
if (!read_rec(&rec, win_buf + i))
|
||||
continue;
|
||||
|
||||
InputBufferAdd(buf, &rec);
|
||||
|
@ -146,15 +131,15 @@ bool PlatformReadInput(struct InputBuffer *buf)
|
|||
|
||||
bool PlatformStopInput()
|
||||
{
|
||||
return SetEvent(win.early_exit_hand) == 0;
|
||||
return CancelSynchronousIo(win.input_hand);
|
||||
}
|
||||
|
||||
bool PlatformWait(struct Time relative)
|
||||
bool PlatformWait(Time duration)
|
||||
{
|
||||
LARGE_INTEGER duration;
|
||||
duration.QuadPart = -10000000 * relative.sec - relative.nsec / 100;
|
||||
LARGE_INTEGER nsec_div_100;
|
||||
nsec_div_100.QuadPart = -duration / 100;
|
||||
|
||||
if (!SetWaitableTimer(win.timer, &duration, 0, NULL, NULL, FALSE))
|
||||
if (!SetWaitableTimer(win.timer, &nsec_div_100, 0, NULL, NULL, FALSE))
|
||||
return false;
|
||||
|
||||
DWORD result = WaitForSingleObject(win.timer, INFINITE);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "input.h"
|
||||
#include "fumotris.h"
|
||||
#include "term.h"
|
||||
#include "tetr.h"
|
||||
#include "event.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -20,6 +19,14 @@ void ErrorExit(char *message)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
struct Game {
|
||||
struct Event Start;
|
||||
struct Event Draw;
|
||||
struct Event Update;
|
||||
|
||||
Time time;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!PlatformInit())
|
||||
|
@ -29,20 +36,20 @@ int main()
|
|||
if (!CreateCtrl(&ctrl))
|
||||
ErrorExit("Out of memory");
|
||||
|
||||
struct InputThreadHandle input;
|
||||
if (!BeginInputThread(&input, &ctrl.buf))
|
||||
struct Game game;
|
||||
CreateEvent(&game.Update);
|
||||
|
||||
struct InputThreadHandle input_hand;
|
||||
if (!BeginInputThread(&input_hand, &ctrl.buf))
|
||||
ErrorExit("Input handle failed to initialize");
|
||||
|
||||
CtrlMap(&ctrl, 0, BUTTON, 'A');
|
||||
|
||||
while (true) {
|
||||
bool poll = CtrlPoll(&ctrl);
|
||||
printf("poll: %u\n", poll);
|
||||
if(!CtrlPoll(&ctrl, &input_hand))
|
||||
ErrorExit("Poll failed");
|
||||
|
||||
struct InputAxis *a = CtrlGet(&ctrl, 0, BUTTON);
|
||||
printf("get: %llu\n", a);
|
||||
|
||||
printf("val: %u\n", a->but.value);
|
||||
EventInvokeUpdate(&game.Update, nullptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue