use sdl2::controller::{Axis, Button}; use core::controller::ControllerManager; use std::cell::RefCell; use std::rc::Rc; use core::controller::Controller; use common::Point2D; use sdl2::rect::Rect; use common::Nanoseconds; use sdl2::event::Event; use sprites::SpriteManager; use sdl2::render::Canvas; use sdl2::video::Window; use AppState; use point; ////////// GAMESTATE /////////////////////////////////////////////////////////// #[derive(Default)] pub struct GameState { world: World, } impl GameState { pub fn new() -> Self { GameState { world: World::new(), } } } impl AppState for GameState { fn enter(&mut self, ctrl_man: &mut ControllerManager) { if let Some(ctrl) = ctrl_man.controllers.get(&0) { self.world.add(Box::new(Character::new(ctrl.clone()))); } } fn leave(&mut self) {} fn update(&mut self, dt: Nanoseconds) { self.world.update(dt); } fn render(&mut self, canvas: &mut Canvas, sprites: &mut SpriteManager) { self.world.render(canvas, sprites); } fn handle_event(&mut self, _event: Event) {} } ////////// WORLD /////////////////////////////////////////////////////////////// #[derive(Default)] pub struct World { level: Level, objects: Vec>, } impl World { pub fn new() -> Self { World { level: Level { gravity: point!(0.0, 0.1), ground: 600.0, }, ..Default::default() } } pub fn update(&mut self, dt: Nanoseconds) { for o in &mut self.objects { o.update(&self.level, dt); } } pub fn render(&mut self, canvas: &mut Canvas, sprites: &mut SpriteManager) { self.level.render(canvas, sprites); for o in &mut self.objects { o.render(canvas, sprites); } } pub fn add(&mut self, object: Box) { self.objects.push(object); } } ////////// LEVEL /////////////////////////////////////////////////////////////// #[derive(Default)] pub struct Level { gravity: Point2D, ground: f64, // just to have something } impl Level { pub fn render(&mut self, canvas: &mut Canvas, _sprites: &mut SpriteManager) { let w = canvas.viewport().width() as i32; for i in 1..11 { let y = (i * i - 1) as i32 + self.ground as i32; canvas.set_draw_color((255 - i * 20, 255 - i * 20, 0)); canvas.draw_line((0, y), (w, y)).unwrap(); } } } ////////// OBJECT ////////////////////////////////////////////////////////////// pub trait Object { fn update(&mut self, lvl: &Level, dt: Nanoseconds); fn render(&mut self, canvas: &mut Canvas, _sprites: &mut SpriteManager); } pub trait Physical {} pub trait Drawable {} ////////// CHARACTER /////////////////////////////////////////////////////////// pub struct Character { ctrl: Rc>, pos: Point2D, vel: Point2D, } impl Character { pub fn new(ctrl: Rc>) -> Self { Character { ctrl, pos: point!(100.0, 100.0), vel: point!(0.0, 0.0), } } } impl Object for Character { fn update(&mut self, lvl: &Level, _dt: Nanoseconds) { self.vel += lvl.gravity; self.pos += self.vel; let ctrl = &self.ctrl.borrow().ctrl; if self.pos.y >= lvl.ground { self.pos.y = lvl.ground; self.vel.y = 0.0; self.vel.x *= 0.9; if ctrl.button(Button::A) { self.vel.y = -5.0; } } match ctrl.axis(Axis::LeftX) as f64 / 32768.0 { v if v < -0.9 => { self.vel.x -= 0.5 } v if v > 0.9 => { self.vel.x += 0.5 } _ => {} } } fn render(&mut self, canvas: &mut Canvas, sprites: &mut SpriteManager) { let block = sprites.get("mario"); let size = 32; canvas.copy(block, None, Rect::new(self.pos.x as i32, self.pos.y as i32 - size as i32, size, size)).unwrap(); } }