diff options
Diffstat (limited to 'src/all.c')
-rw-r--r-- | src/all.c | 692 |
1 files changed, 592 insertions, 100 deletions
@@ -1,103 +1,525 @@ +#ifndef INCLUDE_ALL_C +#define INCLUDE_ALL_C + #include <stddef.h> #include <stdint.h> -typedef struct { - int x, y, w, h; - unsigned char r, g, b, a; -} DrawElement; +#include "types.c" +#include "levels.c" +#include "tick.c" + +static const Color colors[N_COLORS][4] = { + { + {255, 255, 255, 255}, + {255, 255, 255, 255}, + {255, 255, 255, 255}, + {255, 255, 255, 255}, + }, + { + {0, 0, 0, 255}, + {0, 0, 0, 255}, + {0, 0, 0, 255}, + {0, 0, 0, 255}, + }, + { + {255, 0, 0, 255}, + {255, 0, 0, 255}, + {255, 0, 0, 255}, + {255, 0, 0, 255}, + }, + { + {255, 255, 0, 255}, + {255, 255, 0, 255}, + {255, 255, 0, 255}, + {255, 255, 0, 255}, + }, + { + {255, 0, 0, 255}, + {255, 0, 0, 255}, + {255, 255, 0, 255}, + {255, 255, 0, 255}, + }, + { + {255, 255, 0, 255}, + {255, 255, 0, 255}, + {255, 0, 0, 255}, + {255, 0, 0, 255}, + }, + { + {255, 0, 0, 255}, + {255, 255, 0, 255}, + {255, 0, 0, 255}, + {255, 255, 0, 255}, + }, + { + {255, 255, 0, 255}, + {255, 0, 0, 255}, + {255, 255, 0, 255}, + {255, 0, 0, 255}, + }, + { + {0, 0, 255, 255}, + {0, 0, 255, 255}, + {0, 0, 255, 255}, + {0, 0, 255, 255}, + }, + { + {0, 0, 255, 255}, + {0, 0, 255, 255}, + {255, 255, 255, 255}, + {255, 255, 255, 255}, + }, + { + {255, 255, 255, 255}, + {255, 255, 255, 255}, + {0, 0, 255, 255}, + {0, 0, 255, 255}, + }, + { + {0, 0, 255, 255}, + {255, 255, 255, 255}, + {0, 0, 255, 255}, + {255, 255, 255, 255}, + }, + { + {255, 255, 255, 255}, + {0, 0, 255, 255}, + {255, 255, 255, 255}, + {0, 0, 255, 255}, + }, +}; -typedef struct { - int len; - DrawElement els[256]; -} DrawList; +#define BUTTON_SIZE 32 +#define BUTTON_SPACING 16 +#define BUTTON_SPACER(i) (BUTTON_SPACING + BUTTON_SIZE + (BUTTON_SIZE * (i) + (i) * BUTTON_SPACING)) -#define MEM_SIZE (1<<16) +// reverse order as they're anchored to bottom +static const Button buttons[N_BUTTONS] = { + [BUTTON_BACK] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_BACK), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_RETRY] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_RETRY), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_PLAY] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_PLAY), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_CONTINUE] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_CONTINUE), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, +}; -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; +// This returns a positive color index or a negated image index +static int getPlaceAction(int currentColor, int cellx, int celly, float cellWidth, float cellHeight) { + int hoverColor = EMPTY; + + // TODO yellow when there are no reds available + switch (currentColor) { + case BLACK: + if (cellx < cellWidth / 4 && cellx < celly && cellx < cellHeight - celly) { + hoverColor = RED_LEFT; + } else if (celly < cellHeight / 4 && celly < cellx && celly < cellWidth - cellx) { + hoverColor = RED_UP; + } else if (cellx > cellWidth / 4 * 3 && cellWidth - cellx < celly && cellWidth - cellx < cellHeight - celly) { + hoverColor = RED_RIGHT; + } else if (celly > cellHeight / 4 * 3 && cellHeight - celly < cellx && cellHeight - celly < cellWidth - cellx) { + hoverColor = RED_DOWN; + } else { + hoverColor = RED; + } + break; + case EMPTY: + hoverColor = BLACK; + break; } - return r; + return hoverColor; } -typedef struct { - int width, height; -} UI; +static DrawList *render(State *state, UI *ui, Arena *a) { + DrawList *drawList = new(a, 1, DrawList); -typedef struct { - int x, y; -} State; - -// Mirror these in src/index.html.in -enum { - INPUT_NONE, - INPUT_UP, - INPUT_DOWN, - INPUT_LEFT, - INPUT_RIGHT, -}; + float cellWidth = (float) (ui->width - GRID_OFFSET_X) / GRIDWIDTH; + float cellHeight = (float) ui->height / GRIDHEIGHT; + + // Actual cells + for (int x = 0; x < GRIDWIDTH; x++) { + for (int y = 0; y < GRIDHEIGHT; y++) { + if (colorImages[(int) state->grid[x + GRIDWIDTH * y]]) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * x + GRID_OFFSET_X, + .y = cellHeight * y, + .w = cellWidth, + .h = cellHeight, + .image = (ImageRef) { + .index = colorImages[(int) state->grid[x + GRIDWIDTH * y]], + .opacity = 255, + }, + }; + } else { + for (int subx = 0; subx < 2; subx++) { + for (int suby = 0; suby < 2; suby++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * x + GRID_OFFSET_X + subx * cellWidth / 2, + .y = cellHeight * y + suby * cellHeight / 2, + .w = cellWidth / 2 + (1 - subx), + .h = cellHeight / 2 + (1 - suby), + .fill = colors[(int) state->grid[x + GRIDWIDTH * y]][subx + 2 * suby], + }; + } + } + } + } + } -typedef struct { - State state; - UI ui; - int input; -} Game; + // Vertical grid lines + for (int x = 1; x < GRIDWIDTH; x++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * x + GRID_OFFSET_X, + .y = 0, + .w = 1, + .h = ui->height, + .fill = {0, 0, 0, 255}, + }; + } + + // Horizontal grid lines + for (int y = 1; y < GRIDHEIGHT; y++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = GRID_OFFSET_X, + .y = y * cellHeight, + .w = ui->width - GRID_OFFSET_X, + .h = 1, + .fill = {0, 0, 0, 255}, + }; + } -static DrawList *render(State state, UI *ui, Arena *a) { - (void) ui; + // Spawner + if (state->spawnerx != 0 && state->spawnery != 0) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * state->spawnerx + GRID_OFFSET_X, + .y = cellHeight * state->spawnery, + .w = cellWidth, + .h = cellHeight, + .fill = {0, 0, 255, 63}, + .border = {0, 0, 255, 255}, + }; + } - DrawList *drawList = new(a, 1, DrawList); - drawList->len = 1; - drawList->els[0] = (DrawElement) { - .x = state.x, - .y = state.y, - .w = 100, - .h = 100, - .r = 255, - .g = 0, - .b = 0, - .a = 255, + // Goal + if (state->levelComplete) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * state->goalx + GRID_OFFSET_X, + .y = cellHeight * state->goaly, + .w = cellWidth, + .h = cellHeight, + .fill = {0, 255, 0, 63}, + .border = {0, 255, 0, 255}, + }; + } else { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * state->goalx + GRID_OFFSET_X, + .y = cellHeight * state->goaly, + .w = cellWidth, + .h = cellHeight, + .fill = {255, 0, 0, 63}, + .border = {255, 0, 0, 255}, + }; + + if (state->need9) { + for (int i = 0; i < state->blues; i++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * state->goalx + GRID_OFFSET_X + cellWidth / 3 * (i % 3), + .y = cellHeight * state->goaly + cellHeight / 3 * (i / 3), + .w = cellWidth / 3, + .h = cellHeight / 3, + .fill = {196, 255, 196, 255}, + .border = {0, 200, 0, 255}, + }; + } + } + } + + // Hover + if (ui->mousex >= GRID_OFFSET_X) { + int hoverx = (ui->mousex - GRID_OFFSET_X) * GRIDWIDTH / (ui->width - GRID_OFFSET_X); + int hovery = ui->mousey * GRIDHEIGHT / ui->height; + + int cellx = ui->mousex - GRID_OFFSET_X - hoverx * cellWidth; + int celly = ui->mousey - hovery * cellHeight; + + int hoverColor = getPlaceAction( + state->grid[hoverx + hovery * GRIDWIDTH], + cellx, + celly, + cellWidth, + cellHeight + ); + + if (hoverColor != EMPTY) { + for (int i = 0; i < MAX_PLACEABLE_CELLS; i++) { + if (state->placeableCells[i] == hoverColor) { + if (colorImages[hoverColor]) { + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * hoverx + GRID_OFFSET_X, + .y = cellHeight * hovery, + .w = cellWidth, + .h = cellHeight, + .image = { + .index = colorImages[hoverColor], + .opacity = 127, + }, + }; + } else { + int subCellWidth = cellWidth / 2; + int subCellHeight = cellHeight / 2; + for (int subx = 0; subx < 2; subx++) { + for (int suby = 0; suby < 2; suby++) { + Color fill = colors[hoverColor][subx + 2 * suby]; + fill.a = 127; + drawList->els[drawList->len++] = (DrawElement) { + .x = cellWidth * hoverx + GRID_OFFSET_X + (subx * subCellWidth), + .y = cellHeight * hovery + (suby * subCellHeight), + .w = subCellWidth, + .h = subCellHeight, + .fill = fill, + }; + } + } + } + break; + } + } + } + } + + // Side panel + drawList->els[drawList->len++] = (DrawElement) { + .x = 0, + .y = 0, + .w = GRID_OFFSET_X, + .h = ui->height, + .fill = {100, 100, 100, 255}, + .border = {0, 0, 0, 255}, }; + // render buttons + for (int i = 0; i < N_BUTTONS; i++) { + Color colour = {0, 0, 0, 255}; + switch (state->buttonStates[i]) { + case BUTTON_STATE_IDLE: + colour = (Color) {0, 0, 0, 255}; + break; + case BUTTON_STATE_HOVERED: + colour = (Color) {255, 255, 0, 255}; + break; + case BUTTON_STATE_PRESSED: + colour = (Color) {255, 0, 0, 255}; + break; + } + int image = IMAGE_NULL; + switch (i) { + case BUTTON_CONTINUE: + image = IMAGE_CONTINUE; + break; + case BUTTON_BACK: + image = IMAGE_EXIT; + break; + case BUTTON_RETRY: + image = IMAGE_RETRY; + break; + case BUTTON_PLAY: + image = state->playing ? IMAGE_PAUSE : IMAGE_PLAY; + break; + } + Color fill = {0}; + if (i == BUTTON_CONTINUE && state->levelComplete) { + fill = (Color) {127, 255, 127, 200}; + }; + drawList->els[drawList->len++] = (DrawElement) { + .x = buttons[i].x, + .y = ui->height - buttons[i].y, + .w = buttons[i].w, + .h = buttons[i].h, + .fill = fill, + .image = (ImageRef) { + .index = image, + .opacity = 255, + }, + }; + } + + // Placeable cells + for (int i = 0; i < MAX_PLACEABLE_CELLS; i++) { + if (state->placeableCells[i] == EMPTY) { + break; + } + + if (colorImages[(int) state->placeableCells[i]]) { + drawList->els[drawList->len++] = (DrawElement) { + .x = BUTTON_SIZE / 2, + .y = BUTTON_SIZE / 2 + i * (BUTTON_SIZE + BUTTON_SPACING), + .w = BUTTON_SIZE, + .h = BUTTON_SIZE, + .image = { + .index = colorImages[(int) state->placeableCells[i]], + .opacity = 255, + }, + }; + } else { + for (int x = 0; x < 2; x++) { + for (int y = 0; y < 2; y++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = BUTTON_SIZE / 2 + x * (BUTTON_SIZE / 2), + .y = BUTTON_SIZE / 2 + i * (BUTTON_SIZE + BUTTON_SPACING) + y * (BUTTON_SIZE / 2), + .w = BUTTON_SIZE / 2, + .h = BUTTON_SIZE / 2, + .fill = colors[(int) state->placeableCells[i]][x + 2 * y], + }; + } + } + } + } + return drawList; } -static void update(Game *game, Arena a) { +static void restart_level(Game* game) { + const int level = game->state.currentLevel; + xmemcpy(&game->state.grid, &levels[level].grid, sizeof(game->state.grid)); + game->state.goalx = levels[level].goalx; + game->state.goaly = levels[level].goaly; + game->state.spawnerx = levels[level].spawnerx; + game->state.spawnery = levels[level].spawnery; + game->state.spawnerCount = 0; + game->state.playing = 0; + game->state.blues = 0; + game->state.need9 = levels[level].need9; + xmemcpy(&game->state.placeableCells, &levels[level].placeableCells, sizeof(game->state.placeableCells)); +} + +static int update(Game *game, uint64_t now, Arena a) { + const int offset_width = game->ui.width - GRID_OFFSET_X; + + int tutorial = 0; + switch (game->input) { - case INPUT_UP: - game->state.y -= 20; + int x, y; + case INPUT_CLICK: + x = (game->ui.mousex - GRID_OFFSET_X) * GRIDWIDTH / offset_width; + y = game->ui.mousey * GRIDHEIGHT / game->ui.height; + if (game->ui.mousex >= GRID_OFFSET_X) { + float cellWidth = (float) (game->ui.width - GRID_OFFSET_X) / GRIDWIDTH; + float cellHeight = (float) game->ui.height / GRIDHEIGHT; + int cellx = game->ui.mousex - GRID_OFFSET_X - x * cellWidth; + int celly = game->ui.mousey - y * cellHeight; + // Keeping this around for testing purposes + // game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); + char placed = getPlaceAction( + game->state.grid[x + y * GRIDWIDTH], + cellx, + celly, + cellWidth, + cellHeight + ); + + if (placed != EMPTY) { + for (int i = 0; i < MAX_PLACEABLE_CELLS; i++) { + if (game->state.placeableCells[i] == placed) { + game->state.grid[x + y * GRIDWIDTH] = placed; + for (int j = i; j < MAX_PLACEABLE_CELLS - 1; j++) { + game->state.placeableCells[j] = game->state.placeableCells[j + 1]; + } + game->state.placeableCells[MAX_PLACEABLE_CELLS - 1] = EMPTY; + break; + } + } + } + } + + for (int i = 0; i < N_BUTTONS; i++) { + if ( + game->ui.mousex > buttons[i].x && game->ui.mousex < buttons[i].x + buttons[i].w && + game->ui.mousey > game->ui.height - buttons[i].y && + game->ui.mousey < game->ui.height - buttons[i].y + buttons[i].h + ) { + // TODO - CLICK THINGS + //game->state.buttonStates[i] = BUTTON_STATE_PRESSED; + switch (i) { + case BUTTON_RETRY: + restart_level(game); + break; + case BUTTON_CONTINUE: + if ( + !game->state.levelComplete || + game->state.currentLevel + 1 >= sizeof(levels) / sizeof(levels[0]) + ) { + break; + } + game->state.levelComplete = 0; + game->state.currentLevel++; + restart_level(game); + break; + case BUTTON_BACK: + tutorial = 1; + break; + case BUTTON_PLAY: + game->state.playing = !game->state.playing; + break; + } + } + } break; - case INPUT_DOWN: - game->state.y += 20; + case INPUT_RCLICK: + if (game->ui.mousex > GRID_OFFSET_X) { + x = (game->ui.mousex - GRID_OFFSET_X) * GRIDWIDTH / (game->ui.width - GRID_OFFSET_X); + y = game->ui.mousey * GRIDHEIGHT / game->ui.height; + + if (game->state.grid[x + y * GRIDWIDTH] != BLACK) { + break; + } + + for (int i = 0; i < MAX_PLACEABLE_CELLS; i++) { + if (game->state.placeableCells[i] == YELLOW) { + game->state.grid[x + y * GRIDWIDTH] = YELLOW; + for (int j = i; j < MAX_PLACEABLE_CELLS - 1; j++) { + game->state.placeableCells[j] = game->state.placeableCells[j + 1]; + } + game->state.placeableCells[MAX_PLACEABLE_CELLS - 1] = EMPTY; + break; + } + } + } break; - case INPUT_LEFT: - game->state.x -= 20; + case INPUT_PAUSE_PLAY: + game->state.playing = !game->state.playing; break; - case INPUT_RIGHT: - game->state.x += 20; + case INPUT_RESTART: + restart_level(game); break; default: break; } + + if (game->state.playing && game->state.lastTick + TICK_LENGTH <= now) { + game->state.lastTick = now; + + tick(game, a); + } + + return tutorial; } #if SDL #include <SDL3/SDL.h> +typedef struct { + int width, height; + Color colors[16]; + const char *pixels; +} Image; + +#include "../build/images.c" + +SDL_Texture *textures[sizeof(images) / sizeof(images[0])]; + +#include "../build/music.c" + +SDL_AudioStream *stream; + int main(int argc, char **argv) { (void) argc; (void) argv; @@ -109,76 +531,138 @@ int main(int argc, char **argv) { }; Game *game = new(&a, 1, Game); - game->state = (State) { - .x = 100, - .y = 100, - }; + game->state.currentLevel = 0; + restart_level(game); game->ui = (UI) { .width = 640, .height = 480, + .mousex = 0, + .mousey = 0, }; + for (int i = 0; i < N_BUTTONS; i++) { + game->state.buttonStates[i] = BUTTON_STATE_IDLE; + } - SDL_Init(SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); SDL_Window *w = SDL_CreateWindow( "LDJam 57", game->ui.width, game->ui.height, - 0 + SDL_WINDOW_RESIZABLE ); 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); + SDL_SetRenderDrawBlendMode(r, SDL_BLENDMODE_BLEND); + + for (int j = 1; j < (int) (sizeof(images) / sizeof(images[0])); j++) { + textures[j] = SDL_CreateTexture( + r, + SDL_PIXELFORMAT_ABGR8888, + SDL_TEXTUREACCESS_STATIC, + images[j].width, + images[j].height + ); + SDL_SetTextureScaleMode(textures[j], SDL_SCALEMODE_NEAREST); + Arena scratch = a; + Color *pixels = new(&scratch, images[j].width * images[j].height, Color); + for (int i = 0; i < images[j].width * images[j].height; i++) { + pixels[i] = images[j].colors[(int) images[j].pixels[i]]; + } + SDL_UpdateTexture(textures[j], NULL, pixels, images[j].width * 4); + } + + SDL_AudioSpec audioSpec = { + .format = SDL_AUDIO_S16LE, + .channels = 2, + .freq = 48000, + }; + stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audioSpec, NULL, NULL); + SDL_PutAudioStreamData(stream, musicBytes, sizeof(musicBytes)); + SDL_ResumeAudioStreamDevice(stream); for (;;) { + uint64_t now = SDL_GetTicks(); game->input = INPUT_NONE; SDL_Event e = {0}; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_EVENT_QUIT: return 0; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + game->ui.mousex = (int) e.button.x; + game->ui.mousey = (int) e.button.y; + if (e.button.button == 1) { + game->input = INPUT_CLICK; + } else if (e.button.button == 3) { + game->input = INPUT_RCLICK; + } + break; + case SDL_EVENT_MOUSE_MOTION: + game->ui.mousex = (int) e.motion.x; + game->ui.mousey = (int) e.motion.y; + game->input = INPUT_MOVE; + break; case SDL_EVENT_KEY_DOWN: switch (e.key.key) { - case 'w': - game->input = INPUT_UP; - break; - case 'a': - game->input = INPUT_LEFT; + case SDLK_SPACE: + game->input = INPUT_PAUSE_PLAY; break; - case 's': - game->input = INPUT_DOWN; - break; - case 'd': - game->input = INPUT_RIGHT; + case SDLK_R: + game->input = INPUT_RESTART; break; } break; + case SDL_EVENT_WINDOW_RESIZED: + SDL_GetWindowSize(w, &game->ui.width, &game->ui.height); + break; } } Arena scratch = a; - DrawList *drawList = render(game->state, &game->ui, &scratch); + 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].r, - drawList->els[i].g, - drawList->els[i].b, - drawList->els[i].a - ); SDL_FRect rect = { .x = (float) drawList->els[i].x, .y = (float) drawList->els[i].y, .w = (float) drawList->els[i].w, .h = (float) drawList->els[i].h }; + + SDL_SetRenderDrawColor( + r, + drawList->els[i].fill.r, + drawList->els[i].fill.g, + drawList->els[i].fill.b, + drawList->els[i].fill.a + ); SDL_RenderFillRect(r, &rect); + + SDL_SetRenderDrawColor( + r, + drawList->els[i].border.r, + drawList->els[i].border.g, + drawList->els[i].border.b, + drawList->els[i].border.a + ); + SDL_RenderRect(r, &rect); + + if (drawList->els[i].image.index != 0) { + SDL_SetTextureAlphaMod(textures[(int) drawList->els[i].image.index], drawList->els[i].image.opacity); + SDL_RenderTexture(r, textures[(int) drawList->els[i].image.index], NULL, &rect); + } } - update(game, a); + update(game, now, a); + + if (SDL_GetAudioStreamQueued(stream) < (int) sizeof(musicBytes) / 8) { + SDL_PutAudioStreamData(stream, musicBytes, sizeof(musicBytes)); + } SDL_RenderPresent(r); } @@ -198,24 +682,32 @@ void game_init(void) { perm.end = heap + MEM_SIZE; game = new(&perm, 1, Game); - game->state = (State) { - .x = 100, - .y = 100, - }; + game->state.currentLevel = 0; + restart_level(game); + + for (int i = 0; i < N_BUTTONS; i++) { + game->state.buttonStates[i] = BUTTON_STATE_IDLE; + } } __attribute((export_name("game_render"))) -DrawList *game_render(int width, int height) { +DrawList *game_render(int width, int height, int mousex, int mousey) { game->ui.width = width; game->ui.height = height; + game->ui.mousex = mousex; + game->ui.mousey = mousey; Arena scratch = perm; - return render(game->state, &game->ui, &scratch); + return render(&game->state, &game->ui, &scratch); } __attribute((export_name("game_update"))) -void game_update(int input) { +int game_update(int input, int mousex, int mousey, int now) { game->input = input; - update(game, perm); + game->ui.mousex = mousex; + game->ui.mousey = mousey; + return update(game, now, perm); } #endif + +#endif |