Moved out objects from game module
[kaka/rust-sdl-test.git] / src / core / object / character.rs
CommitLineData
5d7eff9e
TW
1use core::controller::Controller;
2use core::object::boll::Boll;
3use core::level::{Level, Wall, IntersectResult::Intersection};
4use core::object::{Object, Objects, ObjectState};
5use core::render::Renderer;
6use geometry::Point;
7use point;
8use sdl2::rect::Rect;
9use sprites::SpriteManager;
10use std::cell::RefCell;
11use std::rc::Rc;
12use time::Duration;
13
14////////// CHARACTER ///////////////////////////////////////////////////////////
15
16pub struct Character {
17 ctrl: Rc<RefCell<Controller>>,
18 pos: Point<f64>,
19 vel: Point<f64>,
20 standing_on: Option<Wall>,
21}
22
23impl Character {
24 pub fn new(ctrl: Rc<RefCell<Controller>>) -> Self {
25 Character {
26 ctrl,
27 pos: point!(300.0, 300.0),
28 vel: point!(0.0, 0.0),
29 standing_on: None,
30 }
31 }
32}
33
34impl Object for Character {
35 fn update(&mut self, objects: &mut Objects, lvl: &Level, dt: Duration) -> ObjectState {
36 let ctrl = self.ctrl.borrow();
37
38 match &self.standing_on {
39 Some(wall) => {
40 if ctrl.jump.is_pressed && !ctrl.jump.was_pressed {
41 if ctrl.mov.to_point().length() < 0.1 {
42 self.vel = wall.normal().into();
43 } else {
44 self.vel = ctrl.mov.to_point();
45 }
46 self.vel *= 5.0;
47 self.pos += self.vel * 0.1;
48 self.standing_on = None;
49 } else {
50 self.vel *= 0.9;
51 }
52 },
53 None => {
54 self.vel += lvl.gravity;
55 self.pos += self.vel;
56
57 match ctrl.mov.x {
58 v if v < -0.9 && self.vel.x > -5.0 => { self.vel.x -= 0.5 }
59 v if v > 0.9 && self.vel.x < 5.0 => { self.vel.x += 0.5 }
60 _ => {}
61 }
62
63 if let Intersection(wall, pos) = lvl.intersect_walls(self.pos - self.vel, self.pos) {
64 self.standing_on = Some(wall);
65 self.pos = pos;
66 self.vel = point!(0.0, 0.0);
67 }
68 }
69 }
70
71 if ctrl.shoot.is_pressed {
72 use rand::distributions::{Distribution, Normal};
73 let normal = Normal::new(0.0, 0.1);
74 let direction = if ctrl.aim.to_point().length() > 0.1 { ctrl.aim.to_point() } else { ctrl.mov.to_point() };
75 for _i in 0..100 {
76 objects.push(Box::new(Boll::new(
77 self.pos + point!(0.0, -16.0), // half the height of mario
78 direction * (10.0 + rand::random::<f64>()) + point!(normal.sample(&mut rand::thread_rng()), normal.sample(&mut rand::thread_rng())) + self.vel,
79 2,
80 )));
81 }
82 ctrl.rumble(1.0, dt);
83 self.vel -= direction * 0.1;
84 }
85
86 ObjectState::Alive
87 }
88
89 fn render(&self, renderer: &mut Renderer, sprites: &SpriteManager) {
90 let block = sprites.get("mario");
91 let size = 32;
92 renderer.blit(block, None, Rect::new(self.pos.x as i32 - size as i32 / 2, self.pos.y as i32 - size as i32, size, size));
93
94 let ctrl = &self.ctrl.borrow();
95 let l = 300.0;
96 let pos = (self.pos.x as i32, self.pos.y as i32);
97 // // axis values
98 // let p = (self.pos + ctrl.aim.to_axis_point() * l).to_i32().into();
99 // renderer.draw_line(pos, p, (0, 255, 0));
100 // draw_cross(renderer, p);
101 // values limited to unit vector
102 let p = (self.pos + ctrl.aim.to_point() * l).to_i32().into();
103 renderer.draw_line(pos, p, (255, 0, 0));
104 draw_cross(renderer, p);
105 let p = (self.pos + ctrl.mov.to_point() * l).to_i32().into();
106 renderer.draw_line(pos, p, (0, 255, 0));
107 draw_cross(renderer, p);
108 // // circle values
109 // let p = (self.pos + Point::from(ctrl.aim.a) * l).to_i32().into();
110 // renderer.draw_line(pos, p, (0, 0, 255));
111 // draw_cross(renderer, p);
112 }
113}
114
115fn draw_cross(renderer: &mut Renderer, p: (i32, i32)) {
116 renderer.canvas().draw_line((p.0 - 5, p.1), (p.0 + 5, p.1)).unwrap();
117 renderer.canvas().draw_line((p.0, p.1 - 5), (p.0, p.1 + 5)).unwrap();
118}