Preparing for massive refactoring

This commit is contained in:
Thomas Forgione 2022-08-01 18:16:45 +02:00
parent c771d1ccea
commit 6a1cc8876f
5 changed files with 62 additions and 376 deletions

View File

@ -3,8 +3,8 @@
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::controls::Controls;
use crate::engine::event::Action;
use crate::engine::math::{clamp, duration_as_f64, duration_as_frame};
use crate::engine::physics;
use crate::engine::scene::Updatable;
@ -74,9 +74,6 @@ pub struct Character {
/// Whether the character is walking or not.
walking: bool,
/// Indicates that the player has released the jump button.
can_jump: bool,
}
impl Character {
@ -90,7 +87,6 @@ impl Character {
jump_counter: 1,
max_jump: 1,
animation_timer: UNIX_EPOCH,
can_jump: true,
walking: false,
}
}
@ -107,7 +103,7 @@ impl Character {
/// Makes the character jump.
pub fn jump(&mut self) {
if self.can_jump && self.jump_counter > 0 {
if self.jump_counter > 0 {
self.jump_counter -= 1;
self.speed.y = physics::JUMP_SPEED.y;
}
@ -152,11 +148,11 @@ impl Character {
}
impl Updatable for Character {
fn update(&mut self, now: SystemTime, duration: Duration, keyboard: &Keyboard) {
fn update(&mut self, now: SystemTime, duration: Duration) {
let mut force = Vector::new(0.0, 0.0);
if let Some(ref controls) = self.controls {
force += controls.direction(keyboard);
// force += controls.direction();
}
if let Some(side) = Side::from_force(force) {
@ -186,7 +182,7 @@ impl Updatable for Character {
}
let limit = match self.controls {
Some(ref controls) if controls.is_running() => physics::MAXIMUM_RUNNING_SPEED,
// Some(ref controls) if controls.is_running() => physics::MAXIMUM_RUNNING_SPEED,
_ => physics::MAXIMUM_WALKING_SPEED,
};
@ -196,21 +192,11 @@ impl Updatable for Character {
self.position += self.speed * duration;
}
fn manage_event(&mut self, event: &Event) {
let action = if let Some(ref controls) = self.controls {
controls.convert(event)
} else {
None
};
/// An action was asked to the character.
fn manage_action(&mut self, action: Action) {
match action {
Some(Action::Jump(true)) => {
Action::Button1 => {
self.jump();
self.can_jump = false;
}
Some(Action::Jump(false)) => {
self.can_jump = true;
}
_ => (),

View File

@ -1,179 +1,4 @@
//! This module helps to deal with controls.
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 {
/// The jump button.
///
/// A bool at true means that the button was pressed,
/// A bool at false means that the button was released.
Jump(bool),
}
pub enum Controls {
/// A keyboard controller.
Keyboard(KeyboardMap),
/// A gamepad controller.
Gamepad(GamepadMap),
}
impl Controls {
/// Returns the default keyboard controls.
pub fn default_keyboard() -> Controls {
Controls::Keyboard(KeyboardMap::default())
}
/// Returns the default gamepad controls from id.
///
/// Returns None if the gamepad corresponding to the id is not connected.
pub fn default_gamepad(gamepad: web_sys::Gamepad) -> Controls {
Controls::Gamepad(GamepadMap::from_gamepad(gamepad))
}
// /// Returns the default gamepad controls from id.
// ///
// /// Returns None if the gamepad corresponding to the id is not connected.
// pub fn all_gamepads() -> Vec<Controls> {
// GamepadMap::all()
// .into_iter()
// .map(|x| Controls::Gamepad(x))
// .collect()
// }
/// Converts an event and depending on the config, returns the corresponding action.
pub fn convert(&self, event: &Event) -> Option<Action> {
match self {
Controls::Keyboard(ref map) => map.convert(event),
Controls::Gamepad(ref map) => map.convert(event),
}
}
/// Returns the direction of the controls.
pub fn direction(&self, keyboard: &Keyboard) -> Vector {
match self {
Controls::Keyboard(ref map) => map.direction(keyboard),
Controls::Gamepad(ref map) => map.direction(),
}
}
/// Returns whether the running key is pressed.
pub fn is_running(&self) -> bool {
false
// match self {
// Controls::Keyboard(ref map) => map.is_running(),
// Controls::Gamepad(ref map) => map.is_running(),
// }
}
}
/// A map between keyboard keys and actions.
#[derive(Copy, Clone)]
pub struct KeyboardMap {
/// The key corresponding to the jump button.
jump_key: Key,
/// The key corresponding to the run button.
run_key: Key,
/// The key corresponding to the left button.
left_key: Key,
/// The key corresponding to the right button.
right_key: Key,
}
impl KeyboardMap {
/// Creates the default keyboard config.
pub fn default() -> KeyboardMap {
KeyboardMap {
jump_key: Key::Space,
run_key: Key::ArrowUp,
left_key: Key::ArrowLeft,
right_key: Key::ArrowRight,
}
}
/// Converts an event and depending on the config, returns the corresponding action.
pub fn convert(&self, event: &Event) -> Option<Action> {
match event {
Event::KeyPressed(code) if *code == self.jump_key => Some(Action::Jump(true)),
Event::KeyReleased(code) if *code == self.jump_key => Some(Action::Jump(false)),
_ => None,
}
}
/// Returns the direction of the keys.
pub fn direction(&self, keyboard: &Keyboard) -> Vector {
let mut ret = Vector::new(0.0, 0.0);
const RIGHT: Vector = Vector { x: 1.0, y: 0.0 };
if keyboard.is_key_pressed(self.right_key) {
ret += RIGHT;
}
if keyboard.is_key_pressed(self.left_key) {
ret -= RIGHT;
}
ret
}
}
/// A map between gamepad buttons and actions.
#[derive(Clone)]
pub struct GamepadMap {
/// Id of the gamepad.
inner: web_sys::Gamepad,
/// Number of the jump button.
jump_button: u32,
/// Number of the run button.
run_button: u32,
// /// Left / Right axis.
// left_right_axis: Axis,
}
impl GamepadMap {
/// Creates a gamepad map from a javascript gamepad.
pub fn from_gamepad(gamepad: web_sys::Gamepad) -> GamepadMap {
GamepadMap {
inner: gamepad,
jump_button: 0,
run_button: 3,
}
}
/// Converts an event and depending on the config, returns the corresponding action.
pub fn convert(&self, event: &Event) -> Option<Action> {
None
// match event {
// Event::JoystickButtonPressed { joystickid, button }
// if *joystickid == self.id && *button == self.jump_button =>
// {
// Some(Action::Jump(true))
// }
// Event::JoystickButtonReleased { joystickid, button }
// if *joystickid == self.id && *button == self.jump_button =>
// {
// Some(Action::Jump(false))
// }
// _ => None,
// }
}
/// Returns the direction of the directionnal buttons of the gamepad.
pub fn direction(&self) -> Vector {
Vector::new(0.0, 0.0)
// Vector2::new(axis_position(self.id, self.left_right_axis) / 100.0, 0.0)
}
// /// Returns whether the run button is held down.
// pub fn is_running(&self) -> bool {
// is_button_pressed(self.id, self.run_button)
// }
}
/// The different types of controls.
pub enum Controls {}

View File

@ -9,146 +9,30 @@ use wasm_bindgen::JsCast;
use crate::Result;
/// The state of the keyboard.
#[derive(Clone)]
pub struct Keyboard {
/// The inner keyboard.
inner: Rc<RefCell<InnerKeyboard>>,
}
impl Keyboard {
/// Checks wether a key is pressed or not.
pub fn is_key_pressed(&self, key: Key) -> bool {
let mut b = self.inner.borrow_mut();
*b.keys.entry(key).or_insert(false)
}
/// Receives and treats an event.
pub fn manage_event(&self, event: Event) {
let mut b = self.inner.borrow_mut();
match event {
Event::KeyPressed(x) => *b.keys.entry(x).or_insert(true) = true,
Event::KeyReleased(x) => *b.keys.entry(x).or_insert(false) = false,
}
b.events.push_back(event);
}
/// Gets an event from the event stack.
pub fn pop(&self) -> Option<Event> {
self.inner.borrow_mut().events.pop_front()
}
}
impl Keyboard {
/// Initializes the keyboard.
pub fn new(document: &web_sys::Document) -> Result<Keyboard> {
let inner = Rc::new(RefCell::new(InnerKeyboard::new()));
let clone = Keyboard {
inner: inner.clone(),
};
let down_cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::KeyboardEvent| {
if let Some(event) = Event::from_js(true, event) {
clone.manage_event(event);
}
});
document.set_onkeydown(Some(down_cb.as_ref().unchecked_ref()));
down_cb.forget();
let clone = Keyboard {
inner: inner.clone(),
};
let up_cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::KeyboardEvent| {
if let Some(event) = Event::from_js(false, event) {
clone.manage_event(event);
}
});
document.set_onkeyup(Some(up_cb.as_ref().unchecked_ref()));
up_cb.forget();
Ok(Keyboard { inner })
}
}
/// The state of the keyboard.
#[derive(Clone)]
pub struct InnerKeyboard {
/// Holds the state of the keys.
keys: HashMap<Key, bool>,
/// The list of events to be processed.
events: VecDeque<Event>,
}
impl InnerKeyboard {
/// Creates a new inner arrowboard.
pub fn new() -> InnerKeyboard {
InnerKeyboard {
keys: HashMap::new(),
events: VecDeque::new(),
}
}
}
/// The different events that can occur.
/// The different actions that a user can do.
#[derive(Copy, Clone)]
pub enum Event {
/// A key was pressed down.
KeyPressed(Key),
pub enum Action {
/// The user asks to go to the left.
GoLeft,
/// A key was released.
KeyReleased(Key),
}
/// The different key we cant to support.
#[derive(Hash, PartialEq, Eq, Copy, Clone)]
pub enum Key {
/// The left arrow key.
ArrowLeft,
/// The right arrow key.
ArrowRight,
/// The up arrow key.
ArrowUp,
/// The bottom arrow key.
ArrowDown,
/// The space key.
Space,
}
impl Key {
/// Tries and converts a javascript key to our key type.
pub fn from_str(string: &str) -> Option<Key> {
match string {
"ArrowLeft" => Some(Key::ArrowLeft),
"ArrowRight" => Some(Key::ArrowRight),
"ArrowUp" => Some(Key::ArrowUp),
"ArrowDown" => Some(Key::ArrowDown),
"Space" => Some(Key::Space),
_ => None,
}
}
}
impl Event {
/// Tries and converts a javacript event to our event type.
pub fn from_js(down: bool, event: web_sys::KeyboardEvent) -> Option<Event> {
let key = Key::from_str(&event.code())?;
let event = if down {
Some(Event::KeyPressed(key))
} else {
Some(Event::KeyReleased(key))
};
event
}
/// The user asks to go to the right.
GoRight,
/// The user asks to go up.
GoUp,
/// The user asks to go down.
GoDown,
/// The user asks to do the main action or validate.
Button1,
/// The user asks to do the secondary action.
Button2,
/// The user asks to do the tertiary action.
Button3,
/// The user asks to do the 4th action or cancel.
Button4,
}

View File

@ -20,8 +20,7 @@ use wasm_bindgen::JsCast;
use crate::engine::bbox::Bbox;
use crate::engine::character::Character;
use crate::engine::controls::{Controls, GamepadMap};
use crate::engine::event::{Key, Keyboard};
use crate::engine::controls::Controls;
use crate::engine::map::Map;
use crate::engine::math::now;
use crate::engine::scene::{Scene, State};
@ -79,7 +78,7 @@ impl Engine {
let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap();
let mut scene = Scene::from_map(map);
let character = Character::with_controls(Controls::default_keyboard());
let character = Character::new();
scene.add(character);
let inner = InnerEngine::new(&document, &performance, scene)?;
@ -159,20 +158,20 @@ impl Engine {
if self.document.has_focus()? {
// Manage events
while let Some(event) = inner.keyboard.pop() {
inner.scene.manage_event(&event);
}
// while let Some(event) = inner.keyboard.pop() {
// inner.scene.manage_action(&action);
// }
let keyboard = inner.keyboard.clone();
if inner.scene.update(now, duration, &keyboard) == State::Finished {
let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap();
let mut scene = Scene::from_map(map);
// let keyboard = inner.keyboard.clone();
// if inner.scene.update(now, duration) == State::Finished {
// let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap();
// let mut scene = Scene::from_map(map);
let character = Character::with_controls(Controls::default_keyboard());
scene.add(character);
// let character = Character::with_controls(Controls::default_keyboard());
// scene.add(character);
inner.scene = scene;
}
// inner.scene = scene;
// }
}
Ok(())
@ -239,12 +238,6 @@ pub struct InnerEngine {
/// The time when the loop is done.
pub after_loop: SystemTime,
/// The keyboard.
pub keyboard: Keyboard,
/// The gamepads.
pub gamepads: Vec<GamepadMap>,
/// The texture manager.
pub textures: TextureManager,
}
@ -259,20 +252,18 @@ impl InnerEngine {
Ok(InnerEngine {
scene,
after_loop: now(&performance),
keyboard: Keyboard::new(document)?,
gamepads: vec![],
textures: TextureManager::new()?,
})
}
/// Adds a gamepad.
pub fn add_gamepad(&mut self, gamepad: &web_sys::GamepadEvent) {
let gamepad = GamepadMap::from_gamepad(gamepad.gamepad().unwrap());
let clone = gamepad.clone();
self.gamepads.push(clone);
// let gamepad = GamepadMap::from_gamepad(gamepad.gamepad().unwrap());
// let clone = gamepad.clone();
// self.gamepads.push(clone);
let controlable = self.scene.controlable_mut().unwrap();
controlable.set_controls(Some(Controls::Gamepad(gamepad)));
// let controlable = self.scene.controlable_mut().unwrap();
// controlable.set_controls(Some(Controls::Gamepad(gamepad)));
}
}

View File

@ -4,7 +4,7 @@ use std::time::{Duration, SystemTime};
use crate::engine::bbox::Bbox;
use crate::engine::character::Character;
use crate::engine::event::{Event, Keyboard};
use crate::engine::event::Action;
use crate::engine::map::Map;
use crate::engine::texture::SPRITE_SIZE;
@ -95,7 +95,7 @@ impl Scene {
}
/// Updates the whole scene.
pub fn update(&mut self, now: SystemTime, duration: Duration, keyboard: &Keyboard) -> State {
pub fn update(&mut self, now: SystemTime, duration: Duration) -> State {
let mut state = State::Running;
for c in &mut self.characters {
@ -107,7 +107,7 @@ impl Scene {
// Compute the offset between position and bbox
let offset = old.position - c.position;
c.update(now, duration, keyboard);
c.update(now, duration);
if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) {
c.position = position - offset;
@ -132,10 +132,10 @@ impl Scene {
state
}
/// Transfers an event to the elements contained in the scene that should receive events.
pub fn manage_event(&mut self, event: &Event) {
/// Transfers an action to the elements contained in the scene that should receive actions.
pub fn manage_action(&mut self, action: Action) {
for c in &mut self.characters {
c.manage_event(event);
c.manage_action(action);
}
}
@ -153,8 +153,8 @@ 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, now: SystemTime, duration: Duration, keyboard: &Keyboard);
fn update(&mut self, now: SystemTime, duration: Duration);
/// Called when an event arrives.
fn manage_event(&mut self, event: &Event);
/// Called when an action arrives.
fn manage_action(&mut self, action: Action);
}