Time starts working
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
//! This module helps us dealing with characters.
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::engine::bbox::Bbox;
|
||||
use crate::engine::controls::{Action, Controls};
|
||||
use crate::engine::event::{Event, Keyboard};
|
||||
use crate::engine::math::{clamp, duration_as_f64};
|
||||
use crate::engine::math::{clamp, duration_as_f64, duration_as_frame};
|
||||
use crate::engine::physics;
|
||||
use crate::engine::scene::Updatable;
|
||||
use crate::engine::texture::Texture;
|
||||
@@ -70,7 +70,7 @@ pub struct Character {
|
||||
max_jump: usize,
|
||||
|
||||
/// The timer of the character's animation.
|
||||
animation_timer: Duration,
|
||||
animation_timer: SystemTime,
|
||||
|
||||
/// Whether the character is walking or not.
|
||||
walking: bool,
|
||||
@@ -89,7 +89,7 @@ impl Character {
|
||||
side: Side::Right,
|
||||
jump_counter: 1,
|
||||
max_jump: 1,
|
||||
animation_timer: Duration::from_millis(0),
|
||||
animation_timer: UNIX_EPOCH,
|
||||
can_jump: true,
|
||||
walking: false,
|
||||
}
|
||||
@@ -147,7 +147,7 @@ impl Character {
|
||||
}
|
||||
|
||||
impl Updatable for Character {
|
||||
fn update(&mut self, duration: &Duration, keyboard: &Keyboard) {
|
||||
fn update(&mut self, now: SystemTime, duration: Duration, keyboard: &Keyboard) {
|
||||
let mut force = Vector::new(0.0, 0.0);
|
||||
|
||||
if let Some(ref controls) = self.controls {
|
||||
@@ -156,13 +156,13 @@ impl Updatable for Character {
|
||||
|
||||
if let Some(side) = Side::from_force(force) {
|
||||
if !self.walking {
|
||||
self.animation_timer = Duration::from_millis(0);
|
||||
self.animation_timer = now;
|
||||
}
|
||||
self.walking = true;
|
||||
self.side = side;
|
||||
} else {
|
||||
if self.walking {
|
||||
self.animation_timer = Duration::from_millis(0);
|
||||
self.animation_timer = now;
|
||||
}
|
||||
self.walking = false;
|
||||
}
|
||||
@@ -218,8 +218,8 @@ impl Drawable for Character {
|
||||
Texture::Rusty
|
||||
}
|
||||
|
||||
fn texture_rect(&self) -> Bbox {
|
||||
let frame = 0.0; // duration_as_frame(&Instant::now().duration_since(self.animation_timer), 4);
|
||||
fn texture_rect(&self, now: SystemTime) -> Bbox {
|
||||
let frame = duration_as_frame(now.duration_since(self.animation_timer).unwrap(), 4) as f64;
|
||||
let offset = if self.walking { 64.0 } else { 0.0 };
|
||||
Bbox::new(self.side.offset() as f64 + offset, frame * 32.0, 32.0, 32.0)
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,5 +1,7 @@
|
||||
//! This module contains everything related to maps.
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::engine::bbox::Bbox;
|
||||
use crate::engine::math::{clamp, Matrix};
|
||||
use crate::engine::texture::Texture;
|
||||
@@ -233,9 +235,9 @@ impl Drawable for PositionedTile {
|
||||
Texture::Overworld
|
||||
}
|
||||
|
||||
fn texture_rect(&self) -> Bbox {
|
||||
fn texture_rect(&self, _now: SystemTime) -> Bbox {
|
||||
let offset = self.graphic.offset();
|
||||
Bbox::new(offset.0 as f64, offset.0 as f64, SPRITE_SIZE, SPRITE_SIZE)
|
||||
Bbox::new(offset.0 as f64, offset.1 as f64, SPRITE_SIZE, SPRITE_SIZE)
|
||||
}
|
||||
|
||||
fn position(&self) -> Vector {
|
||||
|
||||
+10
-3
@@ -1,7 +1,14 @@
|
||||
//! This module contains useful math tools.
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub fn now(performance: &web_sys::Performance) -> SystemTime {
|
||||
let now = performance.now();
|
||||
let secs = (now as u64) / 1_000;
|
||||
let nanos = (((now as u64) % 1_000) as u32) * 1_000_000;
|
||||
UNIX_EPOCH + Duration::new(secs, nanos)
|
||||
}
|
||||
|
||||
/// Clamp a number between two boundaries.
|
||||
pub fn clamp(number: f64, min: f64, max: f64) -> f64 {
|
||||
@@ -15,14 +22,14 @@ pub fn clamp(number: f64, min: f64, max: f64) -> f64 {
|
||||
}
|
||||
|
||||
/// Converts a duration into an animation frame number.
|
||||
pub fn duration_as_frame(duration: &Duration, total: usize) -> i32 {
|
||||
pub fn duration_as_frame(duration: Duration, total: usize) -> i32 {
|
||||
let secs = duration_as_f64(duration);
|
||||
|
||||
(secs * 10.0) as i32 % total as i32
|
||||
}
|
||||
|
||||
/// Converts a duration into its number of seconds.
|
||||
pub fn duration_as_f64(duration: &Duration) -> f64 {
|
||||
pub fn duration_as_f64(duration: Duration) -> f64 {
|
||||
duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 1_000_000_000.0
|
||||
}
|
||||
|
||||
|
||||
+24
-7
@@ -13,7 +13,7 @@ pub mod vector;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
@@ -23,6 +23,7 @@ use crate::engine::character::Character;
|
||||
use crate::engine::controls::Controls;
|
||||
use crate::engine::event::{Key, Keyboard};
|
||||
use crate::engine::map::Map;
|
||||
use crate::engine::math::now;
|
||||
use crate::engine::scene::{Scene, State};
|
||||
use crate::engine::texture::{Texture, TextureManager};
|
||||
use crate::engine::vector::Vector;
|
||||
@@ -55,6 +56,9 @@ pub struct Engine {
|
||||
///
|
||||
/// We keep a reference so that we can easily render things.
|
||||
pub context: Rc<web_sys::CanvasRenderingContext2d>,
|
||||
|
||||
/// The performance object.
|
||||
pub performance: Rc<web_sys::Performance>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
@@ -62,6 +66,7 @@ impl Engine {
|
||||
pub fn new() -> Result<Engine> {
|
||||
let window = unwrap!(web_sys::window());
|
||||
let document = unwrap!(window.document());
|
||||
let performance = unwrap!(window.performance());
|
||||
let canvas = unwrap!(document.get_element_by_id("canvas"));
|
||||
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::<web_sys::HtmlCanvasElement>()?;
|
||||
|
||||
@@ -77,16 +82,18 @@ impl Engine {
|
||||
let character = Character::with_controls(Controls::default_keyboard());
|
||||
scene.add(character);
|
||||
|
||||
let inner = InnerEngine::new(&document, scene)?;
|
||||
let inner = InnerEngine::new(&document, &performance, scene)?;
|
||||
|
||||
let window = Rc::new(window);
|
||||
let document = Rc::new(document);
|
||||
let performance = Rc::new(performance);
|
||||
let context = Rc::new(context);
|
||||
|
||||
Ok(Engine {
|
||||
inner: Rc::new(RefCell::new(inner)),
|
||||
window,
|
||||
document,
|
||||
performance,
|
||||
context,
|
||||
})
|
||||
}
|
||||
@@ -140,10 +147,12 @@ impl Engine {
|
||||
}
|
||||
|
||||
// Manage the physics
|
||||
let duration = Duration::from_millis(60);
|
||||
let now = now(&self.performance);
|
||||
let duration = unwrap!(now.duration_since(inner.after_loop).ok());
|
||||
inner.after_loop = now;
|
||||
|
||||
let keyboard = inner.keyboard.clone();
|
||||
if inner.scene.update(&duration, &keyboard) == State::Finished {
|
||||
if inner.scene.update(now, duration, &keyboard) == State::Finished {
|
||||
// running = false;
|
||||
}
|
||||
|
||||
@@ -155,7 +164,7 @@ impl Engine {
|
||||
let inner = self.inner.borrow();
|
||||
let image = inner.textures.get(drawable.texture());
|
||||
|
||||
let source = drawable.texture_rect();
|
||||
let source = drawable.texture_rect(inner.after_loop);
|
||||
let mut dest = source.clone();
|
||||
dest.position = drawable.position();
|
||||
|
||||
@@ -203,6 +212,9 @@ pub struct InnerEngine {
|
||||
/// The scene of the engine.
|
||||
pub scene: Scene,
|
||||
|
||||
/// The time when the loop is done.
|
||||
pub after_loop: SystemTime,
|
||||
|
||||
/// The keyboard.
|
||||
pub keyboard: Keyboard,
|
||||
|
||||
@@ -212,9 +224,14 @@ pub struct InnerEngine {
|
||||
|
||||
impl InnerEngine {
|
||||
/// Initializes the engine.
|
||||
pub fn new(document: &web_sys::Document, scene: Scene) -> Result<InnerEngine> {
|
||||
pub fn new(
|
||||
document: &web_sys::Document,
|
||||
performance: &web_sys::Performance,
|
||||
scene: Scene,
|
||||
) -> Result<InnerEngine> {
|
||||
Ok(InnerEngine {
|
||||
scene,
|
||||
after_loop: now(&performance),
|
||||
keyboard: Keyboard::new(document)?,
|
||||
textures: TextureManager::new()?,
|
||||
})
|
||||
@@ -227,7 +244,7 @@ pub trait Drawable {
|
||||
fn texture(&self) -> Texture;
|
||||
|
||||
/// Returns the coordinates to use on the texture.
|
||||
fn texture_rect(&self) -> Bbox;
|
||||
fn texture_rect(&self, now: SystemTime) -> Bbox;
|
||||
|
||||
/// Returns the position on which the drawable should be drawn.
|
||||
fn position(&self) -> Vector;
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
//! This module contains the scene struct which holds everything needed during a game.
|
||||
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::engine::character::Character;
|
||||
use crate::engine::event::{Event, Keyboard};
|
||||
@@ -84,7 +84,7 @@ impl Scene {
|
||||
// }
|
||||
|
||||
/// Updates the whole scene.
|
||||
pub fn update(&mut self, duration: &Duration, keyboard: &Keyboard) -> State {
|
||||
pub fn update(&mut self, now: SystemTime, duration: Duration, keyboard: &Keyboard) -> State {
|
||||
let mut state = State::Finished;
|
||||
|
||||
for c in &mut self.characters {
|
||||
@@ -96,7 +96,7 @@ impl Scene {
|
||||
// Compute the offset between position and bbox
|
||||
let offset = old.position - c.position;
|
||||
|
||||
c.update(duration, keyboard);
|
||||
c.update(now, duration, keyboard);
|
||||
|
||||
if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) {
|
||||
c.position = position - offset;
|
||||
@@ -144,7 +144,7 @@ impl Scene {
|
||||
/// Trait that needs to be implemented for everything that can be updatable.
|
||||
pub trait Updatable {
|
||||
/// Updates the thing depending on the duration since last frame.
|
||||
fn update(&mut self, duration: &Duration, keyboard: &Keyboard);
|
||||
fn update(&mut self, now: SystemTime, duration: Duration, keyboard: &Keyboard);
|
||||
|
||||
/// Called when an event arrives.
|
||||
fn manage_event(&mut self, event: &Event);
|
||||
|
||||
Reference in New Issue
Block a user