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

View File

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

View File

@ -2,8 +2,10 @@
use crate::engine::bbox::Bbox;
use crate::engine::math::{clamp, Matrix};
use crate::engine::texture::Texture;
use crate::engine::texture::SPRITE_SIZE;
use crate::engine::vector::Vector;
use crate::engine::Drawable;
use crate::Result;
/// 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.
#[derive(Copy, Clone)]
#[derive(Debug, Copy, Clone)]
pub enum CollisionAxis {
/// The X axis.
X,
@ -226,20 +228,20 @@ pub struct PositionedTile {
pub position: Vector,
}
// impl Drawable for PositionedTile {
// fn texture(&self) -> Texture {
// Texture::Overworld
// }
//
// fn texture_rect(&self) -> Bbox {
// let offset = self.graphic.offset();
// Bbox::new(offset.x, offset.x, SPRITE_SIZE, SPRITE_SIZE)
// }
//
// fn position(&self) -> Vector {
// self.position
// }
// }
impl Drawable for PositionedTile {
fn texture(&self) -> Texture {
Texture::Overworld
}
fn texture_rect(&self) -> Bbox {
let offset = self.graphic.offset();
Bbox::new(offset.0 as f64, offset.0 as f64, SPRITE_SIZE, SPRITE_SIZE)
}
fn position(&self) -> Vector {
self.position
}
}
/// The map represents the tiles contained in a level.
#[derive(Clone)]

View File

@ -18,10 +18,14 @@ use std::time::Duration;
use wasm_bindgen::prelude::*;
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::map::Map;
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};
macro_rules! unwrap {
@ -41,6 +45,9 @@ pub struct Engine {
/// We need Rc<RefCell> in order to deal with events.
pub inner: Rc<RefCell<InnerEngine>>,
/// The web page window.
pub window: Rc<web_sys::Window>,
/// The web page document.
pub document: Rc<web_sys::Document>,
@ -61,20 +68,24 @@ impl Engine {
canvas.set_width(1920);
canvas.set_height(1080);
let context = canvas
.get_context("2d")?
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()?;
let context =
unwrap!(canvas.get_context("2d")?).dyn_into::<web_sys::CanvasRenderingContext2d>()?;
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 window = Rc::new(window);
let document = Rc::new(document);
let context = Rc::new(context);
Ok(Engine {
inner: Rc::new(RefCell::new(inner)),
window,
document,
context,
})
@ -89,10 +100,7 @@ impl Engine {
}
});
web_sys::window()
.unwrap()
.request_animation_frame(cb.as_ref().unchecked_ref())
.unwrap();
(*self.window).request_animation_frame(cb.as_ref().unchecked_ref())?;
cb.forget();
@ -115,10 +123,7 @@ impl Engine {
}
});
web_sys::window()
.unwrap()
.request_animation_frame(cb.as_ref().unchecked_ref())
.unwrap();
(*self.window).request_animation_frame(cb.as_ref().unchecked_ref())?;
cb.forget();
@ -142,29 +147,19 @@ impl Engine {
// running = false;
}
// Perform update
let mut dx = 0.0;
let mut dy = 0.0;
Ok(())
}
if inner.keyboard.is_key_pressed(Key::ArrowDown) {
dy += 5.0;
}
/// Draw a drawable.
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::ArrowUp) {
dy -= 5.0;
}
if inner.keyboard.is_key_pressed(Key::ArrowLeft) {
dx -= 5.0;
}
if inner.keyboard.is_key_pressed(Key::ArrowRight) {
dx += 5.0;
}
inner.x += dx;
inner.y += dy;
let source = drawable.texture_rect();
let mut dest = source.clone();
dest.position = drawable.position();
image.render(source, dest, &self.context)?;
Ok(())
}
@ -172,12 +167,32 @@ impl Engine {
pub fn render(&self) -> Result<()> {
let inner = self.inner.borrow();
// Perform render
// Clear render
self.context.clear_rect(0.0, 0.0, 1920.0, 1080.0);
inner
.textures
.rusty
.render(inner.x, inner.y, &self.context)?;
self.context
.set_fill_style(&JsValue::from_str("rgb(135, 206, 235)"));
self.context.fill_rect(0.0, 0.0, 1920.0, 1080.0);
// 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(())
}
@ -185,12 +200,6 @@ impl Engine {
/// The data contained in our engine.
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.
pub scene: Scene,
@ -204,13 +213,22 @@ pub struct InnerEngine {
impl InnerEngine {
/// Initializes the engine.
pub fn new(document: &web_sys::Document, scene: Scene) -> Result<InnerEngine> {
log!("sup");
Ok(InnerEngine {
x: 0.0,
y: 0.0,
scene,
keyboard: Keyboard::new(document)?,
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.die();
// c.die();
} else {
c.fall_off();
}

View File

@ -8,6 +8,7 @@ use wasm_bindgen::JsCast;
use web_sys::HtmlImageElement;
use crate::engine::bbox::Bbox;
use crate::{log, Result};
/// The size of sprites.
@ -68,28 +69,61 @@ impl Image {
/// Renders the image on a context.
pub fn render(
&self,
x: f64,
y: f64,
source: Bbox,
dest: Bbox,
context: &web_sys::CanvasRenderingContext2d,
) -> 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(())
}
}
/// 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.
///
/// It holds all our resources.
pub struct TextureManager {
/// The main character sprite.
pub rusty: Image,
/// The sprites from the overworld.
pub overworld: Image,
}
impl TextureManager {
/// Creates and start the loading of all our textures.
pub fn new() -> Result<TextureManager> {
let rusty = Image::new("static/textures/rusty.png")?;
Ok(TextureManager { rusty })
Ok(TextureManager {
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.
use std::fmt;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// 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