Back to shtanton's homepage
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2025-04-05 22:16:15 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2025-04-05 22:16:15 +0100
commit7bb8b8c7670728b0dcd510d8a8205bb3776368dd (patch)
tree8a1ccfd408736ed7b6793d19785ff3f1f85672a7
parent1c805d096248db7184b7d935f008ab5ae49a714e (diff)
downloadldjam57-7bb8b8c7670728b0dcd510d8a8205bb3776368dd.tar
Add audio to web and images to SDL
-rw-r--r--Makefile27
m---------lib/qoi0
-rw-r--r--res/continue.pngbin0 -> 279 bytes
-rw-r--r--res/music.mp3bin0 -> 197056 bytes
-rw-r--r--src/all.c38
-rw-r--r--src/img.c95
-rw-r--r--src/index.html.in13
-rw-r--r--src/types.c1
8 files changed, 171 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index fc6af8f..aa91fae 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-build/main: src/all.c src/all.h
+build/main: src/all.c src/all.h build/images.c src/types.c src/levels.c src/tick.c
mkdir -p build
gcc -Wall -Wextra -Wpedantic -DSDL $$(pkg-config --libs sdl3) -o build/main src/all.c
@@ -7,11 +7,34 @@ build/main.wasm: src/all.c src/all.h
clang --target=wasm32 -nostdlib -DWASM -Wall -Wextra -Wpedantic \
-Wl,--no-entry -fno-builtin -o build/main.wasm src/all.c
+build/music.mp3.b64: res/music.mp3
+ mkdir -p build
+ (printf '"data:audio/mpeg;base64,'; base64 < res/music.mp3 | tr -d '\n'; printf '"') > build/music.mp3.b64
+
build/main.wasm.b64: build/main.wasm
+ mkdir -p build
(printf '"'; base64 < build/main.wasm | tr -d '\n'; printf '"') > build/main.wasm.b64
-build/index.html: src/index.html.in build/main.wasm.b64
+build/index.html: src/index.html.in build/main.wasm.b64 build/music.mp3.b64
+ mkdir -p build
clang -E -P -undef -nostdinc -x c -o build/index.html src/index.html.in
+build/img: src/img.c
+ mkdir -p build
+ gcc -Wall -Wextra -Wpedantic -o build/img src/img.c
+
+build/%.qoi: res/%.png
+ mkdir -p build
+ magick $< $@
+
+build/images.c: build/continue.qoi build/img
+ mkdir -p build
+ (\
+ build/img pixels build/continue.qoi 1 && \
+ echo 'Image images[] = {{0},' && \
+ build/img image build/continue.qoi 1 && \
+ echo '};' \
+ ) > build/images.c
+
clean:
rm -r build
diff --git a/lib/qoi b/lib/qoi
new file mode 160000
+Subproject d0cf1dfcc371f894da88a8d5fb3b08c2e8ad747
diff --git a/res/continue.png b/res/continue.png
new file mode 100644
index 0000000..d93dd6f
--- /dev/null
+++ b/res/continue.png
Binary files differ
diff --git a/res/music.mp3 b/res/music.mp3
new file mode 100644
index 0000000..dac1000
--- /dev/null
+++ b/res/music.mp3
Binary files differ
diff --git a/src/all.c b/src/all.c
index 028289c..b1560a5 100644
--- a/src/all.c
+++ b/src/all.c
@@ -134,6 +134,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) {
@@ -213,6 +214,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;
@@ -249,6 +260,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();
@@ -284,6 +312,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,
@@ -309,6 +338,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);
@@ -331,7 +364,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 cbd9315..fde4ab4 100644
--- a/src/types.c
+++ b/src/types.c
@@ -14,6 +14,7 @@ typedef struct {
int x, y, w, h;
Color fill;
Color border;
+ int image;
} DrawElement;
typedef struct {