diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/all.c | 38 | ||||
-rw-r--r-- | src/img.c | 95 | ||||
-rw-r--r-- | src/index.html.in | 13 | ||||
-rw-r--r-- | src/types.c | 1 |
4 files changed, 146 insertions, 1 deletions
@@ -139,6 +139,7 @@ static DrawList *render(State *state, UI *ui, Arena *a) { .h = cellHeight, .fill = {255, 0, 0, 63}, .border = {255, 0, 0, 255}, + .image = 1, }; drawList->els[drawList->len++] = (DrawElement) { @@ -218,6 +219,16 @@ static void update(Game *game, uint64_t now, Arena a) { #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])]; + int main(int argc, char **argv) { (void) argc; (void) argv; @@ -254,6 +265,23 @@ int main(int argc, char **argv) { 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); + } for (;;) { uint64_t now = SDL_GetTicks(); @@ -289,6 +317,7 @@ int main(int argc, char **argv) { 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_FRect rect = { .x = (float) drawList->els[i].x, @@ -314,6 +343,10 @@ int main(int argc, char **argv) { drawList->els[i].border.a ); SDL_RenderRect(r, &rect); + + if (drawList->els[i].image != 0) { + SDL_RenderTexture(r, textures[drawList->els[i].image], NULL, &rect); + } } update(game, now, a); @@ -336,7 +369,10 @@ void game_init(void) { perm.end = heap + MEM_SIZE; game = new(&perm, 1, Game); - game->state.grid[0] = 1; + 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; } __attribute((export_name("game_render"))) diff --git a/src/img.c b/src/img.c new file mode 100644 index 0000000..09f000b --- /dev/null +++ b/src/img.c @@ -0,0 +1,95 @@ +#define QOI_IMPLEMENTATION +#include "../lib/qoi/qoi.h" + +#include <stdio.h> + +typedef struct { + unsigned char r, g, b, a; +} Color; + +int pixels(char *index, char *filename) { + qoi_desc desc; + Color *pixels = qoi_read(filename, &desc, 4); + + Color colors[16]; + int colorsLen = 0; + char *compressed = malloc(desc.width * desc.height); + + for (int i = 0; i < (int) (desc.width * desc.height); i++) { + char c = -1; + for (int j = 0; j < colorsLen; j++) { + if (*((int *) &colors[j]) == *((int *) pixels + i)) { + c = j; + break; + } + } + if (c == -1) { + c = colorsLen; + if (colorsLen >= 16) { + return 1; + } + colors[colorsLen++] = pixels[i]; + } + compressed[i] = c; + } + + printf("const char imagePixels%s[%d * %d] = {\n", index, desc.width, desc.height); + for (int y = 0; y < (int) desc.height; y++) { + for (int x = 0; x < (int) desc.width; x++) { + printf("%d,", compressed[x + y * desc.width]); + } + printf("\n"); + } + printf("};\n"); + + return 0; +} + +int image(char *index, char *filename) { + qoi_desc desc; + Color *pixels = qoi_read(filename, &desc, 4); + + Color colors[16]; + int colorsLen = 0; + char *compressed = malloc(desc.width * desc.height); + + for (int i = 0; i < (int) (desc.width * desc.height); i++) { + char c = -1; + for (int j = 0; j < colorsLen; j++) { + if (*((int *) &colors[j]) == *((int *) pixels + i)) { + c = j; + break; + } + } + if (c == -1) { + c = colorsLen; + if (colorsLen >= 16) { + return 1; + } + colors[colorsLen++] = pixels[i]; + } + compressed[i] = c; + } + + printf("{\n.width = %d,\n.height = %d,\n.colors = {\n", desc.width, desc.height); + for (int i = 0; i < colorsLen; i++) { + printf("\t{%u, %u, %u, %u},\n", colors[i].r, colors[i].g, colors[i].b, colors[i].a); + } + printf("},\n.pixels = imagePixels%s,\n},\n", index); + + return 0; +} + +int main(int argc, char **argv) { + if (argc != 4) { + return 1; + } + + if (!strcmp(argv[1], "pixels")) { + return pixels(argv[3], argv[2]); + } else if (!strcmp(argv[1], "image")) { + return image(argv[3], argv[2]); + } else { + return 1; + } +} diff --git a/src/index.html.in b/src/index.html.in index 8d0ccea..aca8b6d 100644 --- a/src/index.html.in +++ b/src/index.html.in @@ -36,6 +36,9 @@ const INPUT_PAUSE_PLAY = 3; const WASM = #include "../build/main.wasm.b64" +const MUSIC = +#include "../build/music.mp3.b64" + async function main() { let bytes = Uint8Array.from(atob(WASM), function(c) { return c.charCodeAt(0); @@ -48,6 +51,12 @@ async function main() { let ctx = canvas.getContext("2d"); let memory = exports.memory; + const audio = new Audio(); + audio.src = MUSIC; + audio.volume = 0.2; + audio.loop = true; + let musicPlaying = false; + const start = Date.now(); function now() { return Date.now() - start; @@ -94,6 +103,10 @@ async function main() { e.preventDefault(); exports.game_update(INPUT_RCLICK, mousex, mousey, now()); } + if (!musicPlaying) { + musicPlaying = true; + audio.play(); + } }); canvas.addEventListener("contextmenu", function (e) { diff --git a/src/types.c b/src/types.c index 8e8ba1d..bfe0d7d 100644 --- a/src/types.c +++ b/src/types.c @@ -17,6 +17,7 @@ typedef struct { int x, y, w, h; Color fill; Color border; + int image; } DrawElement; typedef struct { |