diff options
Diffstat (limited to '2026/framing/src')
18 files changed, 112 insertions, 25 deletions
diff --git a/2026/framing/src/assets/audio/aww.wav b/2026/framing/src/assets/audio/aww.wav Binary files differnew file mode 100644 index 0000000..6df8dd8 --- /dev/null +++ b/2026/framing/src/assets/audio/aww.wav diff --git a/2026/framing/src/assets/audio/boo.wav b/2026/framing/src/assets/audio/boo.wav Binary files differnew file mode 100644 index 0000000..d06c162 --- /dev/null +++ b/2026/framing/src/assets/audio/boo.wav diff --git a/2026/framing/src/assets/audio/booyah.wav b/2026/framing/src/assets/audio/booyah.wav Binary files differnew file mode 100644 index 0000000..82d2bdf --- /dev/null +++ b/2026/framing/src/assets/audio/booyah.wav diff --git a/2026/framing/src/assets/audio/epicwin.wav b/2026/framing/src/assets/audio/epicwin.wav Binary files differnew file mode 100644 index 0000000..d55964e --- /dev/null +++ b/2026/framing/src/assets/audio/epicwin.wav diff --git a/2026/framing/src/assets/audio/excellent.wav b/2026/framing/src/assets/audio/excellent.wav Binary files differnew file mode 100644 index 0000000..9067c75 --- /dev/null +++ b/2026/framing/src/assets/audio/excellent.wav diff --git a/2026/framing/src/assets/audio/explosion.wav b/2026/framing/src/assets/audio/explosion.wav Binary files differnew file mode 100644 index 0000000..32c9db9 --- /dev/null +++ b/2026/framing/src/assets/audio/explosion.wav diff --git a/2026/framing/src/assets/audio/gamingtime.wav b/2026/framing/src/assets/audio/gamingtime.wav Binary files differnew file mode 100644 index 0000000..4c3dc70 --- /dev/null +++ b/2026/framing/src/assets/audio/gamingtime.wav diff --git a/2026/framing/src/assets/audio/itsover.wav b/2026/framing/src/assets/audio/itsover.wav Binary files differnew file mode 100644 index 0000000..b495ac8 --- /dev/null +++ b/2026/framing/src/assets/audio/itsover.wav diff --git a/2026/framing/src/assets/audio/jam2026.wav b/2026/framing/src/assets/audio/jam2026.wav Binary files differnew file mode 100644 index 0000000..84239cf --- /dev/null +++ b/2026/framing/src/assets/audio/jam2026.wav diff --git a/2026/framing/src/assets/audio/test.wav b/2026/framing/src/assets/audio/test.wav Binary files differdeleted file mode 100644 index 0eabe85..0000000 --- a/2026/framing/src/assets/audio/test.wav +++ /dev/null diff --git a/2026/framing/src/assets/audio/wind.wav b/2026/framing/src/assets/audio/wind.wav Binary files differnew file mode 100644 index 0000000..652fdde --- /dev/null +++ b/2026/framing/src/assets/audio/wind.wav diff --git a/2026/framing/src/assets/audio/wow.wav b/2026/framing/src/assets/audio/wow.wav Binary files differnew file mode 100644 index 0000000..11cb807 --- /dev/null +++ b/2026/framing/src/assets/audio/wow.wav diff --git a/2026/framing/src/assets/audio/youlose.wav b/2026/framing/src/assets/audio/youlose.wav Binary files differnew file mode 100644 index 0000000..6d4c935 --- /dev/null +++ b/2026/framing/src/assets/audio/youlose.wav diff --git a/2026/framing/src/assets/audio/yousuck.wav b/2026/framing/src/assets/audio/yousuck.wav Binary files differnew file mode 100644 index 0000000..8b96229 --- /dev/null +++ b/2026/framing/src/assets/audio/yousuck.wav diff --git a/2026/framing/src/assets/textures/intro.png b/2026/framing/src/assets/textures/intro.png Binary files differnew file mode 100644 index 0000000..5625316 --- /dev/null +++ b/2026/framing/src/assets/textures/intro.png diff --git a/2026/framing/src/assets/textures/titlescreen.png b/2026/framing/src/assets/textures/titlescreen.png Binary files differnew file mode 100644 index 0000000..6111223 --- /dev/null +++ b/2026/framing/src/assets/textures/titlescreen.png diff --git a/2026/framing/src/bindings.js b/2026/framing/src/bindings.js new file mode 100644 index 0000000..1f17e14 --- /dev/null +++ b/2026/framing/src/bindings.js @@ -0,0 +1,3 @@ +export function js_test() { + console.log("test"); +} diff --git a/2026/framing/src/game.rs b/2026/framing/src/game.rs index b8fb5ce..6c2df1b 100644 --- a/2026/framing/src/game.rs +++ b/2026/framing/src/game.rs @@ -3,12 +3,16 @@ use std::collections::HashMap; use teleia::*; use teleia::renderer::UberFlags; use wasm_bindgen::prelude::*; +use rand::seq::SliceRandom; use crate::assets; const NUM_LIVES: usize = 4; const LIFE_LOSS_FRAMES: u64 = 120; +const SOUND_POSITIVE: &[&str] = &["booyah", "excellent", "epicwin", "wow"]; +const SOUND_NEGATIVE: &[&str] = &["boo", "aww", "itsover", "youlose", "yousuck"]; + #[derive(PartialEq, Eq)] enum MrColor { Green, @@ -146,8 +150,11 @@ fn draw_mr_armed( } pub enum Mode { + Titlescreen, + Intro, BetweenGames, InGame, + PostGames, } pub struct Game { @@ -160,55 +167,116 @@ pub struct Game { impl Game { pub fn new(ctx: &context::Context, st: &mut state::State) -> Self { Self { - mode: Mode::BetweenGames, + mode: Mode::Titlescreen, mode_started: 0, renderer: renderer::Renderer::new(ctx, st, assets::Assets::new), lives: Lives::new(), } } + pub fn switch(&mut self, _ctx: &context::Context, st: &mut state::State, m: Mode) { + self.mode = m; + self.mode_started = st.tick; + } + fn draw_mrworld(&mut self, ctx: &context::Context, st: &mut state::State, fadeout: Option<Tick>) -> Erm<()> { + self.renderer.bind_uber_2d(ctx, st, UberFlags::TEXTURE_COLOR | UberFlags::TEXTURE_FLIP | UberFlags::SPRITE | UberFlags::OPACITY); + self.renderer.bind_texture(ctx, st, assets::Texture::Mrworld); + self.renderer.set_position_2d(ctx, st, Vec2::ZERO, st.render_dims); + self.renderer.set_vec2(ctx, st, "texture_flip", glam::Vec2::new(0.0, 1.0)); + if let Some(t) = fadeout { + if t < 35 { + self.renderer.set_texture_offset(ctx, st, 8, 1, 2 + (t / 5).clamp(0, 5) as i32, 0); + self.renderer.set_f32(ctx, st, "opacity", 1.0); + } else if t < 70 { + let since = ((t - 35) as f32).clamp(0.0, 34.0); + let opacity = (34.0 - since) / 34.0; + self.renderer.set_texture_offset(ctx, st, 8, 1, 7, 0); + self.renderer.set_f32(ctx, st, "opacity", opacity); + } + } else { + self.renderer.set_texture_offset(ctx, st, 8, 1, (st.tick as i32 / 20) % 2, 0); + self.renderer.set_f32(ctx, st, "opacity", 1.0); + } + self.renderer.render_square(ctx, st); + Ok(()) + } + fn play_random_sound(&mut self, ctx: &context::Context, st: &mut state::State, sounds: &[&str]) { + st.audio.play_sfx(sounds.choose(&mut rand::thread_rng()).unwrap()); + } } 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![ + ("jam2026".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/jam2026.wav"))), + ("wind".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/wind.wav"))), ("footsteps".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/footsteps.wav"))), + ("explosion".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/explosion.wav"))), + ("gamingtime".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/gamingtime.wav"))), + ("booyah".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/booyah.wav"))), + ("excellent".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/excellent.wav"))), + ("epicwin".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/epicwin.wav"))), + ("wow".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/wow.wav"))), + ("boo".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/boo.wav"))), + ("aww".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/aww.wav"))), + ("itsover".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/itsover.wav"))), + ("youlose".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/youlose.wav"))), + ("yousuck".to_owned(), audio::Audio::new(actx, include_bytes!("assets/audio/yousuck.wav"))), ]) } fn update(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { + let t = st.tick - self.mode_started; + match self.mode { + Mode::Intro => { + if t == 43 * 5 { + st.audio.play_sfx("explosion"); + st.audio.play_music("jam2026", None, None); + } + if t >= 57 * 5 { + self.switch(ctx, st, Mode::BetweenGames); + } + }, + _ => {}, + } Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { let t = st.tick - self.mode_started; match self.mode { - Mode::BetweenGames => { + Mode::Titlescreen => { self.renderer.begin_frame(ctx, st, Vec4::ZERO); self.renderer.bind_uber_2d(ctx, st, UberFlags::TEXTURE_COLOR | UberFlags::TEXTURE_FLIP | UberFlags::SPRITE); - self.renderer.bind_texture(ctx, st, assets::Texture::Mrworld); - self.renderer.set_texture_offset(ctx, st, 8, 1, (t / 20 % 2) as i32, 0); + self.renderer.bind_texture(ctx, st, assets::Texture::Titlescreen); + self.renderer.set_texture_offset(ctx, st, 2, 1, (t / 60 % 2) as i32, 0); self.renderer.set_position_2d(ctx, st, Vec2::ZERO, st.render_dims); self.renderer.set_vec2(ctx, st, "texture_flip", glam::Vec2::new(0.0, 1.0)); self.renderer.render_square(ctx, st); - self.lives.render(ctx, st, &mut self.renderer)?; }, - Mode::InGame => { + Mode::Intro => { self.renderer.begin_frame(ctx, st, Vec4::ZERO); - self.renderer.bind_uber_2d(ctx, st, UberFlags::TEXTURE_COLOR | UberFlags::TEXTURE_FLIP | UberFlags::SPRITE | UberFlags::OPACITY); - self.renderer.bind_texture(ctx, st, assets::Texture::Mrworld); + self.draw_mrworld(ctx, st, None)?; + self.lives.render(ctx, st, &mut self.renderer)?; + let f = t / 5; + let sx = f % 8; + let sy = f / 8; + self.renderer.bind_uber_2d(ctx, st, UberFlags::TEXTURE_COLOR | UberFlags::TEXTURE_FLIP | UberFlags::SPRITE); + self.renderer.bind_texture(ctx, st, assets::Texture::Intro); + self.renderer.set_texture_offset(ctx, st, 8, 8, sx as i32, sy as i32); self.renderer.set_position_2d(ctx, st, Vec2::ZERO, st.render_dims); self.renderer.set_vec2(ctx, st, "texture_flip", glam::Vec2::new(0.0, 1.0)); - if t < 35 { - self.renderer.set_texture_offset(ctx, st, 8, 1, 2 + (t / 5).clamp(0, 5) as i32, 0); - self.renderer.set_f32(ctx, st, "opacity", 1.0); - self.renderer.render_square(ctx, st); - } else if t < 70 { - let since = ((t - 35) as f32).clamp(0.0, 34.0); - let opacity = (34.0 - since) / 34.0; - self.renderer.set_texture_offset(ctx, st, 8, 1, 7, 0); - self.renderer.set_f32(ctx, st, "opacity", opacity); - self.renderer.render_square(ctx, st); - } - // self.lives.render(ctx, st, &mut self.renderer)?; + self.renderer.render_square(ctx, st); } + Mode::BetweenGames => { + self.renderer.begin_frame(ctx, st, Vec4::ZERO); + self.draw_mrworld(ctx, st, None)?; + self.lives.render(ctx, st, &mut self.renderer)?; + }, + Mode::InGame => { + self.renderer.begin_frame(ctx, st, Vec4::ZERO); + self.draw_mrworld(ctx, st, Some(t))?; + // self.lives.render(ctx, st, &mut self.renderer)?; + }, + Mode::PostGames => { + }, } Ok(()) } @@ -217,22 +285,38 @@ impl teleia::state::Game for Game { } } +#[wasm_bindgen(module = "/src/bindings.js")] +extern { + fn js_test(); +} + +#[wasm_bindgen] +pub fn titlescreen_click() { + contextualize(|ctx, st, g: &mut Game| { + g.switch(ctx, st, Mode::Intro); + st.audio.play_music("wind", None, None); + }); +} + #[wasm_bindgen] pub fn start_game() { contextualize(|ctx, st, g: &mut Game| { - g.mode = Mode::InGame; - g.mode_started = st.tick; + g.switch(ctx, st, Mode::InGame); + st.audio.mute_music(0.0); }); } #[wasm_bindgen] pub fn end_game(win: bool) { contextualize(|ctx, st, g: &mut Game| { - g.mode = Mode::BetweenGames; - g.mode_started = st.tick; - if !win { + g.switch(ctx, st, Mode::BetweenGames); + st.audio.unmute_music(0.0); + if win { + g.play_random_sound(ctx, st, SOUND_POSITIVE); + } else { g.lives.lose_life(ctx, st); st.audio.play_sfx("footsteps"); + g.play_random_sound(ctx, st, SOUND_NEGATIVE); } }); } |
