diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2025-04-07 18:53:49 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2025-04-07 18:53:49 +0100 | 
| commit | d0863cbc9e6276776eecfbdab3f95e3bf33cfeef (patch) | |
| tree | 0a542b8f4d6cfc31954b61d1fee818c0599a3fbc | |
| parent | bd31dd79eb31b76f3d7276be8dfaff21f615b1da (diff) | |
| download | ldjam57-main.tar | |
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | res/tutorial_black_white.png | bin | 0 -> 595 bytes | |||
| -rw-r--r-- | res/tutorial_blue_1.png | bin | 0 -> 585 bytes | |||
| -rw-r--r-- | res/tutorial_blue_2.png | bin | 0 -> 588 bytes | |||
| -rw-r--r-- | res/tutorial_blue_clone.png | bin | 0 -> 573 bytes | |||
| -rw-r--r-- | res/tutorial_direction_red.png | bin | 0 -> 601 bytes | |||
| -rw-r--r-- | res/tutorial_red_yellow.png | bin | 0 -> 572 bytes | |||
| -rw-r--r-- | src/all.c | 21 | ||||
| -rw-r--r-- | src/index.html.in | 105 | ||||
| -rw-r--r-- | src/tick.c | 2 | ||||
| -rw-r--r-- | src/types.c | 4 | 
11 files changed, 118 insertions, 19 deletions
| @@ -22,7 +22,10 @@ build/main.wasm.b64: build/main.wasm  build/index.html: src/index.html.in build/main.wasm.b64 build/music.mp3.b64 \  		build/continue.png.b64 build/exit.png.b64 build/pause.png.b64 build/play.png.b64 build/restart.png.b64 \  		build/nelson.png.b64 build/nelson_left.png.b64 build/nelson_up.png.b64 \ -		build/nelson_right.png.b64 build/nelson_down.png.b64 +		build/nelson_right.png.b64 build/nelson_down.png.b64 \ +		build/tutorial_black_white.png.b64 build/tutorial_red_yellow.png.b64 \ +		build/tutorial_direction_red.png.b64 build/tutorial_blue_1.png.b64 \ +		build/tutorial_blue_2.png.b64 build/tutorial_blue_clone.png.b64  	mkdir -p build  	clang -E -P -undef -nostdinc -x c -o build/index.html src/index.html.in diff --git a/res/tutorial_black_white.png b/res/tutorial_black_white.pngBinary files differ new file mode 100644 index 0000000..990804a --- /dev/null +++ b/res/tutorial_black_white.png diff --git a/res/tutorial_blue_1.png b/res/tutorial_blue_1.pngBinary files differ new file mode 100644 index 0000000..b289564 --- /dev/null +++ b/res/tutorial_blue_1.png diff --git a/res/tutorial_blue_2.png b/res/tutorial_blue_2.pngBinary files differ new file mode 100644 index 0000000..0c82bb2 --- /dev/null +++ b/res/tutorial_blue_2.png diff --git a/res/tutorial_blue_clone.png b/res/tutorial_blue_clone.pngBinary files differ new file mode 100644 index 0000000..c8edb68 --- /dev/null +++ b/res/tutorial_blue_clone.png diff --git a/res/tutorial_direction_red.png b/res/tutorial_direction_red.pngBinary files differ new file mode 100644 index 0000000..7ade0dc --- /dev/null +++ b/res/tutorial_direction_red.png diff --git a/res/tutorial_red_yellow.png b/res/tutorial_red_yellow.pngBinary files differ new file mode 100644 index 0000000..6d56825 --- /dev/null +++ b/res/tutorial_red_yellow.png @@ -390,8 +390,10 @@ static void restart_level(Game* game) {  	xmemcpy(&game->state.placeableCells, &levels[level].placeableCells, sizeof(game->state.placeableCells));  } -static void update(Game *game, uint64_t now, Arena a) { +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) {  		int x, y; @@ -451,6 +453,7 @@ static void update(Game *game, uint64_t now, Arena a) {  							restart_level(game);  							break;  						case BUTTON_BACK: +							tutorial = 1;  							break;  						case BUTTON_PLAY:  							game->state.playing = !game->state.playing; @@ -495,6 +498,8 @@ static void update(Game *game, uint64_t now, Arena a) {  		tick(game, a);  	} + +	return tutorial;  }  #if SDL @@ -677,10 +682,12 @@ void game_init(void) {  	perm.end = heap + MEM_SIZE;  	game = new(&perm, 1, Game); -	xmemcpy(&game->state.grid, &levels[0].grid, sizeof(game->state.grid)); -	game->state.goalx = levels[0].goalx; -	game->state.goaly = levels[0].goaly; -	game->state.playing = 0; +	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"))) @@ -694,11 +701,11 @@ DrawList *game_render(int width, int height, int mousex, int mousey) {  }  __attribute((export_name("game_update"))) -void game_update(int input, int mousex, int mousey, int now) { +int game_update(int input, int mousex, int mousey, int now) {  	game->input = input;  	game->ui.mousex = mousex;  	game->ui.mousey = mousey; -	update(game, now, perm); +	return update(game, now, perm);  }  #endif diff --git a/src/index.html.in b/src/index.html.in index 46d39e4..5414f09 100644 --- a/src/index.html.in +++ b/src/index.html.in @@ -11,9 +11,9 @@ html, body {      overflow: hidden;      text-align: center;      width: 100%; +		color: white;  }  h1 { -    color: white;      margin: 0;  }  button { @@ -22,9 +22,84 @@ button {      margin: 0.3em;      width: 25%;  } + +canvas { +	margin: auto; +}  </style> -<canvas></canvas> +<div id="tutorial" style="overflow-y: scroll; height: 90vh"> +	<h1>Depths of the Mind</h1> + +	<p> +		The mind is an intricate thing, with many tiny components working together +		in perfect harmony... Until something came in and messed everything up! +	</p> + +	<p> +		If you want to set all the pieces of the mind right, you'll need to know how +		it works! +	</p> + +	<img src= +#include "../build/tutorial_black_white.png.b64" +			> + +	<p> +		The structure of the brain consists of black blocks filling a white void. +	</p> + +	<img src= +#include "../build/tutorial_red_yellow.png.b64" +			> + +	<p> +		Black blocks will turn red when clicked (if you have red in your inventory on the left). +		While the brain is running, black blocks next to red blocks will turn red! +		Red blocks will eventually tire to yellow, and then back to black. They don't stay red very long! +		This is what allows the brain to send signals along a series of black blocks. +		Yellow blocks can be placed with a right click on a black block (if you have one in your inventory) +	</p> + +	<img src= +#include "../build/tutorial_direction_red.png.b64" +			 > + +	<p> +		Sometimes, only one side of a block turns red. +		When this happens, it will try to move in that direction (and leave a yellow behind it) +		but if it cannot it will turn clockwise and try again. +	</p> + +	<span> +		<img src= +#include "../build/tutorial_blue_1.png.b64" +				 > +		<img src= +#include "../build/tutorial_blue_2.png.b64" +				 > + +	<p> +		Blue blocks need to be moved around to keep things running smoothly! +		When a blue block is touched by a single red block, it will start rolling +		away from it. +		Each level has a goal in faint red which needs at least one blue block to be delivered to it. +		Some levels will also have faint blue areas that create new blue blocks for you! +	</p> + +		<img src= +#include "../build/tutorial_blue_clone.png.b64" +				 > + +	<p> +		Finally, if a blue block touches a red block <em>while in motion</em> it will be cloned! +		One will be left behind and the other will continue. +	</p> + +	<button id="play-button">Play!</button> +</div> + +<canvas style="display: none;"></canvas>  <script>  // Mirror these in src/all.c @@ -73,6 +148,7 @@ async function main() {      let exports = wasm.exports;      let html    = document.querySelector("html");      let canvas  = document.querySelector("canvas"); +	const tutorial = document.querySelector("#tutorial");      let ctx     = canvas.getContext("2d");      let memory  = exports.memory; @@ -140,11 +216,18 @@ async function main() {      window.addEventListener("resize", onresize);      onresize(); +	function doUpdate(input) { +		if (exports.game_update(input, mousex, mousey, now()) !== 0) { +			canvas.style.display = "none"; +			tutorial.style.display = "block"; +		} +	} +  	canvas.addEventListener("mousemove", function(e) {  		const rect = e.target.getBoundingClientRect();  		mousex = e.clientX - rect.left;  		mousey = e.clientY - rect.top; -		exports.game_update(INPUT_MOVE, mousex, mousey, now()); +		doUpdate(INPUT_MOVE);  	});  	canvas.addEventListener("mousedown", function(e) { @@ -152,15 +235,21 @@ async function main() {  		mousex = e.clientX - rect.left;  		mousey = e.clientY - rect.top;  		if (e.button == 0) { -			exports.game_update(INPUT_CLICK, mousex, mousey, now()); +			doUpdate(INPUT_CLICK);  		} else if (e.button == 2) {  			e.preventDefault(); -			exports.game_update(INPUT_RCLICK, mousex, mousey, now()); +			doUpdate(INPUT_RCLICK);  		} +	}); + +	document.getElementById("play-button").addEventListener("click", function (e) {  		if (!musicPlaying) {  			musicPlaying = true;  			audio.play();  		} + +		canvas.style.display = "block"; +		tutorial.style.display = "none";  	});  	canvas.addEventListener("contextmenu", function (e) { @@ -169,16 +258,16 @@ async function main() {  	document.addEventListener("keydown", function (e) {  		if (e.key === " ") { -			exports.game_update(INPUT_PAUSE_PLAY, mousex, mousey, now()); +			doUpdate(INPUT_PAUSE_PLAY);  		} else if (e.key == "r") { -			exports.game_update(INPUT_RESTART, mousex, mousey, now()); +			doUpdate(INPUT_RESTART);  		}  	});      function animate() {          // TODO: stop requesting frames when state is static          requestAnimationFrame(animate); -        exports.game_update(INPUT_NONE, mousex, mousey, now()); +				doUpdate(INPUT_NONE);          render();      }      requestAnimationFrame(animate); @@ -178,7 +178,7 @@ static void tick(Game *game, Arena a) {  						(y > 0 && lastState->grid[x + (y - 1) * GRIDWIDTH] == BLUE_DOWN) ||  						(y < GRIDHEIGHT - 1 && lastState->grid[x + (y + 1) * GRIDWIDTH] == BLUE_UP)  					) { -						game->state.grid[x + y * GRIDWIDTH] = RED; +						game->state.grid[x + y * GRIDWIDTH] = BLACK; // used to be RED  					} else {  						game->state.grid[x + y * GRIDWIDTH] = BLACK;  					} diff --git a/src/types.c b/src/types.c index bf6dcf4..c40d9c3 100644 --- a/src/types.c +++ b/src/types.c @@ -70,11 +70,11 @@ enum {  };  static const char colorImages[N_COLORS] = { -	[RED] = IMAGE_NELSON, +	/*[RED] = IMAGE_NELSON,  	[RED_LEFT] = IMAGE_NELSON_LEFT,  	[RED_UP] = IMAGE_NELSON_UP,  	[RED_RIGHT] = IMAGE_NELSON_RIGHT, -	[RED_DOWN] = IMAGE_NELSON_DOWN, +	[RED_DOWN] = IMAGE_NELSON_DOWN,*/  };  enum { | 
