#include "all.h" #define MEM_SIZE (1<<16) typedef struct { char *start; char *end; } Arena; #define new(a, c, t) ((t *) alloc(a, c, sizeof(t), _Alignof(t))) #define affirm(c) while (!(c)) *(volatile int *)0 = 0 static void *alloc(Arena *a, ptrdiff_t count, ptrdiff_t size, ptrdiff_t align) { ptrdiff_t pad = -(size_t) a->start & (align - 1); affirm(count < (a->end - a->start - pad) / size); char *r = a->start + pad; a->start += pad + size * count; for (ptrdiff_t i = 0; i < count * size; i++) { r[i] = 0; } return r; } typedef struct { int width, height; } UI; typedef struct { int x, y; } State; enum { INPUT_NONE, INPUT_UP, INPUT_DOWN, INPUT_LEFT, INPUT_RIGHT, }; typedef struct { State state; UI ui; int input; } Game; static DrawList *render(State state, UI *ui, Arena *a) { (void) ui; DrawList *drawList = new(a, 1, DrawList); drawList->len = 1; drawList->els[0] = (DrawElement) { .rect = (SDL_Rect) { .x = state.x, .y = state.y, .w = 100, .h = 100, }, .color = (SDL_Color) { .r = 255, .g = 0, .b = 0, .a = 255, }, }; return drawList; } static void update(Game *game, Arena a) { switch (game->input) { case INPUT_UP: game->state.y -= 20; break; case INPUT_DOWN: game->state.y += 20; break; case INPUT_LEFT: game->state.x -= 20; break; case INPUT_RIGHT: game->state.x += 20; break; default: break; } } #if SDL int main(int argc, char **argv) { (void) argc; (void) argv; char *mem = SDL_malloc(MEM_SIZE); Arena a = { .start = mem, .end = mem + MEM_SIZE, }; Game *game = new(&a, 1, Game); game->state = (State) { .x = 100, .y = 100, }; game->ui = (UI) { .width = 640, .height = 480, }; SDL_Init(SDL_INIT_VIDEO); SDL_Window *w = SDL_CreateWindow( "LDJam 57", game->ui.width, game->ui.height, 0 ); SDL_PropertiesID renderProps = SDL_CreateProperties(); SDL_SetPointerProperty(renderProps, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, w); SDL_SetNumberProperty(renderProps, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 1); SDL_Renderer *r = SDL_CreateRendererWithProperties(renderProps); SDL_DestroyProperties(renderProps); for (;;) { game->input = INPUT_NONE; SDL_Event e = {0}; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_EVENT_QUIT: return 0; case SDL_EVENT_KEY_DOWN: switch (e.key.key) { case 'w': game->input = INPUT_UP; break; case 'a': game->input = INPUT_LEFT; break; case 's': game->input = INPUT_DOWN; break; case 'd': game->input = INPUT_RIGHT; break; } break; } } Arena scratch = a; DrawList *drawList = render(game->state, &game->ui, &scratch); SDL_SetRenderDrawColor(r, 0, 0, 0, 255); SDL_RenderFillRect(r, NULL); for (int i = 0; i < drawList->len; i++) { SDL_SetRenderDrawColor( r, drawList->els[i].color.r, drawList->els[i].color.g, drawList->els[i].color.b, drawList->els[i].color.a ); SDL_FRect rect = { .x = (float) drawList->els[i].rect.x, .y = (float) drawList->els[i].rect.y, .w = (float) drawList->els[i].rect.w, .h = (float) drawList->els[i].rect.h }; SDL_RenderFillRect(r, &rect); } update(game, a); SDL_RenderPresent(r); } return 0; } #elif WASM #endif