Created
July 17, 2026 12:44
-
-
Save doccaico/d7fc03524393d7c1e134aacaed49e66d to your computer and use it in GitHub Desktop.
Raylib + Emscripten using HTML's select
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @echo off | |
| setlocal | |
| set OUT_DIR=web | |
| if not exist %OUT_DIR% mkdir %OUT_DIR% | |
| set FILES="vendor\raylib\bin\wasm\libraylib.web.a" | |
| set "FLAGS=-DPLATFORM_WEB" | |
| set "FLAGS=%FLAGS% -I ./vendor/raylib/include" | |
| set "FLAGS=%FLAGS% -sEXPORTED_RUNTIME_METHODS=['HEAPF32'] -sUSE_GLFW=3 -sWASM_BIGINT -sWARN_ON_UNDEFINED_SYMBOLS=0 -sEXPORTED_RUNTIME_METHODS=ccall --shell-file src\index_template.html" | |
| if "%~1" == "--debug" ( | |
| set "FLAGS=%FLAGS% -sASSERTIONS=1 -sSTACK_OVERFLOW_CHECK=1" | |
| ) else if "%~1" == "--release" ( | |
| set "FLAGS=%FLAGS% -Os -flto" | |
| ) | |
| cmd /c emcc -o %OUT_DIR%\index.html src\main.c %FLAGS% %FILES% | |
| echo Web build created in %OUT_DIR% | |
| endlocal |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| // #include <time.h> | |
| // #include "types.h" | |
| #include "defines.h" | |
| // #include "input_handling.h" | |
| #include "raylib.h" | |
| #if defined(PLATFORM_WEB) | |
| #include <emscripten/emscripten.h> | |
| #endif | |
| typedef enum { | |
| PET_CAT = 0, | |
| PET_DOG = 1, | |
| } PetType; | |
| PetType pet_type = PET_CAT; | |
| EMSCRIPTEN_KEEPALIVE | |
| void on_select_changed(const char* value) { | |
| if (strcmp(value, "cat") == 0) { | |
| pet_type = PET_CAT; | |
| } else if (strcmp(value, "dog") == 0) { | |
| pet_type = PET_DOG; | |
| } | |
| printf("Received value: %s\n", value); | |
| printf("Current pet_type: %d\n", pet_type); | |
| } | |
| static void init_game(void) { | |
| } | |
| static void deinit_game() { | |
| } | |
| static void update_game(void) | |
| { | |
| BeginDrawing(); | |
| ClearBackground(WHITE); | |
| if (pet_type == PET_CAT) { | |
| DrawText("Cat", 100, 300, 25, BLACK); | |
| } else if (pet_type == PET_DOG) { | |
| DrawText("Dog", 100, 300, 25, BLACK); | |
| } | |
| EndDrawing(); | |
| } | |
| int main(void) | |
| { | |
| InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE); | |
| init_game(); | |
| #if defined(PLATFORM_WEB) | |
| // Hand over loop execution control to the browser. | |
| // 0 = Use browser's preferred FPS (requestAnimationFrame). | |
| // 1 = Simulate an infinite block loop. | |
| emscripten_set_main_loop(update_game, 0, 1); | |
| #else | |
| // Traditional desktop game loop capped at 60 FPS | |
| SetTargetFPS(60); | |
| while (!WindowShouldClose()) | |
| { | |
| update_game(); | |
| } | |
| #endif | |
| #if !defined(PLATFORM_WEB) | |
| deinit_game(); | |
| #endif | |
| CloseWindow(); | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="EN-us"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
| <title>Simple CGOL</title> | |
| <meta name="title" content="Simple CGOL"> | |
| <meta name="description" content="A single player game invented in 1970 by Cambridge mathematician John Conway"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> | |
| <style> | |
| html, body { | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| width: 100vw !important; | |
| height: 100dvh !important; | |
| background-color: #1a1a24; | |
| overflow: hidden !important; | |
| /* 上下左右の完全に真ん中に要素を集める設定 */ | |
| display: flex !important; | |
| justify-content: center !important; | |
| align-items: center !important; | |
| } | |
| /* 1. Canvasのサイズにぴったり合わせる基準コンテナ */ | |
| .game-wrapper { | |
| position: relative !important; /* 中のselectの位置基準になります */ | |
| /* Canvasと全く同じサイズ制限を持たせる */ | |
| display: flex !important; | |
| width: auto !important; | |
| height: auto !important; | |
| max-width: 100vw !important; | |
| max-height: 100dvh !important; | |
| aspect-ratio: 2 / 3 !important; | |
| } | |
| /* 2. Canvas自体を画面の中央に固定する設定 */ | |
| canvas.emscripten { | |
| border: 0px none; | |
| background-color: black; | |
| display: block !important; | |
| width: 100% !important; /* 親のwrapperいっぱいに広げる */ | |
| height: 100% !important; /* 親のwrapperいっぱいに広げる */ | |
| image-rendering: pixelated; | |
| } | |
| /* 3. 白い画面の左上に重ねる設定 */ | |
| #pet-select { | |
| font-size: 18px; /* 文字を20pxに拡大 */ | |
| padding: 4px 8px; /* 見栄えを良くするための余白 */ | |
| position: absolute !important; | |
| top: 5px; /* 白い画面の上端からの隙間 */ | |
| left: 5px; /* 白い画面の左端からの隙間 */ | |
| z-index: 999; /* 最前面に表示 */ | |
| } | |
| </style> | |
| <script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script> | |
| <script type='text/javascript'> | |
| function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code | |
| { | |
| var isSafari = false; // Not supported, navigator.userAgent access is being restricted | |
| //var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); | |
| var data = FS.readFile(memoryFSname); | |
| var blob; | |
| if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" }); | |
| else blob = new Blob([data.buffer], { type: "application/octet-binary" }); | |
| // NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome, | |
| // in Settings/Advanced/Downloads section you have a setting: | |
| // 'Ask where to save each file before downloading' - which you can set true/false. | |
| // If you enable this setting it would always ask you and bring the SaveAsDialog | |
| saveAs(blob, localFSname); | |
| // Alternative implementation to avoid FileSaver.js | |
| //const link = document.createElement("a"); | |
| //link.href = URL.createObjectURL(blob); | |
| //link.download = localFSname; | |
| //link.click(); | |
| } | |
| </script> | |
| </head> | |
| <body> | |
| <div class="game-wrapper"> | |
| <select name="pets" id="pet-select"> | |
| <option value="cat" selected>I'm cat and don't sleep</option> | |
| <option value="dog">Rotation circle</option> | |
| </select> | |
| <canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas> | |
| </div> | |
| <p id="output" /> | |
| <script> | |
| var Module = { | |
| canvas: (function() { | |
| var canvas = document.getElementById('canvas'); | |
| return canvas; | |
| })(), | |
| }; | |
| document.getElementById('pet-select').addEventListener('change', function() { | |
| var selectedValue = this.value; | |
| // C側の関数 `on_select_changed` を呼び出す (事前バインドが必要) | |
| Module.ccall('on_select_changed', null, ['string'], [selectedValue]); | |
| }); | |
| </script> | |
| {{{ SCRIPT }}} | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment