Mercurial > touhou
diff src/th06/enemy.rs @ 686:aefe5b5f481e
ecl_vm: implement the SetBulletAttributes opcodes.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 17 Aug 2019 04:28:24 +0200 |
parents | c8bb28961d31 |
children | ac092b70c39a |
line wrap: on
line diff
--- a/src/th06/enemy.rs +++ b/src/th06/enemy.rs @@ -10,14 +10,14 @@ use std::collections::HashMap; use std::rc::{Rc, Weak}; /// The 2D position of an object in the game. -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, Default, PartialEq)] pub struct Position { pub(crate) x: f32, pub(crate) y: f32, } /// An offset which can be added to a Position. -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, Default, PartialEq)] pub struct Offset { dx: f32, dy: f32, @@ -120,10 +120,10 @@ struct Element { pub(crate) struct DifficultyCoeffs { pub(crate) speed_a: f32, pub(crate) speed_b: f32, - pub(crate) nb_a: u16, - pub(crate) nb_b: u16, - pub(crate) shots_a: u16, - pub(crate) shots_b: u16, + pub(crate) nb_a: i16, + pub(crate) nb_b: i16, + pub(crate) shots_a: i16, + pub(crate) shots_b: i16, } impl Default for DifficultyCoeffs { @@ -139,6 +139,32 @@ impl Default for DifficultyCoeffs { } } +#[derive(Debug, Clone, Default, PartialEq)] +pub(crate) struct BulletAttributes { + pub(crate) anim: i16, + pub(crate) sprite_index_offset: i16, + pub(crate) pos: Position, // Doesn’t have a z field. + pub(crate) launch_angle: f32, + pub(crate) angle: f32, + pub(crate) speed: f32, + pub(crate) speed2: f32, + pub(crate) extended_attributes: (i32, i32, i32, i32, f32, f32, f32, f32), + // unknown: x32, + pub(crate) bullets_per_shot: i16, + pub(crate) number_of_shots: i16, + pub(crate) bullet_type: i16, + // zero: x32, + pub(crate) flags: u32, + pub(crate) ins84_param: i32, +} + +impl BulletAttributes { + /// Fire! + pub fn fire(&mut self) { + println!("PAN!"); + } +} + #[derive(PartialEq)] pub(crate) enum Direction { Left, @@ -198,9 +224,8 @@ pub struct Enemy { // Tuples. pub(crate) difficulty_coeffs: DifficultyCoeffs, - pub(crate) extended_bullet_attributes: Option<(u32, u32, u32, u32, f32, f32, f32, f32)>, - pub(crate) bullet_attributes: Option<(i16, i16, u32, u32, u32, f32, f32, f32, f32, u32)>, - pub(crate) bullet_launch_offset: Offset, + pub(crate) bullet_attributes: BulletAttributes, + pub(crate) bullet_offset: Offset, pub(crate) movement_dependant_sprites: Option<(u8, u8, u8, u8)>, pub(crate) screen_box: Option<(f32, f32, f32, f32)>, @@ -274,6 +299,54 @@ impl Enemy { self.hitbox_half_size = [width / 2., height / 2.]; } + /// Defines the attributes for the next bullet fired, and fire it if delay_attack isn’t set! + pub fn set_bullet_attributes(&mut self, opcode: u16, anim: i16, sprite_index_offset: i16, + bullets_per_shot: i16, number_of_shots: i16, speed: f32, + speed2: f32, launch_angle: f32, angle: f32, flags: u32) { + // Get the coeffs for the current difficulty. + let difficulty = self.get_difficulty() as i16; + let coeff_nb = self.difficulty_coeffs.nb_a + (self.difficulty_coeffs.nb_b - self.difficulty_coeffs.nb_a) * difficulty / 32; + let coeff_shots = self.difficulty_coeffs.shots_a + (self.difficulty_coeffs.shots_b - self.difficulty_coeffs.shots_a) * difficulty / 32; + let coeff_speed = self.difficulty_coeffs.speed_a + (self.difficulty_coeffs.speed_b - self.difficulty_coeffs.speed_a) * difficulty as f32 / 32.; + + let opcode = 67; + let mut bullet = &mut self.bullet_attributes; + + bullet.anim = anim; + bullet.bullet_type = opcode - 67; + bullet.sprite_index_offset = sprite_index_offset; + + bullet.bullets_per_shot = bullets_per_shot + coeff_nb; + if bullet.bullets_per_shot < 1 { + bullet.bullets_per_shot = 1; + } + + bullet.number_of_shots = number_of_shots + coeff_shots; + if bullet.number_of_shots < 1 { + bullet.number_of_shots = 1; + } + + bullet.pos = self.pos + self.bullet_offset; + + bullet.speed = speed + coeff_speed; + if bullet.speed < 0.3 { + bullet.speed = 0.3; + } + + bullet.speed2 = speed2 + coeff_speed / 2.; + if bullet.speed2 < 0.3 { + bullet.speed2 = 0.3; + } + + bullet.launch_angle = launch_angle.atan2(0.); + bullet.angle = angle; + bullet.flags = flags; + + if !self.delay_attack { + bullet.fire(); + } + } + /// Run all interpolators and such, and update internal variables once per /// frame. pub fn update(&mut self) {