summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-06-02 00:54:56 -0400
committerLLLL Colonq <llll@colonq>2026-06-02 00:54:56 -0400
commitab80e4583b53a7b424563cbd17ba2bf95e168cc9 (patch)
tree54d4bb560c03585046e0b1ac0de7fafb496be94a
parent7409691cb134eef99a7d9e53b57a1cba41a7ca09 (diff)
Update
-rwxr-xr-x2026/examples/raylib/build.sh1
-rw-r--r--2026/examples/raylib/main.c2
-rw-r--r--2026/framing/.dir-locals.el8
-rw-r--r--2026/framing/Cargo.lock66
-rw-r--r--2026/framing/Cargo.toml3
-rw-r--r--2026/framing/index.css3
-rw-r--r--2026/framing/index.html52
-rw-r--r--2026/framing/src/assets.rs1
-rw-r--r--2026/framing/src/assets/audio/footsteps.wavbin0 -> 140588 bytes
-rw-r--r--2026/framing/src/assets/textures/arm.pngbin0 -> 2541 bytes
-rw-r--r--2026/framing/src/assets/textures/lagerboy.pngbin0 -> 886192 bytes
-rw-r--r--2026/framing/src/assets/textures/mrblue.pngbin0 -> 771 bytes
-rw-r--r--2026/framing/src/assets/textures/mrgreen.png (renamed from 2026/framing/src/assets/textures/test.png)bin714 -> 714 bytes
-rw-r--r--2026/framing/src/assets/textures/timbs.pngbin0 -> 4051 bytes
-rw-r--r--2026/framing/src/game.rs198
-rw-r--r--2026/framing/src/lagerboy.pngbin0 -> 886192 bytes
-rw-r--r--2026/framing/src/lib.rs3
-rw-r--r--2026/index.html94
18 files changed, 324 insertions, 107 deletions
diff --git a/2026/examples/raylib/build.sh b/2026/examples/raylib/build.sh
index f176746..6454acc 100755
--- a/2026/examples/raylib/build.sh
+++ b/2026/examples/raylib/build.sh
@@ -1,3 +1,4 @@
#!/bin/sh
+set -xeu -o pipefail
mkdir -p output
emcc -I./raylib/src libraylib.a -s USE_GLFW=3 -s ASYNCIFY --shell-file ./raylib/src/minshell.html main.c -DPLATFORM_WEB -o output/game.html
diff --git a/2026/examples/raylib/main.c b/2026/examples/raylib/main.c
index 64091b5..c047aa7 100644
--- a/2026/examples/raylib/main.c
+++ b/2026/examples/raylib/main.c
@@ -20,7 +20,7 @@ int main(int argc, char **argv) {
} else {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
printf("clicked\n");
- emscripten_run_script("window.parent.postMessage({op: \"done\", win: true});");
+ emscripten_run_script("window.parent.postMessage({op: \"done\", win: false});");
return 0;
}
BeginDrawing();
diff --git a/2026/framing/.dir-locals.el b/2026/framing/.dir-locals.el
index d0146c5..ebe3652 100644
--- a/2026/framing/.dir-locals.el
+++ b/2026/framing/.dir-locals.el
@@ -1 +1,7 @@
-((rust-mode . ((eglot-workspace-configuration . (:rust-analyzer (:cargo (:target "x86_64-unknown-linux-gnu")))))))
+((rust-ts-mode .
+ ((eglot-workspace-configuration .
+ (:rust-analyzer
+ ( :check (:command "clippy")
+ :cargo ( :target "wasm32-unknown-unknown"
+ :targetDir t)
+ :hover (:show (:fields 10))))))))
diff --git a/2026/framing/Cargo.lock b/2026/framing/Cargo.lock
index 1b66407..96a3e84 100644
--- a/2026/framing/Cargo.lock
+++ b/2026/framing/Cargo.lock
@@ -714,6 +714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
+ "serde",
]
[[package]]
@@ -728,6 +729,15 @@ dependencies = [
]
[[package]]
+name = "env"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc95de49ad098572c02d3fbf368c9a020bfff5ae78483685b77f51d8a7e9486d"
+dependencies = [
+ "num_threads",
+]
+
+[[package]]
name = "env_filter"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -860,12 +870,15 @@ name = "game_lib"
version = "0.1.0"
dependencies = [
"bitflags 2.11.1",
+ "enum-map",
"glam",
"lazy_static",
"log",
"rand",
- "strum 0.26.3",
+ "serde",
+ "strum",
"teleia",
+ "teleia_macros",
"wasm-bindgen",
]
@@ -1246,6 +1259,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
+name = "litrs"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
+
+[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1484,6 +1503,15 @@ dependencies = [
]
[[package]]
+name = "num_threads"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "objc-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2232,33 +2260,11 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
name = "strum"
-version = "0.26.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
-dependencies = [
- "strum_macros 0.26.4",
-]
-
-[[package]]
-name = "strum"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
dependencies = [
- "strum_macros 0.27.2",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn",
+ "strum_macros",
]
[[package]]
@@ -2425,7 +2431,7 @@ dependencies = [
"serde",
"serde_json",
"simple-eyre",
- "strum 0.27.2",
+ "strum",
"tobj",
"tracing-wasm",
"tungstenite",
@@ -2436,6 +2442,16 @@ dependencies = [
]
[[package]]
+name = "teleia_macros"
+version = "0.1.0"
+dependencies = [
+ "env",
+ "heck",
+ "litrs",
+ "walkdir",
+]
+
+[[package]]
name = "tempfile"
version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/2026/framing/Cargo.toml b/2026/framing/Cargo.toml
index b673692..cf605fa 100644
--- a/2026/framing/Cargo.toml
+++ b/2026/framing/Cargo.toml
@@ -17,12 +17,15 @@ opt-level = 2
[dependencies]
# teleia = { git = "https://github.com/lcolonq/teleia" } # engine
teleia = { path = "../../../teleia/crates/teleia" } # engine
+teleia_macros = { path = "../../../teleia/crates/teleia_macros" } # engine
glam = "*" # linear algebra
bitflags = "*" # C-style bitwise flags
rand = "*" # rng
log = "*" # logging
lazy_static = "*" # global constants
strum = {version = "*", features = ["derive"]} # utility macros for enums
+enum-map = {version = "2.7.3", features = ["serde"]} # enum map
+serde = { version = "1.0.228", features = ["derive"] } # serialization
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "=0.2.100" # wasm bindings \ No newline at end of file
diff --git a/2026/framing/index.css b/2026/framing/index.css
index aa6ff76..42d23c8 100644
--- a/2026/framing/index.css
+++ b/2026/framing/index.css
@@ -23,6 +23,7 @@ canvas {
top: 0%;
left: 50%;
transform: translate(-50%, 0%);
+ image-rendering: pixelated;
/* color: #000000; */
}
@@ -37,5 +38,5 @@ canvas {
font-size: 24px;
font-family: Ubuntu-Light, Helvetica, sans-serif;
text-align: center;
- image-transform: pixelated;
+ image-rendering: pixelated;
}
diff --git a/2026/framing/index.html b/2026/framing/index.html
index 7be78b5..a38f0f5 100644
--- a/2026/framing/index.html
+++ b/2026/framing/index.html
@@ -1,25 +1,33 @@
<!DOCTYPE html>
<html>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
- <head>
- <meta charset="UTF-8">
- <link data-trunk rel="rust" data-wasm-opt="2" data-target-name="game_lib" />
- <!-- <link data-trunk rel="rust" data-keep-debug="true" /> -->
- <base data-trunk-public-url />
- <meta name="theme-color" media="(prefers-color-scheme: light)" content="white">
- <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#404040">
- <link rel="icon" href="data:;base64,iVBORw0KGgo=">
- <link data-trunk rel="css" href="index.css" />
- <title>TODO TITLE</title>
- </head>
- <body>
- <script>
- addEventListener("TrunkApplicationStarted", async (event) => {
- console.log("initialized, starting...");
- window.wasmBindings.main_js();
- });
- </script>
- <div id="teleia-parent"></div>
- </body>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+ <head>
+ <meta charset="UTF-8">
+ <link data-trunk rel="rust" data-wasm-opt="2" data-target-name="game_lib" />
+ <!-- <link data-trunk rel="rust" data-keep-debug="true" /> -->
+ <base data-trunk-public-url />
+ <meta name="theme-color" media="(prefers-color-scheme: light)" content="white">
+ <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#404040">
+ <link rel="icon" href="data:;base64,iVBORw0KGgo=">
+ <link data-trunk rel="css" href="index.css" />
+ <title>TODO TITLE</title>
+ </head>
+ <body>
+ <script type="module">
+ window.addEventListener("TrunkApplicationStarted", async (event) => {
+ console.log("initialized, starting...");
+ window.wasmBindings.main_js();
+ });
+ window.addEventListener("message", ev => {
+ switch (ev.data.op) {
+ case "loselife":
+ window.wasmBindings.lose_life();
+ break;
+ default: console.log(`unknown event: ${ev}`); break;
+ }
+ });
+ </script>
+ <div id="teleia-parent"></div>
+ </body>
</html>
diff --git a/2026/framing/src/assets.rs b/2026/framing/src/assets.rs
new file mode 100644
index 0000000..31fa1b5
--- /dev/null
+++ b/2026/framing/src/assets.rs
@@ -0,0 +1 @@
+teleia_macros::generate_assets!("src/assets/");
diff --git a/2026/framing/src/assets/audio/footsteps.wav b/2026/framing/src/assets/audio/footsteps.wav
new file mode 100644
index 0000000..57bfddf
--- /dev/null
+++ b/2026/framing/src/assets/audio/footsteps.wav
Binary files differ
diff --git a/2026/framing/src/assets/textures/arm.png b/2026/framing/src/assets/textures/arm.png
new file mode 100644
index 0000000..0b4accf
--- /dev/null
+++ b/2026/framing/src/assets/textures/arm.png
Binary files differ
diff --git a/2026/framing/src/assets/textures/lagerboy.png b/2026/framing/src/assets/textures/lagerboy.png
new file mode 100644
index 0000000..89992f7
--- /dev/null
+++ b/2026/framing/src/assets/textures/lagerboy.png
Binary files differ
diff --git a/2026/framing/src/assets/textures/mrblue.png b/2026/framing/src/assets/textures/mrblue.png
new file mode 100644
index 0000000..8cf2a0b
--- /dev/null
+++ b/2026/framing/src/assets/textures/mrblue.png
Binary files differ
diff --git a/2026/framing/src/assets/textures/test.png b/2026/framing/src/assets/textures/mrgreen.png
index 1f1edca..1f1edca 100644
--- a/2026/framing/src/assets/textures/test.png
+++ b/2026/framing/src/assets/textures/mrgreen.png
Binary files differ
diff --git a/2026/framing/src/assets/textures/timbs.png b/2026/framing/src/assets/textures/timbs.png
new file mode 100644
index 0000000..0c093ad
--- /dev/null
+++ b/2026/framing/src/assets/textures/timbs.png
Binary files differ
diff --git a/2026/framing/src/game.rs b/2026/framing/src/game.rs
index b704b49..8e819c0 100644
--- a/2026/framing/src/game.rs
+++ b/2026/framing/src/game.rs
@@ -1,37 +1,165 @@
#![allow(dead_code, unused_variables)]
use std::collections::HashMap;
use teleia::*;
+use teleia::renderer::UberFlags;
+use wasm_bindgen::prelude::*;
-struct Assets {
- font: font::Bitmap,
- shader_flat: shader::Shader,
- mesh_square: mesh::Mesh,
- texture_test: texture::Texture,
+use crate::assets;
+
+const NUM_LIVES: usize = 4;
+const LIFE_LOSS_FRAMES: u64 = 120;
+
+#[derive(PartialEq, Eq)]
+enum MrColor {
+ Green,
+ Blue,
+}
+impl MrColor {
+ fn texture(&self) -> assets::Texture {
+ match self {
+ Self::Green => assets::Texture::Mrgreen,
+ Self::Blue => assets::Texture::Mrblue,
+ }
+ }
+ fn hue(&self) -> f32 {
+ match self {
+ Self::Green => 0.3,
+ Self::Blue => 0.6,
+ }
+ }
}
-impl Assets {
- fn new(ctx: &context::Context) -> Self {
+struct Lives {
+ lives: [ui::Mode; NUM_LIVES],
+}
+impl Lives {
+ fn new() -> Self {
Self {
- font: font::Bitmap::default(ctx),
- shader_flat: shader::Shader::new(
- ctx,
- include_str!("assets/shaders/flat/vert.glsl"),
- include_str!("assets/shaders/flat/frag.glsl"),
- ),
- mesh_square: mesh::Mesh::from_obj(ctx, include_bytes!("assets/meshes/square.obj")),
- texture_test: texture::Texture::new(ctx, include_bytes!("assets/textures/test.png")),
+ lives: [
+ ui::Mode::new(LIFE_LOSS_FRAMES),
+ ui::Mode::new(LIFE_LOSS_FRAMES),
+ ui::Mode::new(LIFE_LOSS_FRAMES),
+ ui::Mode::new(LIFE_LOSS_FRAMES),
+ ],
+ }
+ }
+ fn last_life(&self) -> Option<usize> {
+ self.lives.iter().rposition(|l| !l.is_active())
+ }
+ fn lives_remaining(&self) -> i32 {
+ self.last_life().map(|x| (x + 1) as i32).unwrap_or(0)
+ }
+ fn lose_life(&mut self, _ctx: &context::Context, st: &state::State) {
+ if let Some(ll) = self.last_life() {
+ self.lives[ll].toggle(st.tick)
}
}
+ fn render(&self,
+ ctx: &context::Context, st: &mut state::State, r: &mut renderer::Renderer<assets::Assets>,
+ ) -> Erm<()> {
+ let base = glam::Vec2::new(90.0, 250.0);
+ let off = glam::Vec2::new(90.0, 0.0);
+ let t = st.tick as f32 / 10.0;
+ for i in 0..NUM_LIVES {
+ let fi = i as f32;
+ let pos = base + fi * off;
+ let osc = (t + fi * 10.0).sin();
+ if self.lives[i].is_active() {
+ let hoff = self.lives[i].progress(st.tick) * st.render_dims.x;
+ draw_mr_armed(ctx, st, r, MrColor::Blue, pos + glam::Vec2::new(hoff, 0.0), osc)?;
+ } else {
+ draw_mr_armed(ctx, st, r, MrColor::Green, pos, osc)?;
+ };
+ }
+ Ok(())
+ }
+}
+
+pub fn draw_texture_rotated_about(
+ ctx: &context::Context, st: &mut state::State, r: &mut renderer::Renderer<assets::Assets>,
+ texture: assets::Texture, flip: bool, hueset: Option<f32>,
+ pos: glam::Vec2, dims: glam::Vec2, joint: glam::Vec2, angle: f32,
+) -> Erm<()> {
+ let origin_offset = glam::Vec3::new(-st.render_dims.x / 2.0, st.render_dims.y / 2.0, 0.0);
+ r.bind_uber_2d(ctx, st, UberFlags::TEXTURE_COLOR | UberFlags::EFFECTS);
+ r.set_i32(ctx, st, "effect_flip", flip as i32);
+ r.set_f32(ctx, st, "effect_flash", 0.0);
+ r.set_f32(ctx, st, "effect_huescale", if hueset.is_some() { 0.0 } else { 1.0 });
+ r.set_f32(ctx, st, "effect_hueshift", if let Some(hs) = hueset { hs } else { 0.0 });
+ r.bind_texture(ctx, st, texture);
+ r.set_position_2d_mat(ctx, st,
+ glam::Mat4::from_translation(glam::Vec3::new(pos.x, -pos.y, 0.0) + origin_offset)
+ .mul_mat4(&glam::Mat4::from_translation(glam::Vec3::new(joint.x, -joint.y, 0.0)))
+ .mul_mat4(&glam::Mat4::from_rotation_z(angle))
+ .mul_mat4(&glam::Mat4::from_translation(glam::Vec3::new(-joint.x, joint.y, 0.0)))
+ .mul_mat4(&glam::Mat4::from_scale(glam::Vec3::new(dims.x / 2.0, dims.y / 2.0, 1.0))),
+ );
+ r.render_square(ctx, st);
+ Ok(())
+}
+
+fn draw_mr_armed(
+ ctx: &context::Context, st: &mut state::State, r: &mut renderer::Renderer<assets::Assets>,
+ mr: MrColor, center: glam::Vec2, oscillation: f32,
+) -> Erm<()> {
+ let dims = glam::Vec2::new(48.0, 48.0);
+ let pos = center + glam::Vec2::new(0.0, 4.0 * oscillation);
+ let topleft = pos - dims / 2.0;
+ let leftedge = pos.x - dims.x / 2.0;
+ let rightedge = pos.x + dims.x / 2.0;
+ let armheight = pos.y - dims.y / 3.0;
+ let legheight = pos.y + dims.y / 2.0;
+ let legangle = 0.2 * oscillation;
+ let armangle = 0.1 * oscillation;
+ let origin_offset = glam::Vec3::new(-st.render_dims.x / 2.0, st.render_dims.y / 2.0, 0.0);
+ draw_texture_rotated_about(ctx, st, r,
+ assets::Texture::Timbs, true, None,
+ glam::Vec2::new(leftedge, legheight),
+ dims,
+ glam::Vec2::new(dims.x / 2.0, -dims.y / 2.0),
+ legangle,
+ )?;
+ draw_texture_rotated_about(ctx, st, r,
+ assets::Texture::Timbs, false, None,
+ glam::Vec2::new(rightedge, legheight),
+ dims,
+ glam::Vec2::new(-dims.x / 2.0, -dims.y / 2.0),
+ -legangle,
+ )?;
+ if mr == MrColor::Green {
+ draw_texture_rotated_about(ctx, st, r,
+ assets::Texture::Arm, true, Some(mr.hue()),
+ glam::Vec2::new(leftedge, armheight),
+ dims,
+ glam::Vec2::new(dims.x / 2.0, dims.y / 2.0),
+ armangle,
+ )?;
+ draw_texture_rotated_about(ctx, st, r,
+ assets::Texture::Arm, false, Some(mr.hue()),
+ glam::Vec2::new(rightedge, armheight),
+ dims,
+ glam::Vec2::new(-dims.x / 2.0, dims.y / 2.0),
+ -armangle,
+ )?;
+ }
+ r.texture_screen(ctx, st,
+ mr.texture(),
+ topleft,
+ dims,
+ );
+ Ok(())
}
pub struct Game {
- assets: Assets,
+ renderer: renderer::Renderer<assets::Assets>,
+ lives: Lives,
}
impl Game {
pub fn new(ctx: &context::Context) -> Self {
Self {
- assets: Assets::new(ctx),
+ renderer: renderer::Renderer::new(ctx, assets::Assets::new),
+ lives: Lives::new(),
}
}
}
@@ -39,29 +167,31 @@ impl Game {
impl teleia::state::Game for Game {
fn initialize_audio(&self, ctx: &context::Context, st: &state::State, actx: &audio::Context) -> HashMap<String, audio::Audio> {
HashMap::from_iter(vec![
- ("test".to_owned(), audio::Audio::new(&actx, include_bytes!("assets/audio/test.wav"))),
+ ("footsteps".to_owned(), audio::Audio::new(&actx, include_bytes!("assets/audio/footsteps.wav"))),
])
}
- fn update(&mut self, _ctx: &context::Context, _st: &mut state::State) -> Erm<()> {
+ fn update(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> {
+ if st.keys.new_a() {
+ log::info!("yo");
+ self.lives.lose_life(ctx, st);
+ st.audio.play_sfx("footsteps");
+ }
Ok(())
}
fn render(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> {
- ctx.clear_color(glam::Vec4::new(1.0, 0.0, 0.0, 0.5));
+ ctx.clear_color(glam::Vec4::ZERO);
ctx.clear();
- self.assets.font.render_text_at(
- ctx, st,
- glam::Vec2::new(0.0, 0.0),
- "hello computer",
- font::BitmapParams::default(),
- );
- st.bind_2d(ctx, &self.assets.shader_flat);
- self.assets.texture_test.bind(ctx);
- self.assets.shader_flat.set_position_2d(
- ctx, st,
- &glam::Vec2::new(40.0, 40.0),
- &glam::Vec2::new(16.0, 16.0),
- );
- self.assets.mesh_square.render(ctx);
+ self.renderer.text_screen(ctx, st, glam::Vec2::new(0.0, 0.0), "hi");
+ self.lives.render(ctx, st, &mut self.renderer)?;
Ok(())
}
}
+
+#[wasm_bindgen]
+pub fn lose_life() {
+ contextualize(|ctx, st, g: &mut Game| {
+ log::info!("lose a life");
+ g.lives.lose_life(ctx, st);
+ st.audio.play_sfx("footsteps");
+ });
+}
diff --git a/2026/framing/src/lagerboy.png b/2026/framing/src/lagerboy.png
new file mode 100644
index 0000000..89992f7
--- /dev/null
+++ b/2026/framing/src/lagerboy.png
Binary files differ
diff --git a/2026/framing/src/lib.rs b/2026/framing/src/lib.rs
index fa27675..19ac407 100644
--- a/2026/framing/src/lib.rs
+++ b/2026/framing/src/lib.rs
@@ -1,4 +1,5 @@
mod game;
+mod assets;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
@@ -6,5 +7,5 @@ use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn main_js() {
- teleia::run(240, 160, teleia::Options::OVERLAY, game::Game::new);
+ teleia::run(480, 320, teleia::Options::OVERLAY, game::Game::new);
}
diff --git a/2026/index.html b/2026/index.html
index ce28e45..f45326c 100644
--- a/2026/index.html
+++ b/2026/index.html
@@ -11,6 +11,9 @@
width: 100vw;
height: 100vh;
}
+ .jam-hidden {
+ visibility: hidden;
+ }
#jam-iframe-parent {
display: grid;
grid-template-columns: 100%;
@@ -28,10 +31,9 @@
padding: 0px;
border: 0px;
}
- #jam-game-iframe {
- }
#jam-framing-iframe {
z-index: 1;
+ pointer-events: none;
}
</style>
</head>
@@ -39,44 +41,92 @@
<div id="jam-iframe-parent">
<iframe id="jam-framing-iframe" width="480" height="320" src="./framing/dist/index.html"></iframe>
<!-- <iframe id="jam-game-iframe" width="240" height="160" src="./examples/godot/output/game.html"></iframe> -->
- <iframe id="jam-game-iframe" width="240" height="160" src="game.html"></iframe>
+ <iframe id="jam-game-iframe-0" class="jam-hidden" width="240" height="160"></iframe>
+ <iframe id="jam-game-iframe-1" class="jam-hidden" width="240" height="160"></iframe>
+ <iframe id="jam-game-iframe-2" class="jam-hidden" width="240" height="160"></iframe>
+ <iframe id="jam-game-iframe-3" class="jam-hidden" width="240" height="160"></iframe>
+ <iframe id="jam-game-iframe-4" class="jam-hidden" width="240" height="160"></iframe>
+ <!-- <iframe id="jam-game-iframe" width="240" height="160" src="game.html"></iframe> -->
<div>
<script type="module">
- let iframe = document.getElementById("jam-game-iframe");
- iframe.addEventListener("load", () => {
- iframe.contentDocument.body.style["overflow"] = "hidden";
- iframe.contentDocument.body.style["image-rendering"] = "pixelated";
- });
- function resizeView() {
- let least_ratio = Math.min(Math.floor(window.innerWidth / 480), Math.floor(window.innerHeight / 320));
- let factor = Math.max(1, least_ratio);
- console.log(factor);
- let game = document.getElementById("jam-game-iframe");
- game.style["transform"] = `scale(${factor})`;
- console.log(game.style.transform);
- let framing = document.getElementById("jam-framing-iframe");
- framing.style["transform"] = `scale(${factor})`;
- }
- resizeView();
+ let microgame_index = 0;
+ let microgames = [
+ {url: "./examples/raylib/output/game.html", loaded: null},
+ {url: "./examples/godot/output/game.html", loaded: null},
+ ];
+ let framing = document.getElementById("jam-framing-iframe");
+ let iframes = [...Array(5).keys()].map(i => document.getElementById(`jam-game-iframe-${i}`));
window.addEventListener("resize", resizeView);
+ function loadGame(i) {
+ if (!microgames[i].loaded) {
+ for (let iframe of iframes) {
+ if (!iframe.src) {
+ iframe.src = microgames[i].url;
+ microgames[i].loaded = iframe;
+ }
+ }
+ }
+ }
+ function unloadGame(i) {
+ if (microgames[i].loaded) {
+ microgames[i].loaded.src = null;
+ microgaems[i].loaded = null;
+ }
+ }
+ function loadUpcomingGames() {
+ let first = true;
+ let to_load = Math.min(5, microgames.length);
+ for (let i = (microgame_index + to_load) % microgames.len; i != microgame_index; i = (i + 1) % microgames.length) {
+ unloadGame(i)
+ }
+ for (let off = 0; off < to_load; ++off) {
+ let i = (microgame_index + off) % microgames.length;
+ loadGame(i)
+ }
+ }
+ function readyNextGame() {
+ loadUpcomingGames();
+ for (let i of iframes) { i.classList.add("jam-hidden"); }
+ microgames[microgame_index].loaded.classList.remove("jam-hidden");
+ microgame_index += 1;
+ microgame_index %= microgames.length;
+ }
+ readyNextGame();
window.addEventListener("message", ev => {
console.log(ev.data);
switch (ev.data.op) {
case "ready":
window.setTimeout(() => {
const resp = {op: "start", difficulty: 1.0};
- iframe.contentWindow.postMessage(resp);
- iframe.contentWindow.lcolonqJamStart = resp.difficulty;
+ game.contentWindow.postMessage(resp);
+ game.contentWindow.lcolonqJamStart = resp.difficulty;
}, 1000);
break;
case "started":
- iframe.contentWindow.focus();
+ game.contentWindow.focus();
break;
case "done":
+ if (!ev.data.win) {
+ framing.contentWindow.postMessage({op: "loselife"});
+ }
+ readyNextGame();
break;
default: console.log(`unknown event: ${ev}`); break;
}
});
+ game.addEventListener("load", () => {
+ game.contentDocument.body.style["overflow"] = "hidden";
+ game.contentDocument.body.style["image-rendering"] = "pixelated";
+ });
+ function resizeView() {
+ let least_ratio = Math.min(Math.floor(window.innerWidth / 480), Math.floor(window.innerHeight / 320));
+ let factor = Math.max(1, least_ratio);
+ console.log(factor);
+ game.style["transform"] = `scale(${factor})`;
+ console.log(game.style.transform);
+ framing.style["transform"] = `scale(${factor})`;
+ }
+ resizeView();
</script>
</body>
</html>