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); | 
