diff --git a/assets/items/machine_gun.json b/assets/items/machine_gun.json index f80c2672e3..361f31301f 100644 --- a/assets/items/machine_gun.json +++ b/assets/items/machine_gun.json @@ -5,6 +5,7 @@ }, "type": "weapon", "cooldown": 0.15, + "attack_duration": 0.1, "recoil": 125.0, "uses": 24, "mount_offset": { @@ -12,32 +13,48 @@ "y": -4 }, "effect_offset": { - "x": 56, + "x": 64, "y": 4 }, "sound_effect": "shoot", - "effects": { - "type": "projectile", - "range": 128.0, - "speed": 12.0, - "spread": 5.0, - "projectile": { - "type": "sprite", - "sprite": { - "texture": "small_projectile", - "size": { - "x": 8, - "y": 4 + "effects": [ + { + "type": "projectile", + "range": 512.0, + "speed": 8.0, + "spread": 5.0, + "projectile": { + "type": "sprite", + "sprite": { + "texture": "machine_gun_bullet", + "size": { + "x": 30, + "y": 4 + }, + "offset": { + "x": -15, + "y": -2 + } }, - "tint": { - "r": 0.9, - "g": 0.75, - "b": 0.12, - "a": 1.0 - } + "is_rotated": true } + }, + { + "type": "particle_controller", + "id": "0", + "particle_id": "machine_gun_muzzle_smoke", + "start_delay": 0.2, + "is_can_be_interrupted": true, + "amount": 5, + "interval": 0.05 + }, + { + "type": "particle_controller", + "id": "1", + "particle_id": "machine_gun_firing_smoke", + "amount": 1 } - }, + ], "collider_size": { "x": 68, "y": 24 @@ -55,7 +72,7 @@ { "id": "attack", "row": 1, - "frames": 2, + "frames": 1, "fps": 8, "is_looping": true } diff --git a/assets/particle_effects.json b/assets/particle_effects.json index 794dccb839..d56f8a7bdc 100644 --- a/assets/particle_effects.json +++ b/assets/particle_effects.json @@ -30,5 +30,13 @@ { "id": "smoke", "path": "particle_effects/smoke.json" + }, + { + "id": "machine_gun_muzzle_smoke", + "path": "particle_effects/machine_gun_muzzle_smoke.json" + }, + { + "id": "machine_gun_firing_smoke", + "path": "particle_effects/machine_gun_firing_smoke.json" } ] \ No newline at end of file diff --git a/assets/particle_effects/machine_gun_firing_smoke.json b/assets/particle_effects/machine_gun_firing_smoke.json new file mode 100644 index 0000000000..f4dcd3014c --- /dev/null +++ b/assets/particle_effects/machine_gun_firing_smoke.json @@ -0,0 +1,73 @@ +{ + "local_coords": false, + "emission_shape": { + "Sphere": { + "radius": 3 + } + }, + "one_shot": true, + "lifetime": 0.29999995, + "lifetime_randomness": 0, + "explosiveness": 1, + "amount": 1, + "shape": { + "Circle": { + "subdivisions": 16 + } + }, + "emitting": false, + "initial_direction": { + "x": 0, + "y": -1 + }, + "initial_direction_spread": 0.3, + "initial_velocity": 54.300003, + "initial_velocity_randomness": 0.4, + "linear_accel": -0.89999986, + "size": 2, + "size_randomness": 0, + "size_curve": { + "points": [ + [ + 0.005, + 1.36 + ], + [ + 0.49, + 1.84 + ], + [ + 1, + 0 + ] + ], + "interpolation": "Linear", + "resolution": 30 + }, + "blend_mode": "Alpha", + "colors_curve": { + "start": { + "r": 0.6818182, + "g": 0.6818182, + "b": 0.6818182, + "a": 1 + }, + "mid": { + "r": 0.77272725, + "g": 0.77272725, + "b": 0.77272725, + "a": 1 + }, + "end": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + } + }, + "gravity": { + "x": 0, + "y": -54.1 + }, + "post_processing": {} +} \ No newline at end of file diff --git a/assets/particle_effects/machine_gun_muzzle_smoke.json b/assets/particle_effects/machine_gun_muzzle_smoke.json new file mode 100644 index 0000000000..967da77ba0 --- /dev/null +++ b/assets/particle_effects/machine_gun_muzzle_smoke.json @@ -0,0 +1,73 @@ +{ + "local_coords": false, + "emission_shape": { + "Sphere": { + "radius": 3 + } + }, + "one_shot": true, + "lifetime": 0.7999999, + "lifetime_randomness": 0, + "explosiveness": 1, + "amount": 1, + "shape": { + "Circle": { + "subdivisions": 16 + } + }, + "emitting": false, + "initial_direction": { + "x": 0, + "y": -1 + }, + "initial_direction_spread": 0.3, + "initial_velocity": 54.300003, + "initial_velocity_randomness": 0.4, + "linear_accel": -0.89999986, + "size": 2.9, + "size_randomness": 0, + "size_curve": { + "points": [ + [ + 0, + 0.88 + ], + [ + 0.49, + 1.88 + ], + [ + 1, + 0 + ] + ], + "interpolation": "Linear", + "resolution": 30 + }, + "blend_mode": "Alpha", + "colors_curve": { + "start": { + "r": 0.29545453, + "g": 0.29545453, + "b": 0.29545453, + "a": 1 + }, + "mid": { + "r": 0.52272725, + "g": 0.52272725, + "b": 0.52272725, + "a": 1 + }, + "end": { + "r": 0.84090906, + "g": 0.84090906, + "b": 0.84090906, + "a": 1 + } + }, + "gravity": { + "x": 0, + "y": -54.1 + }, + "post_processing": {} +} \ No newline at end of file diff --git a/assets/textures.json b/assets/textures.json index 926db82a03..25839dea62 100644 --- a/assets/textures.json +++ b/assets/textures.json @@ -314,5 +314,9 @@ { "id": "musket_bullet", "path": "textures/items/MusketBullet(15x15).png" + }, + { + "id": "machine_gun_bullet", + "path": "textures/items/MachineGunBullet(7x4).png" } ] \ No newline at end of file diff --git a/assets/textures/items/MachineGunBullet(7x4).png b/assets/textures/items/MachineGunBullet(7x4).png new file mode 100644 index 0000000000..2eca8aaf92 Binary files /dev/null and b/assets/textures/items/MachineGunBullet(7x4).png differ diff --git a/src/components/sprite.rs b/src/components/sprite.rs index 1973eaf49b..8112fa4a78 100644 --- a/src/components/sprite.rs +++ b/src/components/sprite.rs @@ -21,8 +21,12 @@ pub struct SpriteParams { /// The pivot of the sprite, relative to the position provided as an argument to the `Sprite` /// draw method, plus any offset. /// Note that this offset will not be inverted if the sprite is flipped. - #[serde(default, with = "json::vec2_def")] - pub pivot: Vec2, + #[serde( + default, + with = "json::vec2_opt", + skip_serializing_if = "Option::is_none" + )] + pub pivot: Option, /// The size of the drawn sprite. If no size is specified, the texture entry's `sprite_size` /// will be used, if specified, or the raw texture size, if not. #[serde( @@ -49,7 +53,7 @@ impl Default for SpriteParams { texture_id: "".to_string(), index: 0, offset: Vec2::ZERO, - pivot: Vec2::ZERO, + pivot: None, size: None, tint: None, is_deactivated: false, @@ -63,7 +67,7 @@ pub struct Sprite { source_rect: Rect, tint: Color, offset: Vec2, - pivot: Vec2, + pivot: Option, pub is_deactivated: bool, } @@ -139,7 +143,7 @@ impl Sprite { rotation, source: Some(self.source_rect), dest_size: Some(size), - pivot: Some(self.pivot), + pivot: self.pivot, }, ) } diff --git a/src/effects/active/projectiles.rs b/src/effects/active/projectiles.rs index 4a1f19ae81..bb42a0219d 100644 --- a/src/effects/active/projectiles.rs +++ b/src/effects/active/projectiles.rs @@ -1,3 +1,5 @@ +use std::f32::consts::PI; + use macroquad::{ experimental::{ collections::storage, @@ -33,6 +35,10 @@ pub enum ProjectileKind { Sprite { #[serde(rename = "sprite")] params: Option, + #[serde(default)] + /// If yes, the sprite would be rotated by angle between Vec2(1, 0) (most likely will be changed in the future) and velocity vector. + /// This, for example, used for machine gun bullets rotation. + is_rotated: bool, }, } @@ -45,6 +51,7 @@ struct Projectile { velocity: Vec2, range: f32, sprite: Option, + sprite_draw_angle: f32, particle_controller: Option, } @@ -67,12 +74,31 @@ impl Projectiles { range: f32, particle_params: Option, ) { - let sprite = if let ProjectileKind::Sprite { params } = &mut kind { + let mut sprite = None; + + let mut sprite_draw_angle = 0.0; + + if let ProjectileKind::Sprite { params, is_rotated } = &mut kind { let params = params.take().unwrap(); - Some(Sprite::new(params)) - } else { - None - }; + sprite = Some(Sprite::new(params)); + + if *is_rotated { + let mut vec = Vec2::new(0.0, 0.0); + + if velocity.x < 0.0 { + vec.x = 1.0; + } else { + vec.x = -1.0; + } + + sprite_draw_angle = (velocity.y - vec.y).atan2(velocity.x - vec.x); + + // By this, we have correct sprite rotation after flipping sprite by X + if velocity.x < 0.0 { + sprite_draw_angle += PI; + } + } + } let particle_controller = particle_params.map(ParticleController::new); @@ -84,6 +110,7 @@ impl Projectiles { velocity, range, sprite, + sprite_draw_angle, particle_controller, }); } @@ -192,7 +219,12 @@ impl Node for Projectiles { ProjectileKind::Sprite { .. } => { let sprite = projectile.sprite.as_ref().unwrap(); let flip_x = projectile.velocity.x < 0.0; - sprite.draw(projectile.position, 0.0, flip_x, false); + sprite.draw( + projectile.position, + projectile.sprite_draw_angle, + flip_x, + false, + ); } } }