diff --git a/src/app.rs b/src/app.rs index 2806e05..4449e56 100644 --- a/src/app.rs +++ b/src/app.rs @@ -231,6 +231,7 @@ impl App { } } } + self.game.update(); } fn do_freecam(&mut self) { diff --git a/src/game.rs b/src/game.rs index 55683b8..cc59ffa 100644 --- a/src/game.rs +++ b/src/game.rs @@ -10,7 +10,7 @@ use sfml::{ use crate::{ graphics::{ScreenSc, ScreenVec}, - math::{wp_to_tp, WorldPos}, + math::{smoothwave, wp_to_tp, WorldPos}, res::Res, tiles::TileDb, world::{Tile, TileId, TilePos, World}, @@ -37,6 +37,9 @@ pub struct GameState { pub clock: SfBox, pub light_sources: Vec, pub tile_db: TileDb, + /// This is the number of ticks since the world has started. + /// In other words, the age of the world. + pub ticks: u64, } #[derive(Debug, Inspect)] @@ -51,6 +54,9 @@ pub enum Biome { } impl GameState { + pub fn update(&mut self) { + self.ticks += 1; + } pub(crate) fn draw_world(&mut self, rt: &mut RenderTexture, res: &mut Res) { self.light_sources.clear(); let mut s = Sprite::with_texture(&res.tile_atlas); @@ -111,7 +117,8 @@ impl GameState { )); for ls in &self.light_sources { let mut s = Sprite::with_texture(&res.light_texture); - s.set_scale((4., 4.)); + let flicker = smoothwave(self.ticks, 40) as f32 / 64.0; + s.set_scale((4. + flicker, 4. + flicker)); s.set_origin((128., 128.)); s.set_position((ls.pos.x.into(), ls.pos.y.into())); lightmap.draw(&s); @@ -157,6 +164,7 @@ impl Default for GameState { clock: Clock::start(), light_sources: Vec::new(), tile_db: TileDb::load_or_default(), + ticks: 0, } } } diff --git a/src/math.rs b/src/math.rs index 3c90ae1..6be56f8 100644 --- a/src/math.rs +++ b/src/math.rs @@ -1,5 +1,5 @@ use egui_inspect::derive::Inspect; -use num_traits::Signed; +use num_traits::{Num, Signed}; use crate::world::{TilePos, TilePosScalar}; @@ -70,6 +70,29 @@ pub fn center_offset + Copy + Signed>(xw: N, yw: N) -> N { diff / N::from(2) } +/// A smooth triangle-wave like transform of the input value, oscillating between 0 and the ceiling. +pub fn smoothwave + PartialOrd + Copy>(input: T, max: T) -> T { + let period = max * T::from(2); + let value = input % period; + if value < max { + value + } else { + period - value + } +} + +#[test] +fn test_smooth_wave() { + assert_eq!(smoothwave(0, 100), 0); + assert_eq!(smoothwave(50, 100), 50); + assert_eq!(smoothwave(125, 100), 75); + assert_eq!(smoothwave(150, 100), 50); + assert_eq!(smoothwave(175, 100), 25); + assert_eq!(smoothwave(199, 100), 1); + assert_eq!(smoothwave(200, 100), 0); + assert_eq!(smoothwave(201, 100), 1); +} + #[test] fn test_wp_to_tp() { assert_eq!(wp_to_tp(0), 0);