Skip to content

Commit

Permalink
Port core_basic_window to raylib.js
Browse files Browse the repository at this point in the history
  • Loading branch information
rexim committed Feb 5, 2024
1 parent c6abb91 commit 65a1e43
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
4 changes: 0 additions & 4 deletions Makefile

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Unofficial Implementation of Subset of [Raylib](https://github.com/raysan5/rayli
## Quick Start

```console
$ make
$ ./build.sh
$ python3 -m http.server 6969
$ <browser> http://localhost:6969/
```
11 changes: 11 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh

set -xe

mkdir -p build/

clang -I./include/ -o build/core_basic_window ./examples/core_basic_window.c -L./lib/ -lraylib -lm
clang -I./include/ -o build/game ./game.c -L./lib/ -lraylib -lm

clang --target=wasm32 -I./include --no-standard-libraries -Wl,--export-table -Wl,--no-entry -Wl,--allow-undefined -Wl,--export=main -o wasm/core_basic_window.wasm ./examples/core_basic_window.c -DPLATFORM_WEB
clang --target=wasm32 -I./include --no-standard-libraries -Wl,--export-table -Wl,--no-entry -Wl,--allow-undefined -Wl,--export=main -o wasm/game.wasm game.c -DPLATFORM_WEB
78 changes: 78 additions & 0 deletions examples/core_basic_window.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*******************************************************************************************
*
* raylib [core] example - Basic window
*
* Welcome to raylib!
*
* To test examples, just press F6 and execute raylib_compile_execute script
* Note that compiled executable is placed in the same folder as .c file
*
* You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com
*
* Enjoy using raylib. :)
*
* Example originally created with raylib 1.0, last time updated with raylib 1.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
*
********************************************************************************************/

#include "raylib.h"

void raylib_js_set_entry(void (*entry)(void));

void GameFrame(void)
{
BeginDrawing();

ClearBackground(RAYWHITE);

DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);

EndDrawing();
}

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;

InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");

SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------

#ifdef PLATFORM_WEB
raylib_js_set_entry(GameFrame);
#else
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------

// Draw
//----------------------------------------------------------------------------------
GameFrame();
//----------------------------------------------------------------------------------
}

// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
#endif

return 0;
}
1 change: 1 addition & 0 deletions fonts/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add the license of the official Raylib font here
Binary file added fonts/acme_7_wide_xtnd.woff
Binary file not shown.
25 changes: 10 additions & 15 deletions game.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
static Vector2 ball_position = {0};
static Vector2 ball_velocity = {200, 200};

void game_frame()
void raylib_js_set_entry(void (*entry)(void));

void GameFrame()
{
BeginDrawing();
ClearBackground((Color){20, 20, 20, 255});
Expand All @@ -29,7 +31,7 @@ void game_frame()
EndDrawing();
}

void game_init()
int main()
{
InitWindow(800, 600, "Hello, from WebAssembly");
SetTargetFPS(60);
Expand All @@ -38,21 +40,14 @@ void game_init()
int h = GetScreenHeight();
ball_position.x = w/2;
ball_position.y = h/2;
}

void game_over()
{
CloseWindow();
}

#ifndef PLATFORM_WEB
int main()
{
game_init();
#ifdef PLATFORM_WEB
raylib_js_set_entry(GameFrame);
#else
while (!WindowShouldClose()) {
game_frame();
GameFrame();
}
game_over();
CloseWindow();
#endif
return 0;
}
#endif
6 changes: 5 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
.not-hosted-msg .important {
font-weight: bold;
}
@font-face {
font-family: grixel;
src: url(fonts/acme_7_wide_xtnd.woff);
}
</style>
<script>
const { protocol } = window.location;
Expand All @@ -32,7 +36,7 @@
if (isHosted) {
const script = Object.assign(document.createElement("script"), {
type: "text/javascript",
src: "/raylib.js",
src: "./raylib.js",
defer: true
});

Expand Down
Binary file added lib/libraylib.a
Binary file not shown.
43 changes: 36 additions & 7 deletions raylib.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ function make_environment(...envs) {
return env[prop];
}
}
return (...args) => {console.error("NOT IMPLEMENTED: "+prop, args)}
return (...args) => {
throw new Error(`NOT IMPLEMENTED: ${prop} ${args}`);
}
}
});
}
Expand All @@ -16,6 +18,7 @@ let wasm = undefined;
let ctx = undefined;
let dt = undefined;
let targetFPS = 60;
let entryFunction = undefined;

function cstrlen(mem, ptr) {
let len = 0;
Expand Down Expand Up @@ -49,7 +52,12 @@ function color_hex(color) {
return "#"+r+g+b+a;
}

WebAssembly.instantiateStreaming(fetch('wasm/game.wasm'), {
function getColorFromMemory(buffer, color_ptr) {
const [r, g, b, a] = new Uint8Array(buffer, color_ptr, 4);
return color_hex_unpacked(r, g, b, a);
}

WebAssembly.instantiateStreaming(fetch('wasm/core_basic_window.wasm'), {
env: make_environment({
InitWindow: (width, height, title_ptr) => {
ctx.canvas.width = width;
Expand Down Expand Up @@ -83,11 +91,30 @@ WebAssembly.instantiateStreaming(fetch('wasm/game.wasm'), {
ctx.fill();
},
ClearBackground: (color_ptr) => {
const buffer = wasm.instance.exports.memory.buffer;
const [r, g, b, a] = new Uint8Array(buffer, color_ptr, 4);
ctx.fillStyle = color_hex_unpacked(r, g, b, a);
ctx.fillStyle = getColorFromMemory(wasm.instance.exports.memory.buffer, color_ptr);
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
},
// RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
DrawText: (text_ptr, posX, posY, fontSize, color_ptr) => {
const buffer = wasm.instance.exports.memory.buffer;
const text = cstr_by_ptr(buffer, text_ptr);
const color = getColorFromMemory(buffer, color_ptr);
// TODO: We stole the font from the website
// (https://raylib.com/) and it's slightly different than
// the one that is "baked" into Raylib library itself. To
// account for the differences we scale the size with a
// magical factor.
//
// It would be nice to have a better approach...
const fontSizeFactor = 0.6;
ctx.fillStyle = color;
ctx.font = `${fontSize*fontSizeFactor}px grixel`;
ctx.fillText(text, posX, posY);
},
raylib_js_set_entry: (entry) => {
entryFunction = entry;
console.log(`Entry function was set to ${entryFunction}`);
}
})
})
.then((w) => {
Expand All @@ -96,15 +123,17 @@ WebAssembly.instantiateStreaming(fetch('wasm/game.wasm'), {
const canvas = document.getElementById("game");
ctx = canvas.getContext("2d");

w.instance.exports.game_init();
w.instance.exports.main();
let entry = w.instance.exports.__indirect_function_table.get(entryFunction);

function first(timestamp) {
previous = timestamp;
window.requestAnimationFrame(next)
}
function next(timestamp) {
dt = (timestamp - previous)/1000.0;
previous = timestamp;
w.instance.exports.game_frame();
entry();
window.requestAnimationFrame(next);
}
window.requestAnimationFrame(first);
Expand Down
Binary file added wasm/core_basic_window.wasm
Binary file not shown.
Binary file modified wasm/game.wasm
100644 → 100755
Binary file not shown.

0 comments on commit 65a1e43

Please sign in to comment.