comparison src/th06/anm0_vm.rs @ 741:3555845f8cf4

Make it so we can use more than a single anm0 in an EclRunner.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 07 Jan 2020 00:06:18 +0100
parents 6d4802abe134
children 0a250ddfae79
comparison
equal deleted inserted replaced
740:8d29dac12219 741:3555845f8cf4
212 self.changed = true; 212 self.changed = true;
213 } 213 }
214 } 214 }
215 } 215 }
216 216
217 struct Anms {
218 inner: Rc<RefCell<[Anm0; 2]>>,
219 }
220
221 impl Anms {
222 fn new(anms: Rc<RefCell<[Anm0; 2]>>) -> Anms {
223 Anms {
224 inner: anms,
225 }
226 }
227
228 fn load_sprite(&self, sprite: &mut Sprite, id: u8) {
229 let anms = self.inner.borrow();
230 let mut anm = None;
231 let mut texcoords = None;
232 'anm: for anm0 in anms.iter() {
233 for sp in anm0.sprites.iter() {
234 if sp.index == id as u32 {
235 texcoords = Some(sp);
236 anm = Some(anm0.clone());
237 break 'anm;
238 }
239 }
240 }
241 sprite.anm = anm;
242 if let Some(texcoords) = texcoords {
243 sprite.texcoords = [texcoords.x, texcoords.y, texcoords.width, texcoords.height];
244 }
245 }
246
247 fn get_script(&self, id: u8) -> Script {
248 let anms = self.inner.borrow();
249 for anm0 in anms.iter() {
250 if anm0.scripts.contains_key(&id) {
251 return anm0.scripts[&id].clone();
252 }
253 }
254 unreachable!();
255 }
256 }
257
217 /// Interpreter for `Anm0` instructions to update a `Sprite`. 258 /// Interpreter for `Anm0` instructions to update a `Sprite`.
218 pub struct AnmRunner { 259 pub struct AnmRunner {
219 anm: Anm0, 260 anms: Anms,
220 sprite: Rc<RefCell<Sprite>>, 261 sprite: Rc<RefCell<Sprite>>,
221 prng: Weak<RefCell<Prng>>, 262 prng: Weak<RefCell<Prng>>,
222 running: bool, 263 running: bool,
223 sprite_index_offset: u32, 264 sprite_index_offset: u32,
224 script: Script, 265 script: Script,
229 timeout: Option<u32>, 270 timeout: Option<u32>,
230 } 271 }
231 272
232 impl AnmRunner { 273 impl AnmRunner {
233 /// Create a new `AnmRunner`. 274 /// Create a new `AnmRunner`.
234 pub fn new(anm: &Anm0, script_id: u8, sprite: Rc<RefCell<Sprite>>, prng: Weak<RefCell<Prng>>, sprite_index_offset: u32) -> AnmRunner { 275 pub fn new(anms: Rc<RefCell<[Anm0; 2]>>, script_id: u8, sprite: Rc<RefCell<Sprite>>, prng: Weak<RefCell<Prng>>, sprite_index_offset: u32) -> AnmRunner {
276 let anms = Anms::new(anms);
277 let script = anms.get_script(script_id);
235 let mut runner = AnmRunner { 278 let mut runner = AnmRunner {
236 anm: anm.clone(), 279 anms,
237 sprite: sprite, 280 sprite: sprite,
238 prng, 281 prng,
239 running: true, 282 running: true,
240 waiting: false, 283 waiting: false,
241 284
242 script: anm.scripts[&script_id].clone(), 285 script,
243 frame: 0, 286 frame: 0,
244 timeout: None, 287 timeout: None,
245 instruction_pointer: 0, 288 instruction_pointer: 0,
246 variables: ([0, 0, 0, 0 ], 289 variables: ([0, 0, 0, 0 ],
247 [0., 0., 0., 0.], 290 [0., 0., 0., 0.],
319 Instruction::Delete() => { 362 Instruction::Delete() => {
320 sprite.removed = true; 363 sprite.removed = true;
321 self.running = false; 364 self.running = false;
322 } 365 }
323 Instruction::LoadSprite(sprite_index) => { 366 Instruction::LoadSprite(sprite_index) => {
324 sprite.anm = Some(self.anm.clone()); 367 self.anms.load_sprite(&mut sprite, (sprite_index + self.sprite_index_offset) as u8);
325 let texcoords = &self.anm.sprites[(sprite_index + self.sprite_index_offset) as usize];
326 sprite.texcoords = [texcoords.x, texcoords.y, texcoords.width, texcoords.height];
327 } 368 }
328 Instruction::SetScale(sx, sy) => { 369 Instruction::SetScale(sx, sy) => {
329 sprite.rescale = [sx, sy]; 370 sprite.rescale = [sx, sy];
330 } 371 }
331 Instruction::SetAlpha(alpha) => { 372 Instruction::SetAlpha(alpha) => {
373 let prng = self.prng.upgrade().unwrap(); 414 let prng = self.prng.upgrade().unwrap();
374 let rand = prng.borrow_mut().get_u16(); 415 let rand = prng.borrow_mut().get_u16();
375 amplitude = (rand as u32) % amplitude; 416 amplitude = (rand as u32) % amplitude;
376 } 417 }
377 let sprite_index = min_index + amplitude; 418 let sprite_index = min_index + amplitude;
378 419 self.anms.load_sprite(&mut sprite, (sprite_index + self.sprite_index_offset) as u8);
379 // TODO: refactor that with Instruction::LoadSprite.
380 sprite.anm = Some(self.anm.clone());
381 let texcoords = &self.anm.sprites[(sprite_index + self.sprite_index_offset) as usize];
382 sprite.texcoords = [texcoords.x, texcoords.y, texcoords.width, texcoords.height];
383 } 420 }
384 Instruction::Move(x, y, z) => { 421 Instruction::Move(x, y, z) => {
385 sprite.dest_offset = [x, y, z]; 422 sprite.dest_offset = [x, y, z];
386 } 423 }
387 Instruction::MoveToLinear(x, y, z, duration) => { 424 Instruction::MoveToLinear(x, y, z, duration) => {