comparison src/th06/enemy.rs @ 658:3a9d82a02c88

Add a contructor for enemy, and a new example.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sat, 10 Aug 2019 12:48:01 +0200
parents ff7b6355cdf1
children 31fc0d881105
comparison
equal deleted inserted replaced
657:ff7b6355cdf1 658:3a9d82a02c88
6 use crate::util::prng::Prng; 6 use crate::util::prng::Prng;
7 use std::cell::RefCell; 7 use std::cell::RefCell;
8 use std::collections::HashMap; 8 use std::collections::HashMap;
9 use std::rc::{Rc, Weak}; 9 use std::rc::{Rc, Weak};
10 10
11 #[derive(Debug, Clone, Copy)] 11 /// The 2D position of an object in the game.
12 struct Position { 12 #[derive(Debug, Clone, Copy, Default)]
13 pub struct Position {
13 x: f32, 14 x: f32,
14 y: f32, 15 y: f32,
15 } 16 }
16 17
17 #[derive(Debug, Clone, Copy)] 18 /// An offset which can be added to a Position.
18 struct Offset { 19 #[derive(Debug, Clone, Copy, Default)]
20 pub struct Offset {
19 dx: f32, 21 dx: f32,
20 dy: f32, 22 dy: f32,
21 } 23 }
22 24
23 impl Position { 25 impl Position {
26 /// Create said position.
24 pub fn new(x: f32, y: f32) -> Position { 27 pub fn new(x: f32, y: f32) -> Position {
25 Position { x, y } 28 Position { x, y }
26 } 29 }
27 } 30 }
28 31
29 impl Offset { 32 impl Offset {
33 /// Create said offset.
30 pub fn new(dx: f32, dy: f32) -> Offset { 34 pub fn new(dx: f32, dy: f32) -> Offset {
31 Offset { dx, dy } 35 Offset { dx, dy }
32 } 36 }
33 } 37 }
34 38
46 struct Callback; 50 struct Callback;
47 51
48 #[derive(Debug, Clone)] 52 #[derive(Debug, Clone)]
49 struct Laser; 53 struct Laser;
50 54
51 #[derive(Debug, Clone)] 55 #[derive(Debug, Clone, Default)]
52 struct Process; 56 struct Process;
53 57
54 struct Game { 58 /// God struct of our game.
55 enemies: Vec<Enemy>, 59 pub struct Game {
60 enemies: Vec<Rc<RefCell<Enemy>>>,
61 anmrunners: Vec<Rc<RefCell<AnmRunner>>>,
56 prng: Rc<RefCell<Prng>>, 62 prng: Rc<RefCell<Prng>>,
63 }
64
65 impl Game {
66 /// Create said god struct.
67 pub fn new(prng: Rc<RefCell<Prng>>) -> Game {
68 Game {
69 enemies: Vec::new(),
70 anmrunners: Vec::new(),
71 prng,
72 }
73 }
74
75 /// Run the simulation for a single frame.
76 pub fn run_frame(&mut self) {
77 /*
78 for eclrunner in self.eclrunners {
79 eclrunner.run_frame();
80 }
81 */
82
83 for anmrunner in self.anmrunners.iter() {
84 let mut anmrunner = anmrunner.borrow_mut();
85 anmrunner.run_frame();
86 }
87 }
88
89 /// Returns a list of all sprites currently being displayed on screen.
90 pub fn get_sprites(&self) -> Vec<Rc<RefCell<Sprite>>> {
91 let mut sprites = vec![];
92 for anmrunner in self.anmrunners.iter() {
93 let anmrunner = anmrunner.borrow();
94 let sprite = anmrunner.get_sprite();
95 sprites.push(sprite);
96 }
97 sprites
98 }
57 } 99 }
58 100
59 /// Common to all elements in game. 101 /// Common to all elements in game.
60 struct Element { 102 struct Element {
61 pos: Position, 103 pos: Position,
62 removed: bool, 104 removed: bool,
63 sprite: Weak<RefCell<Sprite>>,
64 anmrunner: AnmRunner, 105 anmrunner: AnmRunner,
65 } 106 }
66 107
67 /// The enemy struct, containing everything pertaining to an enemy. 108 /// The enemy struct, containing everything pertaining to an enemy.
109 #[derive(Default)]
68 pub struct Enemy { 110 pub struct Enemy {
69 // Common to all elements in game. 111 // Common to all elements in game.
70 pos: Position, 112 pos: Position,
71 removed: bool, 113 removed: bool,
72 sprite: Rc<RefCell<Sprite>>, 114 anmrunner: Weak<RefCell<AnmRunner>>,
73 anmrunner: Rc<RefCell<AnmRunner>>,
74 115
75 // Specific to enemy. 116 // Specific to enemy.
76 // Floats. 117 // Floats.
77 z: f32, 118 z: f32,
78 angle: f32, 119 angle: f32,
86 die_score: u32, 127 die_score: u32,
87 frame: u32, 128 frame: u32,
88 life: u32, 129 life: u32,
89 death_flags: u32, 130 death_flags: u32,
90 current_laser_id: u32, 131 current_laser_id: u32,
91 low_life_trigger: u32, 132 low_life_trigger: Option<u32>,
92 timeout: u32, 133 timeout: Option<u32>,
93 remaining_lives: u32, 134 remaining_lives: u32,
94 bullet_launch_interval: u32, 135 bullet_launch_interval: u32,
95 bullet_launch_timer: u32, 136 bullet_launch_timer: u32,
96 death_anim: u32, 137 death_anim: u32,
97 direction: u32, 138 direction: u32,
123 164
124 // Laser. 165 // Laser.
125 laser_by_id: HashMap<u32, Laser>, 166 laser_by_id: HashMap<u32, Laser>,
126 167
127 // Options. 168 // Options.
169 // TODO: actually a 8 element array.
128 options: Vec<Element>, 170 options: Vec<Element>,
129 171
130 // Interpolators. 172 // Interpolators.
131 interpolator: Option<Interpolator2<f32>>, 173 interpolator: Option<Interpolator2<f32>>,
132 speed_interpolator: Option<Interpolator1<f32>>, 174 speed_interpolator: Option<Interpolator1<f32>>,
134 // Misc stuff, do we need them? 176 // Misc stuff, do we need them?
135 anm0: Weak<RefCell<Anm0>>, 177 anm0: Weak<RefCell<Anm0>>,
136 process: Rc<RefCell<Process>>, 178 process: Rc<RefCell<Process>>,
137 game: Weak<RefCell<Game>>, 179 game: Weak<RefCell<Game>>,
138 prng: Weak<RefCell<Prng>>, 180 prng: Weak<RefCell<Prng>>,
139 hitbox_half_size: (f32, f32), 181 hitbox_half_size: [f32; 2],
140 } 182 }
141 183
142 impl Enemy { 184 impl Enemy {
185 /// Create a new enemy.
186 pub fn new(pos: Position, life: i32, bonus_dropped: u32, die_score: u32, anm0: Weak<RefCell<Anm0>>, game: Weak<RefCell<Game>>) -> Enemy {
187 Enemy {
188 pos,
189 anm0,
190 game,
191 visible: true,
192 bonus_dropped,
193 die_score,
194 life: if life < 0 { 1 } else { life as u32 },
195 touchable: true,
196 collidable: true,
197 damageable: true,
198 difficulty_coeffs: (-0.5, 0.5, 0, 0, 0, 0),
199 ..Default::default()
200 }
201 }
202
143 /// Sets the animation to the one indexed by index in the current anm0. 203 /// Sets the animation to the one indexed by index in the current anm0.
144 pub fn set_anim(&mut self, index: u8) { 204 pub fn set_anim(&mut self, index: u8) {
145 self.sprite = Rc::new(RefCell::new(Sprite::new()));
146 let anm0 = self.anm0.upgrade().unwrap(); 205 let anm0 = self.anm0.upgrade().unwrap();
147 let anmrunner = AnmRunner::new(&*anm0.borrow(), index, self.sprite.clone(), self.prng.clone(), 0); 206 let game = self.game.upgrade().unwrap();
148 self.anmrunner = Rc::new(RefCell::new(anmrunner)); 207 let sprite = Rc::new(RefCell::new(Sprite::new()));
149 } 208 let anmrunner = AnmRunner::new(&*anm0.borrow(), index, sprite, self.prng.clone(), 0);
150 } 209 let anmrunner = Rc::new(RefCell::new(anmrunner));
210 self.anmrunner = Rc::downgrade(&anmrunner);
211 (*game.borrow_mut()).anmrunners.push(anmrunner);
212 }
213
214 /// Sets the hitbox around the enemy.
215 pub fn set_hitbox(&mut self, width: f32, height: f32) {
216 self.hitbox_half_size = [width, height];
217 }
218 }
219
220 #[cfg(test)]
221 mod tests {
222 use super::*;
223 use std::io::{self, Read};
224 use std::fs::File;
225
226 #[test]
227 fn enemy() {
228 let file = File::open("EoSD/ST/stg1enm.anm").unwrap();
229 let mut file = io::BufReader::new(file);
230 let mut buf = vec![];
231 file.read_to_end(&mut buf).unwrap();
232 let anm0 = Anm0::from_slice(&buf).unwrap();
233 let anm0 = Rc::new(RefCell::new(anm0));
234 let prng = Rc::new(RefCell::new(Prng::new(0)));
235 let game = Game::new(prng);
236 let game = Rc::new(RefCell::new(game));
237 let mut enemy = Enemy::new(Position::new(0., 0.), 500, 0, 640, Rc::downgrade(&anm0), Rc::downgrade(&game));
238 assert!(enemy.anmrunner.upgrade().is_none());
239 enemy.set_anim(0);
240 assert!(enemy.anmrunner.upgrade().is_some());
241 }
242 }