diff options
-rw-r--r-- | src/all.c | 103 | ||||
-rw-r--r-- | src/index.html.in | 18 |
2 files changed, 97 insertions, 24 deletions
@@ -1,13 +1,6 @@ #include <stddef.h> #include <stdint.h> -#if SDL -#include <string.h> -#define xmemcpy memcpy -#else -#define xmemcpy __builtin_memcpy -#endif - #define MEM_SIZE (1<<24) #define GRIDWIDTH 16 #define GRIDHEIGHT 16 @@ -36,6 +29,12 @@ typedef struct { #define new(a, c, t) ((t *) alloc(a, c, sizeof(t), _Alignof(t))) #define affirm(c) while (!(c)) *(volatile int *)0 = 0 +static void xmemcpy(void *dst, void *src, ptrdiff_t size) { + for (ptrdiff_t i = 0; i < size; i++) { + ((char *) dst)[i] = ((char *) src)[i]; + } +} + 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); @@ -77,6 +76,8 @@ enum { BLACK, RED, YELLOW, + RED_UP, + RED_DOWN, RED_LEFT, RED_RIGHT, N_COLORS, @@ -109,6 +110,18 @@ static const Color colors[N_COLORS][4] = { }, { {255, 0, 0, 255}, + {255, 0, 0, 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}, {0, 0, 0, 255}, {255, 0, 0, 255}, {0, 0, 0, 255}, @@ -180,23 +193,49 @@ static void update(Game *game, uint64_t now, Arena a) { for (int x = 0; x < GRIDWIDTH; x++) { for (int y = 0; y < GRIDHEIGHT; y++) { switch (lastState->grid[x + y * GRIDWIDTH]) { + int reds, red; case BLACK: + reds = 0; if ( - x < GRIDWIDTH - 1 && - lastState->grid[x + 1 + y * GRIDWIDTH] == RED_LEFT + x < GRIDWIDTH - 1 && ( + lastState->grid[x + 1 + y * GRIDWIDTH] == RED_LEFT || + lastState->grid[x + 1 + y * GRIDWIDTH] == RED + ) ) { - game->state.grid[x + y * GRIDWIDTH] = RED_LEFT; - } else if ( - x > 0 && - lastState->grid[x - 1 + y * GRIDWIDTH] == RED_RIGHT + reds++; + red = lastState->grid[x + 1 + y * GRIDWIDTH]; + } + if ( + x > 0 && ( + lastState->grid[x - 1 + y * GRIDWIDTH] == RED_RIGHT || + lastState->grid[x - 1 + y * GRIDWIDTH] == RED + ) ) { - game->state.grid[x + y * GRIDWIDTH] = RED_RIGHT; - } else if ( - (x > 0 && lastState->grid[x - 1 + y * GRIDWIDTH] == RED) || - (x < GRIDWIDTH - 1 && lastState->grid[x + 1 + y * GRIDWIDTH] == RED) || - (y > 0 && lastState->grid[x + (y - 1) * GRIDWIDTH] == RED) || - (y < GRIDHEIGHT - 1 && lastState->grid[x + (y + 1) * GRIDWIDTH] == RED) + reds++; + red = lastState->grid[x - 1 + y * GRIDWIDTH]; + } + if ( + y > 0 && ( + lastState->grid[x + (y - 1) * GRIDWIDTH] == RED_DOWN || + lastState->grid[x + (y - 1) * GRIDWIDTH] == RED + ) + ) { + reds++; + red = lastState->grid[x + (y - 1) * GRIDWIDTH]; + } + if ( + y < GRIDHEIGHT - 1 && ( + lastState->grid[x + (y + 1) * GRIDWIDTH] == RED_UP || + lastState->grid[x + (y + 1) * GRIDWIDTH] == RED + ) ) { + reds++; + red = lastState->grid[x + (y + 1) * GRIDWIDTH]; + } + + if (reds == 1) { + game->state.grid[x + y * GRIDWIDTH] = red; + } else if (reds >= 2) { game->state.grid[x + y * GRIDWIDTH] = RED; } break; @@ -210,7 +249,7 @@ static void update(Game *game, uint64_t now, Arena a) { ) { game->state.grid[x + y * GRIDWIDTH] = YELLOW; } else { - game->state.grid[x + y * GRIDWIDTH] = RED_RIGHT; + game->state.grid[x + y * GRIDWIDTH] = RED_UP; } break; case RED_RIGHT: @@ -220,6 +259,26 @@ static void update(Game *game, uint64_t now, Arena a) { ) { game->state.grid[x + y * GRIDWIDTH] = YELLOW; } else { + game->state.grid[x + y * GRIDWIDTH] = RED_DOWN; + } + break; + case RED_UP: + if ( + y > 0 && + lastState->grid[x + (y - 1) * GRIDWIDTH] == BLACK + ) { + game->state.grid[x + y * GRIDWIDTH] = YELLOW; + } else { + game->state.grid[x + y * GRIDWIDTH] = RED_RIGHT; + } + break; + case RED_DOWN: + if ( + y < GRIDHEIGHT - 1 && + lastState->grid[x + (y + 1) * GRIDWIDTH] == BLACK + ) { + game->state.grid[x + y * GRIDWIDTH] = YELLOW; + } else { game->state.grid[x + y * GRIDWIDTH] = RED_LEFT; } break; @@ -357,11 +416,11 @@ DrawList *game_render(int width, int height) { } __attribute((export_name("game_update"))) -void game_update(int input, int mousex, int mousey) { +void game_update(int input, int mousex, int mousey, int now) { game->input = input; game->mousex = mousex; game->mousey = mousey; - update(game, perm); + update(game, now, perm); } #endif diff --git a/src/index.html.in b/src/index.html.in index 07bd618..a58354a 100644 --- a/src/index.html.in +++ b/src/index.html.in @@ -30,6 +30,7 @@ button { // Mirror these in src/all.c const INPUT_NONE = 0; const INPUT_CLICK = 1; +const INPUT_PAUSE_PLAY = 2; const WASM = #include "../build/main.wasm.b64" @@ -46,6 +47,11 @@ async function main() { let ctx = canvas.getContext("2d"); let memory = exports.memory; + const start = Date.now(); + function now() { + return Date.now() - start; + } + function min(a, b) { return b<a ? b : a; } @@ -66,8 +72,10 @@ async function main() { let op = ops.subarray(6*i, 6*i+6); const color = new Uint8Array(new Uint32Array(op.subarray(4, 6)).buffer); ctx.fillStyle = `#${color[0].toString(16).padStart(2, "0")}${color[1].toString(16).padStart(2, "0")}${color[2].toString(16).padStart(2, "0")}`; + ctx.globalAlpha = color[3] / 255; ctx.fillRect(op[0], op[1], op[2], op[3]); ctx.strokeStyle = `#${color[4].toString(16).padStart(2, "0")}${color[5].toString(16).padStart(2, "0")}${color[6].toString(16).padStart(2, "0")}`; + ctx.globalAlpha = color[7] / 255; ctx.strokeRect(op[0], op[1], op[2], op[3]); } } @@ -80,14 +88,20 @@ async function main() { const mousex = e.clientX; const mousey = e.clientY; if (e.button == 0) { - exports.game_update(INPUT_CLICK, mousex, mousey); + exports.game_update(INPUT_CLICK, mousex, mousey, now()); + } + }); + + document.addEventListener("keydown", function (e) { + if (e.key === " ") { + exports.game_update(INPUT_PAUSE_PLAY, 0, 0, now()); } }); function animate() { // TODO: stop requesting frames when state is static requestAnimationFrame(animate); - exports.game_update(INPUT_NONE, 0, 0); + exports.game_update(INPUT_NONE, 0, 0, now()); render(); } requestAnimationFrame(animate); |