comparison src/th06/anm0_vm.rs @ 641:a58103f2f264

Implement and use interpolators.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 07 Jul 2019 12:17:42 +0200
parents 37d151fe000b
children 9e40bd5cc26d
comparison
equal deleted inserted replaced
640:37d151fe000b 641:a58103f2f264
7 Instruction, 7 Instruction,
8 }; 8 };
9 use std::cell::RefCell; 9 use std::cell::RefCell;
10 use std::rc::Rc; 10 use std::rc::Rc;
11 11
12 #[derive(Debug, Clone)] 12 #[derive(Debug, Clone, Copy, PartialEq)]
13 struct Interpolator; 13 enum Formula {
14 Linear,
15 Power2,
16 InvertPower2,
17 }
18
19 impl Formula {
20 fn apply(&self, x: f32) -> f32 {
21 match self {
22 Formula::Linear => x,
23 Formula::Power2 => x * x,
24 Formula::InvertPower2 => 2. * x - x * x,
25 }
26 }
27 }
28
29 macro_rules! generate_interpolator {
30 ($name:ident, $n:tt) => {
31 #[derive(Debug, Clone)]
32 struct $name<T> {
33 start_values: [T; $n],
34 end_values: [T; $n],
35 start_frame: u16,
36 end_frame: u16,
37 formula: Formula,
38 }
39
40 impl<T> $name<T>
41 where f32: From<T>,
42 T: From<f32>,
43 T: std::ops::Sub<Output = T>,
44 T: std::ops::Add<Output = T>,
45 T: Copy,
46 T: Default,
47 {
48 pub fn new(start_values: [T; $n], start_frame: u16, end_values: [T; $n], end_frame: u16, formula: Formula) -> $name<T> {
49 $name {
50 start_values,
51 end_values,
52 start_frame,
53 end_frame,
54 formula,
55 }
56 }
57
58 // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here.
59 pub fn values(&self, frame: u16) -> [f32; $n] {
60 if frame + 1 >= self.end_frame {
61 // XXX: skip the last interpolation step.
62 // This bug is replicated from the original game.
63 //self.start_frame = self.end_frame;
64 //self.end_values
65 let mut values: [f32; $n] = [Default::default(); $n];
66 for (i, value) in self.end_values.iter().enumerate() {
67 values[i] = f32::from(*value);
68 }
69 values
70 } else {
71 let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32;
72 coeff = self.formula.apply(coeff);
73 let mut values: [f32; $n] = [Default::default(); $n];
74 for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() {
75 values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start)));
76 }
77 values
78 }
79 }
80 }
81 };
82 }
83
84 generate_interpolator!(Interpolator1, 1);
85 generate_interpolator!(Interpolator2, 2);
86 generate_interpolator!(Interpolator3, 3);
14 87
15 /// Base visual element. 88 /// Base visual element.
16 #[derive(Debug, Clone, Default)] 89 #[derive(Debug, Clone, Default)]
17 pub struct Sprite { 90 pub struct Sprite {
18 blendfunc: u32, 91 blendfunc: u32,
29 automatic_orientation: bool, 102 automatic_orientation: bool,
30 allow_dest_offset: bool, 103 allow_dest_offset: bool,
31 mirrored: bool, 104 mirrored: bool,
32 corner_relative_placement: bool, 105 corner_relative_placement: bool,
33 106
34 scale_interpolator: Option<Interpolator>, 107 scale_interpolator: Option<Interpolator2<f32>>,
35 fade_interpolator: Option<Interpolator>, 108 fade_interpolator: Option<Interpolator1<f32>>, // XXX: should be u8!
36 offset_interpolator: Option<Interpolator>, 109 offset_interpolator: Option<Interpolator3<f32>>,
37 rotation_interpolator: Option<Interpolator>, 110 rotation_interpolator: Option<Interpolator3<f32>>,
38 color_interpolator: Option<Interpolator>, 111 color_interpolator: Option<Interpolator3<f32>>, // XXX: should be u8!
39 112
40 anm: Option<Anm0>, 113 anm: Option<Anm0>,
41 114
42 dest_offset: [f32; 3], 115 dest_offset: [f32; 3],
43 texcoords: [f32; 4], 116 texcoords: [f32; 4],
71 if sax != 0. || say != 0. || saz != 0. { 144 if sax != 0. || say != 0. || saz != 0. {
72 let [ax, ay, az] = self.rotations_3d; 145 let [ax, ay, az] = self.rotations_3d;
73 self.rotations_3d = [ax + sax, ay + say, az + saz]; 146 self.rotations_3d = [ax + sax, ay + say, az + saz];
74 self.changed = true; 147 self.changed = true;
75 } else if let Some(ref interpolator) = self.rotation_interpolator { 148 } else if let Some(ref interpolator) = self.rotation_interpolator {
76 unimplemented!(); 149 self.rotations_3d = interpolator.values(self.frame);
77 self.changed = true; 150 self.changed = true;
78 } 151 }
79 152
80 let [rsx, rsy] = self.scale_speed; 153 let [rsx, rsy] = self.scale_speed;
81 if rsx != 0. || rsy != 0. { 154 if rsx != 0. || rsy != 0. {
83 self.rescale = [rx + rsx, ry + rsy]; 156 self.rescale = [rx + rsx, ry + rsy];
84 self.changed = true; 157 self.changed = true;
85 } 158 }
86 159
87 if let Some(ref interpolator) = self.fade_interpolator { 160 if let Some(ref interpolator) = self.fade_interpolator {
88 unimplemented!(); 161 self.color[3] = interpolator.values(self.frame)[0] as u8;
89 self.changed = true; 162 self.changed = true;
90 } 163 }
91 164
92 if let Some(ref interpolator) = self.scale_interpolator { 165 if let Some(ref interpolator) = self.scale_interpolator {
93 unimplemented!(); 166 self.rescale = interpolator.values(self.frame);
94 self.changed = true; 167 self.changed = true;
95 } 168 }
96 169
97 if let Some(ref interpolator) = self.offset_interpolator { 170 if let Some(ref interpolator) = self.offset_interpolator {
98 unimplemented!(); 171 self.dest_offset = interpolator.values(self.frame);
99 self.changed = true; 172 self.changed = true;
100 } 173 }
101 174
102 if let Some(ref interpolator) = self.color_interpolator { 175 if let Some(ref interpolator) = self.color_interpolator {
103 unimplemented!(); 176 let color = interpolator.values(self.frame);
177 // TODO: this can probably be made to look nicer.
178 self.color[0] = color[0] as u8;
179 self.color[1] = color[1] as u8;
180 self.color[2] = color[2] as u8;
104 self.changed = true; 181 self.changed = true;
105 } 182 }
106 } 183 }
107 } 184 }
108 185
240 } 317 }
241 Instruction::SetScaleSpeed(ssx, ssy) => { 318 Instruction::SetScaleSpeed(ssx, ssy) => {
242 sprite.scale_speed = [ssx, ssy]; 319 sprite.scale_speed = [ssx, ssy];
243 } 320 }
244 Instruction::Fade(new_alpha, duration) => { 321 Instruction::Fade(new_alpha, duration) => {
245 // XXX: implement fade(). 322 sprite.fade_interpolator = Some(Interpolator1::new([sprite.color[3] as f32], sprite.frame, [new_alpha as f32], sprite.frame + duration as u16, Formula::Linear));
246 //sprite.fade(duration, new_alpha)
247 } 323 }
248 Instruction::SetBlendmodeAlphablend() => { 324 Instruction::SetBlendmodeAlphablend() => {
249 sprite.blendfunc = 1; 325 sprite.blendfunc = 1;
250 } 326 }
251 Instruction::SetBlendmodeAdd() => { 327 Instruction::SetBlendmodeAdd() => {
253 } 329 }
254 Instruction::KeepStill() => { 330 Instruction::KeepStill() => {
255 self.running = false; 331 self.running = false;
256 } 332 }
257 Instruction::LoadRandomSprite(min_index, amplitude) => { 333 Instruction::LoadRandomSprite(min_index, amplitude) => {
258 //self.load_sprite(min_index + randrange(amp)) 334 let sprite_index = min_index; // XXX: + randrange(amplitude);
335
336 // TODO: refactor that with Instruction::LoadSprite.
337 sprite.anm = Some(self.anm.clone());
338 let texcoords = &self.anm.sprites[(sprite_index + self.sprite_index_offset) as usize];
339 sprite.texcoords = [texcoords.x, texcoords.y, texcoords.width, texcoords.height];
259 } 340 }
260 Instruction::Move(x, y, z) => { 341 Instruction::Move(x, y, z) => {
261 sprite.dest_offset = [x, y, z]; 342 sprite.dest_offset = [x, y, z];
262 } 343 }
263 Instruction::MoveToLinear(x, y, z, duration) => { 344 Instruction::MoveToLinear(x, y, z, duration) => {
264 // XXX: implement move_in(). 345 sprite.offset_interpolator = Some(Interpolator3::new(sprite.dest_offset, sprite.frame, [x, y, z], sprite.frame + duration as u16, Formula::Linear));
265 //sprite.move_in(duration, x, y, z);
266 } 346 }
267 Instruction::MoveToDecel(x, y, z, duration) => { 347 Instruction::MoveToDecel(x, y, z, duration) => {
268 // XXX: implement move_in(). 348 sprite.offset_interpolator = Some(Interpolator3::new(sprite.dest_offset, sprite.frame, [x, y, z], sprite.frame + duration as u16, Formula::InvertPower2));
269 //sprite.move_in(duration, x, y, z, 2*x - x**2);
270 } 349 }
271 Instruction::MoveToAccel(x, y, z, duration) => { 350 Instruction::MoveToAccel(x, y, z, duration) => {
272 // XXX: implement move_in(). 351 sprite.offset_interpolator = Some(Interpolator3::new(sprite.dest_offset, sprite.frame, [x, y, z], sprite.frame + duration as u16, Formula::Power2));
273 //sprite.move_in(duration, x, y, z, x**2);
274 } 352 }
275 Instruction::Wait() => { 353 Instruction::Wait() => {
276 self.waiting = true; 354 self.waiting = true;
277 } 355 }
278 // There is nothing to do here. 356 // There is nothing to do here.
279 Instruction::InterruptLabel(label) => (), 357 Instruction::InterruptLabel(_label) => (),
280 Instruction::SetCornerRelativePlacement() => { 358 Instruction::SetCornerRelativePlacement() => {
281 sprite.corner_relative_placement = true; 359 sprite.corner_relative_placement = true;
282 } 360 }
283 Instruction::WaitEx() => { 361 Instruction::WaitEx() => {
284 sprite.visible = false; 362 sprite.visible = false;
300 } 378 }
301 Instruction::SetVisible(visible) => { 379 Instruction::SetVisible(visible) => {
302 sprite.visible = (visible & 1) != 0; 380 sprite.visible = (visible & 1) != 0;
303 } 381 }
304 Instruction::ScaleIn(sx, sy, duration) => { 382 Instruction::ScaleIn(sx, sy, duration) => {
305 // TODO: implement scale_in(). 383 sprite.scale_interpolator = Some(Interpolator2::new(sprite.rescale, sprite.frame, [sx, sy], sprite.frame + duration as u16, Formula::Linear));
306 //sprite.scale_in(duration, sx, sy) 384 }
307 } 385 Instruction::Todo(_todo) => {
308 Instruction::Todo(todo) => {
309 // TODO. 386 // TODO.
310 } 387 }
311 } 388 }
312 } 389 }
313 } 390 }