diff options
Diffstat (limited to '2026/framing/src')
| -rw-r--r-- | 2026/framing/src/assets.rs | 1 | ||||
| -rw-r--r-- | 2026/framing/src/assets/audio/footsteps.wav | bin | 0 -> 140588 bytes | |||
| -rw-r--r-- | 2026/framing/src/assets/textures/arm.png | bin | 0 -> 2541 bytes | |||
| -rw-r--r-- | 2026/framing/src/assets/textures/lagerboy.png | bin | 0 -> 886192 bytes | |||
| -rw-r--r-- | 2026/framing/src/assets/textures/mrblue.png | bin | 0 -> 771 bytes | |||
| -rw-r--r-- | 2026/framing/src/assets/textures/mrgreen.png (renamed from 2026/framing/src/assets/textures/test.png) | bin | 714 -> 714 bytes | |||
| -rw-r--r-- | 2026/framing/src/assets/textures/timbs.png | bin | 0 -> 4051 bytes | |||
| -rw-r--r-- | 2026/framing/src/game.rs | 198 | ||||
| -rw-r--r-- | 2026/framing/src/lagerboy.png | bin | 0 -> 886192 bytes | |||
| -rw-r--r-- | 2026/framing/src/lib.rs | 3 |
10 files changed, 167 insertions, 35 deletions
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 Binary files differnew file mode 100644 index 0000000..57bfddf --- /dev/null +++ b/2026/framing/src/assets/audio/footsteps.wav diff --git a/2026/framing/src/assets/textures/arm.png b/2026/framing/src/assets/textures/arm.png Binary files differnew file mode 100644 index 0000000..0b4accf --- /dev/null +++ b/2026/framing/src/assets/textures/arm.png diff --git a/2026/framing/src/assets/textures/lagerboy.png b/2026/framing/src/assets/textures/lagerboy.png Binary files differnew file mode 100644 index 0000000..89992f7 --- /dev/null +++ b/2026/framing/src/assets/textures/lagerboy.png diff --git a/2026/framing/src/assets/textures/mrblue.png b/2026/framing/src/assets/textures/mrblue.png Binary files differnew file mode 100644 index 0000000..8cf2a0b --- /dev/null +++ b/2026/framing/src/assets/textures/mrblue.png diff --git a/2026/framing/src/assets/textures/test.png b/2026/framing/src/assets/textures/mrgreen.png Binary files differindex 1f1edca..1f1edca 100644 --- a/2026/framing/src/assets/textures/test.png +++ b/2026/framing/src/assets/textures/mrgreen.png diff --git a/2026/framing/src/assets/textures/timbs.png b/2026/framing/src/assets/textures/timbs.png Binary files differnew file mode 100644 index 0000000..0c093ad --- /dev/null +++ b/2026/framing/src/assets/textures/timbs.png 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 Binary files differnew file mode 100644 index 0000000..89992f7 --- /dev/null +++ b/2026/framing/src/lagerboy.png 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); } |
