Starting to get something

This commit is contained in:
Thomas Forgione 2022-07-30 16:32:55 +02:00
parent abe9b4ca38
commit 6360cd3bee
8 changed files with 154 additions and 89 deletions

View File

@ -8,7 +8,10 @@ use crate::engine::event::{Event, Keyboard};
use crate::engine::math::{clamp, duration_as_f64}; use crate::engine::math::{clamp, duration_as_f64};
use crate::engine::physics; use crate::engine::physics;
use crate::engine::scene::Updatable; use crate::engine::scene::Updatable;
use crate::engine::texture::Texture;
use crate::engine::vector::Vector; use crate::engine::vector::Vector;
use crate::engine::Drawable;
use crate::log;
/// The different sides a character can face. /// The different sides a character can face.
pub enum Side { pub enum Side {
@ -67,7 +70,7 @@ pub struct Character {
max_jump: usize, max_jump: usize,
/// The timer of the character's animation. /// The timer of the character's animation.
animation_timer: Instant, animation_timer: Duration,
/// Whether the character is walking or not. /// Whether the character is walking or not.
walking: bool, walking: bool,
@ -86,7 +89,7 @@ impl Character {
side: Side::Right, side: Side::Right,
jump_counter: 1, jump_counter: 1,
max_jump: 1, max_jump: 1,
animation_timer: Instant::now(), animation_timer: Duration::from_millis(0),
can_jump: true, can_jump: true,
walking: false, walking: false,
} }
@ -124,7 +127,7 @@ impl Character {
/// Makes the player die. /// Makes the player die.
pub fn die(&self) { pub fn die(&self) {
panic!(); log!("dead");
} }
/// Returns a reference to the controls. /// Returns a reference to the controls.
@ -153,13 +156,13 @@ impl Updatable for Character {
if let Some(side) = Side::from_force(force) { if let Some(side) = Side::from_force(force) {
if !self.walking { if !self.walking {
self.animation_timer = Instant::now(); self.animation_timer = Duration::from_millis(0);
} }
self.walking = true; self.walking = true;
self.side = side; self.side = side;
} else { } else {
if self.walking { if self.walking {
self.animation_timer = Instant::now(); self.animation_timer = Duration::from_millis(0);
} }
self.walking = false; self.walking = false;
} }
@ -210,18 +213,18 @@ impl Updatable for Character {
} }
} }
// impl Drawable for Character { impl Drawable for Character {
// fn texture(&self) -> Texture { fn texture(&self) -> Texture {
// Texture::Rusty Texture::Rusty
// } }
//
// fn texture_rect(&self) -> IntRect { fn texture_rect(&self) -> Bbox {
// let frame = duration_as_frame(&Instant::now().duration_since(self.animation_timer), 4); let frame = 0.0; // duration_as_frame(&Instant::now().duration_since(self.animation_timer), 4);
// let offset = if self.walking { 64 } else { 0 }; let offset = if self.walking { 64.0 } else { 0.0 };
// IntRect::new(self.side.offset() + offset, frame * 32, 32, 32) Bbox::new(self.side.offset() as f64 + offset, frame * 32.0, 32.0, 32.0)
// } }
//
// fn position(&self) -> Vector<f32> { fn position(&self) -> Vector {
// self.position self.position
// } }
// } }

View File

@ -2,6 +2,7 @@
use crate::engine::event::{Event, Key, Keyboard}; use crate::engine::event::{Event, Key, Keyboard};
use crate::engine::vector::Vector; use crate::engine::vector::Vector;
use crate::log;
/// The different actions that a user can do. /// The different actions that a user can do.
pub enum Action { pub enum Action {

View File

@ -2,8 +2,10 @@
use crate::engine::bbox::Bbox; use crate::engine::bbox::Bbox;
use crate::engine::math::{clamp, Matrix}; use crate::engine::math::{clamp, Matrix};
use crate::engine::texture::Texture;
use crate::engine::texture::SPRITE_SIZE; use crate::engine::texture::SPRITE_SIZE;
use crate::engine::vector::Vector; use crate::engine::vector::Vector;
use crate::engine::Drawable;
use crate::Result; use crate::Result;
/// Converts the byte with bits corresponding to the neighbours to the offset on the generated /// Converts the byte with bits corresponding to the neighbours to the offset on the generated
@ -62,7 +64,7 @@ pub fn byte_to_index(byte: u8) -> i32 {
} }
/// This enum represents if the collision happens on the X axis or the Y axis. /// This enum represents if the collision happens on the X axis or the Y axis.
#[derive(Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum CollisionAxis { pub enum CollisionAxis {
/// The X axis. /// The X axis.
X, X,
@ -226,20 +228,20 @@ pub struct PositionedTile {
pub position: Vector, pub position: Vector,
} }
// impl Drawable for PositionedTile { impl Drawable for PositionedTile {
// fn texture(&self) -> Texture { fn texture(&self) -> Texture {
// Texture::Overworld Texture::Overworld
// } }
//
// fn texture_rect(&self) -> Bbox { fn texture_rect(&self) -> Bbox {
// let offset = self.graphic.offset(); let offset = self.graphic.offset();
// Bbox::new(offset.x, offset.x, SPRITE_SIZE, SPRITE_SIZE) Bbox::new(offset.0 as f64, offset.0 as f64, SPRITE_SIZE, SPRITE_SIZE)
// } }
//
// fn position(&self) -> Vector { fn position(&self) -> Vector {
// self.position self.position
// } }
// } }
/// The map represents the tiles contained in a level. /// The map represents the tiles contained in a level.
#[derive(Clone)] #[derive(Clone)]

View File

@ -18,10 +18,14 @@ use std::time::Duration;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use crate::engine::bbox::Bbox;
use crate::engine::character::Character;
use crate::engine::controls::Controls;
use crate::engine::event::{Key, Keyboard}; use crate::engine::event::{Key, Keyboard};
use crate::engine::map::Map; use crate::engine::map::Map;
use crate::engine::scene::{Scene, State}; use crate::engine::scene::{Scene, State};
use crate::engine::texture::TextureManager; use crate::engine::texture::{Texture, TextureManager};
use crate::engine::vector::Vector;
use crate::{error_js, log, Result}; use crate::{error_js, log, Result};
macro_rules! unwrap { macro_rules! unwrap {
@ -41,6 +45,9 @@ pub struct Engine {
/// We need Rc<RefCell> in order to deal with events. /// We need Rc<RefCell> in order to deal with events.
pub inner: Rc<RefCell<InnerEngine>>, pub inner: Rc<RefCell<InnerEngine>>,
/// The web page window.
pub window: Rc<web_sys::Window>,
/// The web page document. /// The web page document.
pub document: Rc<web_sys::Document>, pub document: Rc<web_sys::Document>,
@ -61,20 +68,24 @@ impl Engine {
canvas.set_width(1920); canvas.set_width(1920);
canvas.set_height(1080); canvas.set_height(1080);
let context = canvas let context =
.get_context("2d")? unwrap!(canvas.get_context("2d")?).dyn_into::<web_sys::CanvasRenderingContext2d>()?;
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()?;
let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap(); let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap();
let scene = Scene::from_map(map); let mut scene = Scene::from_map(map);
let character = Character::with_controls(Controls::default_keyboard());
scene.add(character);
let inner = InnerEngine::new(&document, scene)?; let inner = InnerEngine::new(&document, scene)?;
let window = Rc::new(window);
let document = Rc::new(document); let document = Rc::new(document);
let context = Rc::new(context); let context = Rc::new(context);
Ok(Engine { Ok(Engine {
inner: Rc::new(RefCell::new(inner)), inner: Rc::new(RefCell::new(inner)),
window,
document, document,
context, context,
}) })
@ -89,10 +100,7 @@ impl Engine {
} }
}); });
web_sys::window() (*self.window).request_animation_frame(cb.as_ref().unchecked_ref())?;
.unwrap()
.request_animation_frame(cb.as_ref().unchecked_ref())
.unwrap();
cb.forget(); cb.forget();
@ -115,10 +123,7 @@ impl Engine {
} }
}); });
web_sys::window() (*self.window).request_animation_frame(cb.as_ref().unchecked_ref())?;
.unwrap()
.request_animation_frame(cb.as_ref().unchecked_ref())
.unwrap();
cb.forget(); cb.forget();
@ -142,29 +147,19 @@ impl Engine {
// running = false; // running = false;
} }
// Perform update Ok(())
let mut dx = 0.0;
let mut dy = 0.0;
if inner.keyboard.is_key_pressed(Key::ArrowDown) {
dy += 5.0;
} }
if inner.keyboard.is_key_pressed(Key::ArrowUp) { /// Draw a drawable.
dy -= 5.0; pub fn draw<D: Drawable>(&self, drawable: &D) -> Result<()> {
} let inner = self.inner.borrow();
let image = inner.textures.get(drawable.texture());
if inner.keyboard.is_key_pressed(Key::ArrowLeft) { let source = drawable.texture_rect();
dx -= 5.0; let mut dest = source.clone();
} dest.position = drawable.position();
if inner.keyboard.is_key_pressed(Key::ArrowRight) {
dx += 5.0;
}
inner.x += dx;
inner.y += dy;
image.render(source, dest, &self.context)?;
Ok(()) Ok(())
} }
@ -172,12 +167,32 @@ impl Engine {
pub fn render(&self) -> Result<()> { pub fn render(&self) -> Result<()> {
let inner = self.inner.borrow(); let inner = self.inner.borrow();
// Perform render // Clear render
self.context.clear_rect(0.0, 0.0, 1920.0, 1080.0); self.context.clear_rect(0.0, 0.0, 1920.0, 1080.0);
inner self.context
.textures .set_fill_style(&JsValue::from_str("rgb(135, 206, 235)"));
.rusty self.context.fill_rect(0.0, 0.0, 1920.0, 1080.0);
.render(inner.x, inner.y, &self.context)?;
// Draw the scene
let map = inner.scene.map();
let rows = map.rows();
let cols = map.cols();
for i in 0..rows {
for j in 0..cols {
let tile = map.at(i, j);
if tile.graphic.is_visible() {
self.draw(&tile)?;
}
}
}
// Draw characters
for c in inner.scene.characters() {
if true {
self.draw(c)?;
}
}
Ok(()) Ok(())
} }
@ -185,12 +200,6 @@ impl Engine {
/// The data contained in our engine. /// The data contained in our engine.
pub struct InnerEngine { pub struct InnerEngine {
/// The x position of the drawing.
pub x: f64,
/// The y position of the drawing.
pub y: f64,
/// The scene of the engine. /// The scene of the engine.
pub scene: Scene, pub scene: Scene,
@ -204,13 +213,22 @@ pub struct InnerEngine {
impl InnerEngine { impl InnerEngine {
/// Initializes the engine. /// Initializes the engine.
pub fn new(document: &web_sys::Document, scene: Scene) -> Result<InnerEngine> { pub fn new(document: &web_sys::Document, scene: Scene) -> Result<InnerEngine> {
log!("sup");
Ok(InnerEngine { Ok(InnerEngine {
x: 0.0,
y: 0.0,
scene, scene,
keyboard: Keyboard::new(document)?, keyboard: Keyboard::new(document)?,
textures: TextureManager::new()?, textures: TextureManager::new()?,
}) })
} }
} }
/// Our custom drawable trait.
pub trait Drawable {
/// Returns the texture of the drawable.
fn texture(&self) -> Texture;
/// Returns the coordinates to use on the texture.
fn texture_rect(&self) -> Bbox;
/// Returns the position on which the drawable should be drawn.
fn position(&self) -> Vector;
}

View File

@ -108,7 +108,7 @@ impl Scene {
c.ground_collision(); c.ground_collision();
} }
c.die(); // c.die();
} else { } else {
c.fall_off(); c.fall_off();
} }

View File

@ -8,6 +8,7 @@ use wasm_bindgen::JsCast;
use web_sys::HtmlImageElement; use web_sys::HtmlImageElement;
use crate::engine::bbox::Bbox;
use crate::{log, Result}; use crate::{log, Result};
/// The size of sprites. /// The size of sprites.
@ -68,28 +69,61 @@ impl Image {
/// Renders the image on a context. /// Renders the image on a context.
pub fn render( pub fn render(
&self, &self,
x: f64, source: Bbox,
y: f64, dest: Bbox,
context: &web_sys::CanvasRenderingContext2d, context: &web_sys::CanvasRenderingContext2d,
) -> Result<()> { ) -> Result<()> {
context.draw_image_with_html_image_element(&self.inner.borrow().inner, x, y)?; context.draw_image_with_html_image_element_and_sw_and_sh_and_dx_and_dy_and_dw_and_dh(
&self.inner.borrow().inner,
source.position.x,
source.position.y,
source.size.x,
source.size.y,
dest.position.x,
dest.position.y,
dest.size.x,
dest.size.y,
)?;
Ok(()) Ok(())
} }
} }
/// The list of all our textures.
#[derive(Copy, Clone)]
pub enum Texture {
/// The main character sprite.
Rusty,
/// The sprites from the overworld.
Overworld,
}
/// Our texture manager. /// Our texture manager.
/// ///
/// It holds all our resources. /// It holds all our resources.
pub struct TextureManager { pub struct TextureManager {
/// The main character sprite. /// The main character sprite.
pub rusty: Image, pub rusty: Image,
/// The sprites from the overworld.
pub overworld: Image,
} }
impl TextureManager { impl TextureManager {
/// Creates and start the loading of all our textures. /// Creates and start the loading of all our textures.
pub fn new() -> Result<TextureManager> { pub fn new() -> Result<TextureManager> {
let rusty = Image::new("static/textures/rusty.png")?; Ok(TextureManager {
Ok(TextureManager { rusty }) rusty: Image::new("static/textures/rusty.png")?,
overworld: Image::new("static/textures/overworld.png")?,
})
}
/// Returns the image corresponding to a certain texture.
pub fn get(&self, texture: Texture) -> &Image {
match texture {
Texture::Rusty => &self.rusty,
Texture::Overworld => &self.overworld,
}
} }
} }

View File

@ -1,5 +1,6 @@
//! A module for basic maths. //! A module for basic maths.
use std::fmt;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// A 2 dimensional vector. /// A 2 dimensional vector.
@ -79,3 +80,9 @@ impl Mul<Vector> for f64 {
} }
} }
} }
impl fmt::Display for Vector {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "({}, {})", self.x, self.y)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB