From 856c3740c76feea6a82cc95b5e190b1ccd165621 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Sun, 28 Feb 2021 20:58:13 +0100 Subject: [PATCH] Added a jumping trigger and state --- src/core/object/character.rs | 111 +++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 36 deletions(-) diff --git a/src/core/object/character.rs b/src/core/object/character.rs index 18cb0aa..3d789f2 100644 --- a/src/core/object/character.rs +++ b/src/core/object/character.rs @@ -11,10 +11,16 @@ use std::cell::RefCell; use std::rc::Rc; use time::Duration; +////////// TRIGGER ///////////////////////////////////////////////////////////// + +trait Trigger { + fn update(&mut self, body: &Body, ctrl: &Controller, dt: Duration) -> Option>; +} + ////////// STATE /////////////////////////////////////////////////////////////// trait State { - fn enter(&self) {} + fn enter(&mut self, _body: &mut Body, _ctrl: &Controller, _objects: &mut Objects) {} fn exit(&self) {} fn update(&mut self, body: &mut Body, ctrl: &Controller, objects: &mut Objects, lvl: &Level, dt: Duration) -> Option>; } @@ -22,29 +28,16 @@ trait State { ////////// CHARACTER /////////////////////////////////////////////////////////// struct Body { - pub pos: Point, - pub vel: Point, - pub standing_on: Option, -} - -struct StateHolder(Box); - -impl StateHolder { - pub fn get(&mut self) -> &mut Box { - &mut self.0 - } - - pub fn set(&mut self, state: Box) { - self.0.exit(); - self.0 = state; - self.0.enter(); - } + pos: Point, + vel: Point, + standing_on: Option, } pub struct Character { ctrl: Rc>, body: Body, - state: StateHolder, // Plays well with the borrow checker + triggers: Vec>, + state: Box, } impl Character { @@ -56,7 +49,8 @@ impl Character { vel: point!(0.0, 0.0), standing_on: None, }, - state: StateHolder(Box::new(FallState)), + triggers: vec!(Box::new(JumpTrigger)), + state: Box::new(FallState), } } } @@ -65,8 +59,10 @@ impl Object for Character { fn update(&mut self, objects: &mut Objects, lvl: &Level, dt: Duration) -> ObjectState { let ctrl = self.ctrl.borrow(); - if let Some(state) = self.state.get().update(&mut self.body, &ctrl, objects, lvl, dt) { - self.state.set(state); + if let Some(state) = self.state.update(&mut self.body, &ctrl, objects, lvl, dt) { + self.state.exit(); + self.state = state; + self.state.enter(&mut self.body, &ctrl, objects); } match &self.body.standing_on { @@ -77,11 +73,22 @@ impl Object for Character { self.body.standing_on = Some(wall); self.body.pos = pos; self.body.vel = point!(0.0, 0.0); - self.state.set(Box::new(StandState)); + + self.state.exit(); + self.state = Box::new(StandState); + self.state.enter(&mut self.body, &ctrl, objects); } } } + for trigger in &mut self.triggers { + if let Some(state) = trigger.update(&self.body, &ctrl, dt) { + self.state.exit(); + self.state = state; + self.state.enter(&mut self.body, &ctrl, objects); + } + } + if ctrl.shoot.is_pressed { use rand::distributions::{Distribution, Normal}; let normal = Normal::new(0.0, 0.1); @@ -150,26 +157,58 @@ impl State for FallState { } } -////////// STANDING ///////////////////////////////////////////////////////////// +////////// STANDING //////////////////////////////////////////////////////////// struct StandState; impl State for StandState { - fn update(&mut self, body: &mut Body, ctrl: &Controller, _objects: &mut Objects, _lvl: &Level, _dt: Duration) -> Option> { + fn update(&mut self, body: &mut Body, _ctrl: &Controller, _objects: &mut Objects, _lvl: &Level, _dt: Duration) -> Option> { + if let Some(_wall) = &body.standing_on { + body.vel *= 0.9; + } + + None + } +} + +////////// JUMPING ///////////////////////////////////////////////////////////// + +struct JumpTrigger; + +impl Trigger for JumpTrigger { + fn update(&mut self, body: &Body, ctrl: &Controller, _dt: Duration) -> Option> { + if body.standing_on.is_some() && ctrl.jump.is_pressed && !ctrl.jump.was_pressed { // this is redundant now because JumpState needs a wall to get starting velocity, but that will probably change + Some(Box::new(JumpState)) + } else { + None + } + } +} + +struct JumpState; + +impl State for JumpState { + fn enter(&mut self, body: &mut Body, ctrl: &Controller, _objects: &mut Objects) { if let Some(wall) = &body.standing_on { - if ctrl.jump.is_pressed && !ctrl.jump.was_pressed { - if ctrl.mov.to_point().length() < 0.1 { - body.vel = wall.normal().into(); - } else { - body.vel = ctrl.mov.to_point(); - } - body.vel *= 5.0; - body.pos += body.vel * 0.1; - body.standing_on = None; - return Some(Box::new(FallState)) + if ctrl.mov.to_point().length() < 0.1 { + body.vel = wall.normal().into(); } else { - body.vel *= 0.9; + body.vel = ctrl.mov.to_point(); } + body.vel *= 5.0; + body.pos += body.vel * 0.1; + body.standing_on = None; + } + } + + fn update(&mut self, body: &mut Body, ctrl: &Controller, _objects: &mut Objects, lvl: &Level, _dt: Duration) -> Option> { + body.vel += lvl.gravity; + body.pos += body.vel; + + match ctrl.mov.x { + v if v < -0.9 && body.vel.x > -5.0 => { body.vel.x -= 0.5 } + v if v > 0.9 && body.vel.x < 5.0 => { body.vel.x += 0.5 } + _ => {} } None -- 2.11.0