From 34a29179880c62b65ee8b9c5d5ecb7856273ae89 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Sun, 18 Jul 2021 13:03:42 +0200 Subject: [PATCH 01/10] Cannon: Add assets --- assets/Whale/Cannon(32x32).png | Bin 0 -> 644 bytes assets/Whale/Cannonball(128x128).png | Bin 0 -> 9560 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/Whale/Cannon(32x32).png create mode 100644 assets/Whale/Cannonball(128x128).png diff --git a/assets/Whale/Cannon(32x32).png b/assets/Whale/Cannon(32x32).png new file mode 100644 index 0000000000000000000000000000000000000000..422b5aae6c9155ec17c37c381799a82b572b7b98 GIT binary patch literal 644 zcmV-~0(EX>4Tx04R}tkv&MmKpe$iQ>8^Kf_5n4kfAzR5EXIMDionYs1;guFuC*#nlvOW zE{=k0!NHHks)LKOt`4q(Aou~|=H{g6A|?JWDYS_3;J6>}?mh0_0Yan9G^=YI(DbUA zO2oxXc2x|#B7gz(B7&gIEMrcRlJFc~_we!cF2=LG&;2?2)SSftpGZ8*46{nSK|H-# zH8}4RhgnfpiO-40Ou8WPBi9v|-#8Z>7IPWeK{ zWtH<5XRTagt$XqphI0DKGS_JiBY{OML4pVcHIz_B6){?MQY@rsKknfla{Lmx6mpfo z$gzM5G{}x0{11M2Yvm^=+@w$(=zg*7j}aiS3pDGt{e5iP%@e@?3|#4Lf29G;e3D*o zYtbX1e;c^CZfnXOaJd6So($QP9m!8q$mfCgGy0}1Fn9~}thv3l_Hp_Eq^Yaq4RCM> zj20++-Q(TC&ffk#)9UXB7TR)x5##E900006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_005LpL_t(o!|j!^4Zt7_1bJpikp;5_vv67)u7GI?NZ_JL eC6C9@i literal 0 HcmV?d00001 diff --git a/assets/Whale/Cannonball(128x128).png b/assets/Whale/Cannonball(128x128).png new file mode 100644 index 0000000000000000000000000000000000000000..e762d3a60e2900889db6d7ce0ceb42a2268dbf69 GIT binary patch literal 9560 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 literal 0 HcmV?d00001 From cd8501e7e882af835fc08a45935dd383954369a1 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Sun, 18 Jul 2021 13:49:10 +0200 Subject: [PATCH 02/10] Cannon: Implement Cannon type, with (basic) pickup/drop logic --- assets/levels/lev01.json | 14 +- src/main.rs | 16 ++- src/nodes.rs | 14 +- src/nodes/cannon.rs | 282 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 src/nodes/cannon.rs diff --git a/assets/levels/lev01.json b/assets/levels/lev01.json index d96d0e411e..af81499681 100644 --- a/assets/levels/lev01.json +++ b/assets/levels/lev01.json @@ -329,6 +329,18 @@ "x":210.0, "y":548.0 }, + { + "height":0, + "id":70, + "name":"cannon", + "point":true, + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":700.0, + "y":548.0 + }, { "height":0, "id":68, @@ -409,4 +421,4 @@ "type":"map", "version":"1.6", "width":27 -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 30727bb7eb..6bed87f4f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,6 +41,7 @@ struct Resources { whale: Texture2D, whale_red: Texture2D, grenades: Texture2D, + cannon: Texture2D, curse: Texture2D, flying_curses: Texture2D, gun: Texture2D, @@ -98,6 +99,9 @@ impl Resources { let sproinger = load_texture("assets/Whale/Sproinger(32x32).png").await?; sproinger.set_filter(FilterMode::Nearest); + let cannon = load_texture("assets/Whale/Cannon(32x32).png").await?; + cannon.set_filter(FilterMode::Nearest); + let curse = load_texture("assets/Whale/Curse(32x32).png").await?; curse.set_filter(FilterMode::Nearest); @@ -167,6 +171,7 @@ impl Resources { whale, whale_red, grenades, + cannon, curse, flying_curses, gun, @@ -190,8 +195,8 @@ impl Resources { async fn game(game_type: GameType, map: &str) { use nodes::{ - Bullets, Camera, Crate, Curse, Decoration, FlyingCurses, Fxses, GameState, Grenades, - LevelBackground, Mines, Muscet, Player, ScoreCounter, Shoes, Sproinger, Sword, + Bullets, Camera, Cannon, Crate, Curse, Decoration, FlyingCurses, Fxses, GameState, + Grenades, LevelBackground, Mines, Muscet, Player, ScoreCounter, Shoes, Sproinger, Sword, }; let resources_loading = start_coroutine({ @@ -310,6 +315,13 @@ async fn game(game_type: GameType, map: &str) { scene::add_node(grenade); wat_facing ^= true; } + if object.name == "cannon" { + let mut cannon = + Cannon::new(wat_facing, vec2(object.world_x - 35., object.world_y - 25.)); + cannon.throw(false); + scene::add_node(cannon); + wat_facing ^= true; + } if object.name == "crate" { let mut crate_node = diff --git a/src/nodes.rs b/src/nodes.rs index a87baba5cc..457be2ba31 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -2,6 +2,8 @@ mod armed_grenade; mod armed_mine; mod bullets; mod camera; +mod cannon; +mod crates; mod curse; mod decoration; mod flying_curse; @@ -13,15 +15,16 @@ mod mines; mod muscet; pub mod player; mod score_counter; -mod sword; -mod sproinger; -mod crates; mod shoes; +mod sproinger; +mod sword; pub use armed_grenade::ArmedGrenade; pub use armed_mine::ArmedMine; pub use bullets::Bullets; pub use camera::Camera; +pub use cannon::Cannon; +pub use crates::Crate; pub use curse::Curse; pub use decoration::Decoration; pub use flying_curse::FlyingCurses; @@ -33,7 +36,6 @@ pub use mines::Mines; pub use muscet::Muscet; pub use player::Player; pub use score_counter::ScoreCounter; -pub use sword::Sword; -pub use sproinger::Sproinger; -pub use crates::Crate; pub use shoes::Shoes; +pub use sproinger::Sproinger; +pub use sword::Sword; diff --git a/src/nodes/cannon.rs b/src/nodes/cannon.rs new file mode 100644 index 0000000000..11c84d73d9 --- /dev/null +++ b/src/nodes/cannon.rs @@ -0,0 +1,282 @@ +use macroquad::{ + color, + prelude::{ + animation::{AnimatedSprite, Animation}, + collections::storage, + coroutines::{start_coroutine, wait_seconds, Coroutine}, + draw_circle, draw_circle_lines, draw_texture_ex, + scene::{self, Handle, HandleUntyped, RefMut}, + vec2, Color, DrawTextureParams, Rect, Vec2, + }, +}; + +use crate::Resources; + +use super::{ + player::{capabilities, PhysicsBody, Weapon, PLAYER_HITBOX_HEIGHT, PLAYER_HITBOX_WIDTH}, + Player, +}; + +const INITIAL_CANNONBALLS: i32 = 3; +const MAXIMUM_CANNONBALLS: i32 = 3; + +const CANNON_WIDTH: f32 = 32.; +const CANNON_HEIGHT: f32 = 32.; +const CANNON_ANIMATION_BASE: &'static str = "base"; + +pub struct Cannon { + cannon_sprite: AnimatedSprite, + + pub thrown: bool, + + pub amount: i32, + pub body: PhysicsBody, + + origin_pos: Vec2, + deadly_dangerous: bool, +} + +impl Cannon { + pub fn new(facing: bool, pos: Vec2) -> Self { + let cannon_sprite = AnimatedSprite::new( + CANNON_WIDTH as u32, + CANNON_HEIGHT as u32, + &[Animation { + name: CANNON_ANIMATION_BASE.to_string(), + row: 0, + frames: 1, + fps: 1, + }], + false, + ); + + Self { + cannon_sprite, + body: PhysicsBody { + pos, + facing, + angle: 0.0, + speed: vec2(0., 0.), + collider: None, + on_ground: false, + last_frame_on_ground: false, + have_gravity: true, + bouncyness: 0.0, + }, + thrown: false, + amount: INITIAL_CANNONBALLS, + origin_pos: pos, + deadly_dangerous: false, + } + } + + fn draw_hud(&self) { + let full_color = Color::new(0.8, 0.9, 1.0, 1.0); + let empty_color = Color::new(0.8, 0.9, 1.0, 0.8); + for i in 0..MAXIMUM_CANNONBALLS { + let x = self.body.pos.x + 15.0 * i as f32; + + if i >= self.amount { + draw_circle_lines(x, self.body.pos.y - 12.0, 4.0, 2., empty_color); + } else { + draw_circle(x, self.body.pos.y - 12.0, 4.0, full_color); + }; + } + } + + pub fn throw(&mut self, force: bool) { + self.thrown = true; + + if force { + self.body.speed = if self.body.facing { + vec2(600., -200.) + } else { + vec2(-600., -200.) + }; + } else { + self.body.angle = 3.5; + } + + let mut resources = storage::get_mut::(); + + let cannon_mount_pos = if self.body.facing { + vec2(30., 10.) + } else { + vec2(-50., 10.) + }; + + if self.body.collider.is_none() { + self.body.collider = Some(resources.collision_world.add_actor( + self.body.pos + cannon_mount_pos, + 40, + 30, + )); + } else { + resources.collision_world.set_actor_position( + self.body.collider.unwrap(), + self.body.pos + cannon_mount_pos, + ); + } + self.origin_pos = self.body.pos + cannon_mount_pos / 2.; + } + + pub fn shoot(node_h: Handle, player: Handle) -> Coroutine { + let coroutine = async move { + { + let node = scene::get_node(node_h); + + if node.amount <= 0 { + let player = &mut *scene::get_node(player); + player.state_machine.set_state(Player::ST_NORMAL); + + return; + } + + println!("TODO: Cannon::shoot()"); + // let mut cannonball = + // scene::find_node_by_type::().unwrap(); + // cannonball.spawn_cannonball(node.body.pos, node.body.facing); + } + + wait_seconds(0.08).await; + + { + let mut node = scene::get_node(node_h); + + node.amount -= 1; + + let player = &mut *scene::get_node(player); + player.state_machine.set_state(Player::ST_NORMAL); + } + }; + + start_coroutine(coroutine) + } + + pub fn gun_capabilities() -> capabilities::Gun { + fn throw(node: HandleUntyped, force: bool) { + let mut node = scene::get_untyped_node(node).unwrap().to_typed::(); + + Cannon::throw(&mut *node, force); + } + + fn shoot(node: HandleUntyped, player: Handle) -> Coroutine { + let node = scene::get_untyped_node(node) + .unwrap() + .to_typed::() + .handle(); + + Cannon::shoot(node, player) + } + + fn is_thrown(node: HandleUntyped) -> bool { + let node = scene::get_untyped_node(node).unwrap().to_typed::(); + + node.thrown + } + + fn pick_up(node: HandleUntyped) { + let mut node = scene::get_untyped_node(node).unwrap().to_typed::(); + + node.body.angle = 0.; + node.amount = INITIAL_CANNONBALLS; + + node.thrown = false; + } + + capabilities::Gun { + throw, + shoot, + is_thrown, + pick_up, + } + } +} + +impl scene::Node for Cannon { + fn ready(mut node: RefMut) { + node.provides::(( + node.handle().untyped(), + node.handle().lens(|node| &mut node.body), + Self::gun_capabilities(), + )); + } + + fn fixed_update(mut node: RefMut) { + node.cannon_sprite.update(); + + if node.thrown { + node.body.update(); + node.body.update_throw(); + + if (node.origin_pos - node.body.pos).length() > 70. { + node.deadly_dangerous = true; + } + if node.body.speed.length() <= 200.0 { + node.deadly_dangerous = false; + } + if node.body.on_ground { + node.deadly_dangerous = false; + } + + if node.deadly_dangerous { + let others = scene::find_nodes_by_type::(); + let cannon_hit_box = Rect::new( + node.body.pos.x, + node.body.pos.y, + CANNON_WIDTH, + CANNON_HEIGHT, + ); + + for mut other in others { + if Rect::new( + other.body.pos.x, + other.body.pos.y, + PLAYER_HITBOX_WIDTH, + PLAYER_HITBOX_HEIGHT, + ) + .overlaps(&cannon_hit_box) + { + other.kill(!node.body.facing); + } + } + } + } + } + + fn draw(node: RefMut) { + let resources = storage::get_mut::(); + + let cannon_mount_pos = if node.thrown == false { + if node.body.facing { + vec2(0., 16.) + } else { + vec2(-5., 16.) + } + } else { + if node.body.facing { + vec2(-25., 0.) + } else { + vec2(5., 0.) + } + }; + + draw_texture_ex( + resources.cannon, + node.body.pos.x + cannon_mount_pos.x, + node.body.pos.y + cannon_mount_pos.y, + color::WHITE, + DrawTextureParams { + source: Some(node.cannon_sprite.frame().source_rect), + dest_size: Some(node.cannon_sprite.frame().dest_size), + flip_x: !node.body.facing, + rotation: node.body.angle, + ..Default::default() + }, + ); + + if node.thrown == false { + node.draw_hud(); + } + } +} From f8b143a194c2109380c738f14e70d1bed6cbb007 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Sun, 18 Jul 2021 20:27:01 +0200 Subject: [PATCH 03/10] Cannon: Implement Cannonball type, with remaining logic --- assets/Whale/Cannonball(128x128).png | Bin 9560 -> 0 bytes assets/Whale/Cannonball(32x32).png | Bin 0 -> 1898 bytes src/main.rs | 11 +- src/nodes.rs | 2 + src/nodes/cannon.rs | 12 +- src/nodes/cannonball.rs | 188 +++++++++++++++++++++++++++ 6 files changed, 207 insertions(+), 6 deletions(-) delete mode 100644 assets/Whale/Cannonball(128x128).png create mode 100644 assets/Whale/Cannonball(32x32).png create mode 100644 src/nodes/cannonball.rs diff --git a/assets/Whale/Cannonball(128x128).png b/assets/Whale/Cannonball(128x128).png deleted file mode 100644 index e762d3a60e2900889db6d7ce0ceb42a2268dbf69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9560 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 diff --git a/assets/Whale/Cannonball(32x32).png b/assets/Whale/Cannonball(32x32).png new file mode 100644 index 0000000000000000000000000000000000000000..92245e8cdad00bde8d87b26fcb5fc6def0178894 GIT binary patch literal 1898 zcmV-w2bK7VP)EX>4Tx04R}tkv&MmKp2MKrj?3R9NIy|AwzYtAS%*Pt5Adrp;lzBx-kgEzt zj(KcAgY5dj|KN9TtJui;)F#?2lfmXwDzK`4Klwf1*LK+8=QUoCs4Gm-r zC}JR~p~x?!D(g0jR2pQ&kgZ7q2fOIT-sbpap0K zYJr&Rl?7l97zf5uN$aWC?_`J<1NFdS1Zz<~s|3zOur6%FUktPX4M3g9;9wJ&2WEh~ zz(gu(Z3L+(ar9$ABXAhlr^qk|JQMy2U^11o2$;WExSNE(8Yog;nFD5lDd2jxzH340jJW84%|% z(2;Fe7U#btGcO1X0^K?CCxG^V_-_H9rIOZj_k%ZljQ^{wH$fu}e4k!heB^%ccdWAL zr#CtMm+g`zvc?64I-oqdzw(##+F~}!{}DJBApeJX@P8Q~e>HG4y1(*TdTsF^^}!ww z@}DJ13j_Bgv~R)9y;Lkk2oqn(tlkL;c{dFHL>BK|3W>iSxa!`u?Qy--5n$N$!b#!q zLZ4*NVWLac_3hT&_7M5og=4#%qbo%IR>|wO<^YmyKQ18Q$|W&5=*~`MxA9N|{|fM) zJ3E(b`(XhIS1!xoA@}Y?b{l^bkZ|Ur|3j&ywd{@n0~(Z%a18iF03G}XWLvi-I%qIH z!r?W`&ucKgqyN5FB7k^bT9W}BFN`{~P-fqc-&)@$S{#w-mYE20sh#BDD=Q=3SjcOlRbRp(- z4xk+duai{=EHc1fWH@uV)Sy9PameLSfPtH7l4|8>p$8^Y;eQe@J}KlaiAKZ@TRYSTk;@n26+rUBW3!$))_8DxyrdhZG40(LstBHR@xZD^L z*>v#tySIVPENs^xK)Y9^uG~-eYT)nms??SGgdPq2JzkZ%B2%ZP++%r*1BeheunQ=| z!tf3ix|gxb!@~^y+g0c$unQ=|!maI=T9Ga6rJ&I>0x0MJu7p5*1^;p|buIi9yDU5m z{_Y*#IRbnXlH#YaD|2^xuRA3D15lBHQ!iNZbpR3YY`~s42%OF4)K5y6j|V&xhqL6b zC!DIFJHTD%MiZ+d@aBKdvA().unwrap(); - // cannonball.spawn_cannonball(node.body.pos, node.body.facing); + let mut cannonballs = + scene::find_node_by_type::().unwrap(); + let cannonball_pos = vec2( + node.body.pos.x, + node.body.pos.y - 20. - (CANNONBALL_HEIGHT as f32 / 2.), + ); + cannonballs.spawn_cannonball(cannonball_pos, node.body.facing, player); } wait_seconds(0.08).await; diff --git a/src/nodes/cannonball.rs b/src/nodes/cannonball.rs new file mode 100644 index 0000000000..4f5c532c4d --- /dev/null +++ b/src/nodes/cannonball.rs @@ -0,0 +1,188 @@ +use macroquad::{ + color, + experimental::{ + animation::{AnimatedSprite, Animation}, + collections::storage, + scene::RefMut, + }, + prelude::{scene::Handle, *}, +}; + +use crate::{nodes::player::PhysicsBody, Resources}; + +use super::{ + player::{PLAYER_HITBOX_HEIGHT, PLAYER_HITBOX_WIDTH}, + Player, +}; + +const CANNONBALL_COUNTDOWN_DURATION: f32 = 0.5; + +const CANNONBALL_WIDTH: f32 = 32.; +pub const CANNONBALL_HEIGHT: f32 = 32.; +const CANNONBALL_ANIMATION_ROLLING: &'static str = "rolling"; +const CANNONBALL_INITIAL_SPEED_X_REL: f32 = 600.; +const CANNONBALL_INITIAL_SPEED_Y: f32 = -200.; +const CANNONBALL_MOUNT_X_REL: f32 = 20.; +const CANNONBALL_MOUNT_Y: f32 = 40.; + +const EXPLOSION_HITBOX_WIDTH: f32 = 4. * CANNONBALL_WIDTH; +const EXPLOSION_HITBOX_HEIGHT: f32 = 4. * CANNONBALL_HEIGHT; + +pub struct Cannonball { + cannonball_sprite: AnimatedSprite, + body: PhysicsBody, + lived: f32, + countdown: f32, + owner: Handle, +} + +impl Cannonball { + pub fn new(pos: Vec2, facing: bool, owner: Handle) -> Self { + // This can be easily turned into a single sprite, rotated via DrawTextureParams. + // + let cannonball_sprite = AnimatedSprite::new( + CANNONBALL_WIDTH as u32, + CANNONBALL_HEIGHT as u32, + &[Animation { + name: CANNONBALL_ANIMATION_ROLLING.to_string(), + row: 0, + frames: 4, + fps: 12, + }], + true, + ); + + let speed = if facing { + vec2(CANNONBALL_INITIAL_SPEED_X_REL, CANNONBALL_INITIAL_SPEED_Y) + } else { + vec2(-CANNONBALL_INITIAL_SPEED_X_REL, CANNONBALL_INITIAL_SPEED_Y) + }; + + let mut body = PhysicsBody { + pos, + facing, + angle: 0.0, + speed, + collider: None, + on_ground: false, + last_frame_on_ground: false, + have_gravity: true, + bouncyness: 1.0, + }; + + let mut resources = storage::get_mut::(); + + let cannonball_mount_pos = if facing { + vec2(CANNONBALL_MOUNT_X_REL, CANNONBALL_MOUNT_Y) + } else { + vec2(-CANNONBALL_MOUNT_X_REL, CANNONBALL_MOUNT_Y) + }; + + body.collider = Some(resources.collision_world.add_actor( + body.pos + cannonball_mount_pos, + CANNONBALL_WIDTH as i32, + CANNONBALL_HEIGHT as i32, + )); + + Self { + cannonball_sprite, + body, + lived: 0.0, + countdown: CANNONBALL_COUNTDOWN_DURATION, + owner, + } + } +} + +pub struct Cannonballs { + cannonballs: Vec, +} + +impl Cannonballs { + pub fn new() -> Self { + Cannonballs { + cannonballs: vec![], + } + } + + pub fn spawn_cannonball(&mut self, pos: Vec2, facing: bool, owner: Handle) { + self.cannonballs.push(Cannonball::new(pos, facing, owner)); + } +} + +impl scene::Node for Cannonballs { + fn fixed_update(mut node: RefMut) { + for cannonball in &mut node.cannonballs { + cannonball.body.update(); + cannonball.lived += get_frame_time(); + } + + node.cannonballs.retain(|cannonball| { + let hit_fxses = &mut storage::get_mut::().hit_fxses; + let explosion_position = + cannonball.body.pos + vec2(CANNONBALL_WIDTH / 2., CANNONBALL_HEIGHT / 2.); + + if cannonball.lived < cannonball.countdown { + let cannonball_owner_id = scene::get_node(cannonball.owner).id; + + let cannonball_hitbox = Rect::new( + cannonball.body.pos.x + (CANNONBALL_WIDTH - EXPLOSION_HITBOX_WIDTH) / 2., + cannonball.body.pos.y + (CANNONBALL_HEIGHT - EXPLOSION_HITBOX_HEIGHT) / 2., + EXPLOSION_HITBOX_WIDTH, + EXPLOSION_HITBOX_HEIGHT, + ); + + for mut player in scene::find_nodes_by_type::() { + if player.id != cannonball_owner_id { + let player_hitbox = Rect::new( + player.body.pos.x, + player.body.pos.y, + PLAYER_HITBOX_WIDTH, + PLAYER_HITBOX_HEIGHT, + ); + if player_hitbox.intersect(cannonball_hitbox).is_some() { + hit_fxses.spawn(explosion_position); + + scene::find_node_by_type::() + .unwrap() + .shake(); + + let direction = cannonball.body.pos.x + > (player.body.pos.x + PLAYER_HITBOX_WIDTH / 2.); + player.kill(direction); + + return false; + } + } + } + + return true; + } + + hit_fxses.spawn(explosion_position); + + false + }); + } + + fn draw(mut node: RefMut) { + let resources = storage::get_mut::(); + for cannonball in &mut node.cannonballs { + cannonball.cannonball_sprite.update(); + + draw_texture_ex( + resources.cannonballs, + cannonball.body.pos.x, + cannonball.body.pos.y, + color::WHITE, + DrawTextureParams { + source: Some(cannonball.cannonball_sprite.frame().source_rect), + dest_size: Some(cannonball.cannonball_sprite.frame().dest_size), + flip_x: cannonball.body.facing, + rotation: 0.0, + ..Default::default() + }, + ); + } + } +} From 4d6d541c2ec87011aa7d9100a7849a8b852d0678 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Sun, 18 Jul 2021 23:55:48 +0200 Subject: [PATCH 04/10] Cannon: Implement shooting grace time --- src/nodes/cannon.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/nodes/cannon.rs b/src/nodes/cannon.rs index a97d16d3ea..3fdc99c44e 100644 --- a/src/nodes/cannon.rs +++ b/src/nodes/cannon.rs @@ -4,7 +4,7 @@ use macroquad::{ animation::{AnimatedSprite, Animation}, collections::storage, coroutines::{start_coroutine, wait_seconds, Coroutine}, - draw_circle, draw_circle_lines, draw_texture_ex, + draw_circle, draw_circle_lines, draw_texture_ex, get_frame_time, scene::{self, Handle, HandleUntyped, RefMut}, vec2, Color, DrawTextureParams, Rect, Vec2, }, @@ -25,6 +25,8 @@ const CANNON_WIDTH: f32 = 32.; const CANNON_HEIGHT: f32 = 32.; const CANNON_ANIMATION_BASE: &'static str = "base"; +const SHOOTING_GRACE_TIME: f32 = 1.0; // seconds + pub struct Cannon { cannon_sprite: AnimatedSprite, @@ -35,6 +37,8 @@ pub struct Cannon { origin_pos: Vec2, deadly_dangerous: bool, + + grace_time: f32, } impl Cannon { @@ -68,6 +72,7 @@ impl Cannon { amount: INITIAL_CANNONBALLS, origin_pos: pos, deadly_dangerous: false, + grace_time: 0., } } @@ -124,13 +129,17 @@ impl Cannon { pub fn shoot(node_h: Handle, player: Handle) -> Coroutine { let coroutine = async move { { - let node = scene::get_node(node_h); + let mut node = scene::get_node(node_h); - if node.amount <= 0 { + if node.amount <= 0 || node.grace_time > 0. { let player = &mut *scene::get_node(player); player.state_machine.set_state(Player::ST_NORMAL); + node.grace_time -= get_frame_time(); + return; + } else { + node.grace_time = SHOOTING_GRACE_TIME; } let mut cannonballs = @@ -246,6 +255,8 @@ impl scene::Node for Cannon { } } } + + node.grace_time -= get_frame_time(); } fn draw(node: RefMut) { From 0042a48303bfdf690096884a4ad1ccec5f971ade Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Tue, 20 Jul 2021 20:04:00 +0200 Subject: [PATCH 05/10] Cannon: Add throwback --- src/nodes/cannon.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nodes/cannon.rs b/src/nodes/cannon.rs index 3fdc99c44e..dba0a3035b 100644 --- a/src/nodes/cannon.rs +++ b/src/nodes/cannon.rs @@ -25,6 +25,7 @@ const CANNON_WIDTH: f32 = 32.; const CANNON_HEIGHT: f32 = 32.; const CANNON_ANIMATION_BASE: &'static str = "base"; +const CANNON_THROWBACK: f32 = 1050.0; const SHOOTING_GRACE_TIME: f32 = 1.0; // seconds pub struct Cannon { @@ -149,6 +150,9 @@ impl Cannon { node.body.pos.y - 20. - (CANNONBALL_HEIGHT as f32 / 2.), ); cannonballs.spawn_cannonball(cannonball_pos, node.body.facing, player); + + let player = &mut *scene::get_node(player); + player.body.speed.x = -CANNON_THROWBACK * player.body.facing_dir(); } wait_seconds(0.08).await; From f3ef465e70d1ad832166e54ef6877fe760d36428 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Tue, 20 Jul 2021 20:06:00 +0200 Subject: [PATCH 06/10] Cannon: Allow self-pwning --- src/nodes/cannonball.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/nodes/cannonball.rs b/src/nodes/cannonball.rs index 4f5c532c4d..ec6c28ab05 100644 --- a/src/nodes/cannonball.rs +++ b/src/nodes/cannonball.rs @@ -16,6 +16,11 @@ use super::{ }; const CANNONBALL_COUNTDOWN_DURATION: f32 = 0.5; +/// After shooting, the owner is safe for this amount of time. This is crucial, otherwise, given the +/// large hitbox, they will die immediately on shoot. +/// The formula is simplified (it doesn't include mount position, run speed and throwback). +const CANNONBALL_OWNER_SAFE_TIME: f32 = + (EXPLOSION_HITBOX_WIDTH / 2.) / CANNONBALL_INITIAL_SPEED_X_REL; const CANNONBALL_WIDTH: f32 = 32.; pub const CANNONBALL_HEIGHT: f32 = 32.; @@ -34,6 +39,7 @@ pub struct Cannonball { lived: f32, countdown: f32, owner: Handle, + owner_safe_countdown: f32, } impl Cannonball { @@ -90,6 +96,7 @@ impl Cannonball { lived: 0.0, countdown: CANNONBALL_COUNTDOWN_DURATION, owner, + owner_safe_countdown: CANNONBALL_OWNER_SAFE_TIME, } } } @@ -115,6 +122,7 @@ impl scene::Node for Cannonballs { for cannonball in &mut node.cannonballs { cannonball.body.update(); cannonball.lived += get_frame_time(); + cannonball.owner_safe_countdown -= get_frame_time(); } node.cannonballs.retain(|cannonball| { @@ -133,7 +141,7 @@ impl scene::Node for Cannonballs { ); for mut player in scene::find_nodes_by_type::() { - if player.id != cannonball_owner_id { + if player.id != cannonball_owner_id || cannonball.owner_safe_countdown < 0. { let player_hitbox = Rect::new( player.body.pos.x, player.body.pos.y, From 7a231e571cb9774841787d5bf73e73c6f96bed25 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Fri, 23 Jul 2021 15:44:50 +0200 Subject: [PATCH 07/10] Cannon: Update cannonball asset --- assets/Whale/Cannonball(32x32).png | Bin 1898 -> 0 bytes assets/Whale/Cannonball(32x36).png | Bin 0 -> 9677 bytes src/main.rs | 2 +- src/nodes/cannonball.rs | 6 +++--- 4 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 assets/Whale/Cannonball(32x32).png create mode 100644 assets/Whale/Cannonball(32x36).png diff --git a/assets/Whale/Cannonball(32x32).png b/assets/Whale/Cannonball(32x32).png deleted file mode 100644 index 92245e8cdad00bde8d87b26fcb5fc6def0178894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1898 zcmV-w2bK7VP)EX>4Tx04R}tkv&MmKp2MKrj?3R9NIy|AwzYtAS%*Pt5Adrp;lzBx-kgEzt zj(KcAgY5dj|KN9TtJui;)F#?2lfmXwDzK`4Klwf1*LK+8=QUoCs4Gm-r zC}JR~p~x?!D(g0jR2pQ&kgZ7q2fOIT-sbpap0K zYJr&Rl?7l97zf5uN$aWC?_`J<1NFdS1Zz<~s|3zOur6%FUktPX4M3g9;9wJ&2WEh~ zz(gu(Z3L+(ar9$ABXAhlr^qk|JQMy2U^11o2$;WExSNE(8Yog;nFD5lDd2jxzH340jJW84%|% z(2;Fe7U#btGcO1X0^K?CCxG^V_-_H9rIOZj_k%ZljQ^{wH$fu}e4k!heB^%ccdWAL zr#CtMm+g`zvc?64I-oqdzw(##+F~}!{}DJBApeJX@P8Q~e>HG4y1(*TdTsF^^}!ww z@}DJ13j_Bgv~R)9y;Lkk2oqn(tlkL;c{dFHL>BK|3W>iSxa!`u?Qy--5n$N$!b#!q zLZ4*NVWLac_3hT&_7M5og=4#%qbo%IR>|wO<^YmyKQ18Q$|W&5=*~`MxA9N|{|fM) zJ3E(b`(XhIS1!xoA@}Y?b{l^bkZ|Ur|3j&ywd{@n0~(Z%a18iF03G}XWLvi-I%qIH z!r?W`&ucKgqyN5FB7k^bT9W}BFN`{~P-fqc-&)@$S{#w-mYE20sh#BDD=Q=3SjcOlRbRp(- z4xk+duai{=EHc1fWH@uV)Sy9PameLSfPtH7l4|8>p$8^Y;eQe@J}KlaiAKZ@TRYSTk;@n26+rUBW3!$))_8DxyrdhZG40(LstBHR@xZD^L z*>v#tySIVPENs^xK)Y9^uG~-eYT)nms??SGgdPq2JzkZ%B2%ZP++%r*1BeheunQ=| z!tf3ix|gxb!@~^y+g0c$unQ=|!maI=T9Ga6rJ&I>0x0MJu7p5*1^;p|buIi9yDU5m z{_Y*#IRbnXlH#YaD|2^xuRA3D15lBHQ!iNZbpR3YY`~s42%OF4)K5y6j|V&xhqL6b zC!DIFJHTD%MiZ+d@aBKdvA zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3=CkzBj7rT@crmAFyxeg_xq{lC5u1pRZN^H})b z2L{FOiJxO|<~~(FBVj>)n%>u=wLdPN)$(uE)%Z=1)dh^R+s6_0MA2W4Is7{4M-T z{9Nwe#@}kYorHYZX$OC&Yt9puV_bC0b$8spkJC+t82$EzNAD+r(sMNw-~0@UQ`BE~ zdGkso33)_<#?-iT+H#2zy3A<>Bax%uQ_LGiJYx(oyZHu z<(1bALy^<}yo-Ri^NCx!3;gx>6Mp+c{*bCfFx_RYOt9PWE-{k(o?GF@Iq<&3<0~O& z%KBV@CF0(R!MH#KY$p3%cD8t5oMRm;0qTt0hv)|pa4Gr4AbkuWdsBS%x;LLG?!MP2 zpS_+2n+QY-ncAvEs1vLh6ZunOC5L(nDW;TiDyf>(QqLjBoN~@33*>qUC6-ijDW#TH zdJQ$!RC6u0)>eD-Er5Zk823X7~|C9BJfHMjdVRN&3t<)6BEX zI@|2audslLl~-AHwbi#X8>HBAr=54%b+_FQxpu;dC!KuCsi&R(Eo$ylw!i-UFQVo? zQS&!adSCe#HJ&x4d|ko`PLg6q#C&u_yeI-Bv{%e*buoHHPBEjpDT?G7WKwL*a*7xs zjNAEi+_%_$kKDhCn@ROw#m)ayAo8N zS<8R_@^Q3soG&xRWBaMh-_<=snr5Z4XDi7Qk(}ZgVGe#EDAvtRkQPtwl$s4Yq%*@3 zYD|FbG@l9&3^ea*Y#5BZwlYi7lRjDQNBU%!M%Oa{=SnB;0uM6nT85ql1k2g6ty#`- zqnp$6nW>bKPj97ixiQX&EzHSUw-tS9-IWE_@0gn-8q@I;P_Z&Hge23nyUG6h3Y@;- z2-O4Gw%~%j?%g*F?#GUicZ9GVV@vi}rA7hjGx?KD?gY22wokSvj5+JrbMf}ImLJ2i zJhlchx%6d2WaP`G$xXh`^Ul(IO;bXJ0d;Wyja35Wzj!o1Ke1!j-k-X|*`&#_Cym|5 z0V+tU6Y_3(joHbw*=J5}4bq>yJ*EW53Kw32lT;puQ7LM^-zcu$s|{_Ek;He$?sn7j ztVD-)6~8=3+J;D+g8t)E&YhVTuMJD01j5Lja)GDAY$H-J$B(&>D!7!qglG(w4+XbO zAMG*&G~6m-9~DTCxlnVN&{dMfwH0Ps_wEE;(Y$FmUNUN6l76|w;|lkc&I;$;m;D{I z>%F0;bn0My;O2-Lnl!Exi@IV=%KE3-()8x>$zRGbu$*qaWiE~gUpV3tUi_T ztM)WcbGxwik&GalmYL)zYq{;|sf2M?h})6O_f8rHC{g?ZLY76|?F5Lh_DmSevLWpe zOWUSVaYG~WZ*1fqsC24>t7?gJQDh^vUWoh3+ojGLw^pRh({yWgP_U(7)*yko$H`lz z%dp7VlC}?{tau30u&1S5i5Zx+zG60a@q}#eR`*If8cI7iWt{6Ho*Z^QZR|uEG_Jko zPLa%MVUNU2Tw$rg22D3*nd2%9DnmBS^sa>3F;T2z=do?>r>wsv=jfKt7jESkbz&*^ zvJG`*_|+|-o|>-_;A)4mT#+F$Hj1A~Fn;nQgLsY=WoEN>a2SvR1GeCs0hpz1Bd_tcRm$ z3yE6wlkCp#kExOKks<`wxF6NJJBi&%Jmpnf25#>Y!I1o{FsTjbt_@Et0$B1*QgY~1 zjnL+;M)#>jk==fvV(Kl@=F7@=?vTf=<^#o#M5Qh);Hiwj*A1+Ixp4|67CBD6*UX*J z8pbOjLD}Izs)=*)6T)+~gqQPu1o2Vdq3lx#+5&z6ic_&;0bb~vd`4&imN$%Tvu;W{ zu$)D>qk>5D0(47{cPd3#WQ9|xy*dwCWZjYqBO7oN@+3S%z)?Yf0u7@XNdW3^SVglI9lD$biiT%JgxI#%#*q>4`ffA$73DJCBq zpq60J=@5vp^hl_czV@PO>I^1iasyGhV+HNthI#IkW&~a%9-M)rCb|0MF^ec%jnDHr zY{^Us6;*wa&Ib5FSP&S208<A@kO4 z2E%|FRop!yK=`${6Pje~rr1RTVrt4Hlfl!Ynl8+QL^blG=!Rez(*Bkf;Z>dH3LlY0 zDiq~fXC$+DX;sJb9!Q=z+gO{6tO5{%0P6+8&i!*k>vmR=z(HgvXfzq3Xr0}F%F65r zawJ~RE@Z=H7uo3mivYKhHKNRh(&XX}(Zu-h1+}HyT*-3Llo1Px6}%$YBd0$#YCs{WU{V))aUMr7Q4Rj^`$_|4 zd&o+UQ}CID#~t}tFh3FO+E607WQYDYfqDDHGJqOTnPRghh=gQLsrwl#cm%P*Xp2f# zZhI)vDI%04B#xd&otS}SL|rwe5=rZ_b_0t8fB{K}mpd7O9e@x)k+^b%%L8b3(&ZRn zY{45?2m#xpA4GISTp>HfR%j_y8@RA2O(a*^+`z_tv9d!M)TdBM0Lm(v3$93fJ5~@3 zP&W-Pk|_Y@Ar2V>o#LecfX~Y!`CZKW*d-Mvj_<(zfL{@BuA0y>NZlYU7P&h-hr}W^ zYj#vPd0lphpe6yqTa|0^tOp-}k2?7D!NQ_|Xh;|P zr~w=oU`Lgmz`q8>)`=N8!6=UIV&0EZLZxfUABX5Rj?URIZe%7chTs+$k2icSol2 zHUQzp6N^JaARp#jQe<-t+;pd8DYztG31*XOodIlJ$D?$y1Sov6m-~Cz?O-nuo=m6_ z2&{Z<0hx}YBgrw-(l0ee!|3l_BU0;eZM9EzAIB>Ii-QNL4d%w2(PIEgKp(@A4Ac?S zDFu!iu>(=i5%VCn9B)o?tu_x2H+p7Vr5fW9+!q#17~>Ld0@*ebcwbojV(^+;7F0Xc zE=>^p=nOoso)gwRc~_CJI0zpSt8ZCT1cp3CQP|NB&MrF)87^Vw{dm(s%ycQhA{RQ4 z1FfP(x*7mwV|d!e4z!uLZyDWZB!y?4u%dOgE;5z$W6?sCpgYgNAQ$c9JT9W@nlozKU{WsjA!oyP>6dfvL0Zqkk~pvH0#H^#xt7rl!-<}JjKGb@b6dG= za139(S$vXyXEFx0aw$l5ZB^f&a&nLx7&)H6kk4Q=q-~cVGzb9+^*4bsYuhCA$uJEU zW<4nxAccxd9@O$4RzL?+-c)f6kUj<+%*6QhY2keMh>FSTu7=Br?JB$5?zrO#`}rrB zNl53BKe{=XO;B(orbC2#-X;fSa<%G4dSLG4v>$u!fEGmW&Ocm$rM&kt=iN#-8Y7(H zr1D|9r`}lplbO>~nWPCsEJ++bAOHSo^KG1;o3NVP=KC<2)O;EC%Rqk_ruq2-;g4(b z%TRwD=p82Y31Nd#I|G0z zV#PA6pNlG6+3@UOBr`)8$z?zhcdd3&3BZnlDA+LWTis4N+w2)W1PjhoyI6$0C(>bOEi z*xrnG>R}0FH@TNP+5j;OluWb_KB4K!Ihk^3Xa)0nenWKdtwn~U07VKBTs}-)5r4nb zxf^qD{P1Pl{w$3+?OHo{ptHd8_ zUYn1}l^m=>S3K#dl^^oR3?hR48zO<514GKlGxe`gAgC8487wuk^rn$gz*K?2xNSy* zWl{SCDH&@dKN@1cv50qEbIUq9Uzi+PWpq4fh2|&;lLXzKnnJ=d=7@NJ$Vl@XsKM7l zNOEt~+CWjjhM1R3!e4MnQi`~-Ztn6XsUsj4!A-h1wZ*$4$?rt*1ZZ-Mfz(H8^j%Rz zOUplmA)U%vZ5W78nTHU8JgWMC6mic);A;ZN+9^v;Rss9B7uWX-fpgcPlQaUh*9oDF z)D6`udj8U*oNVcoI=n)%qh(PjM^kpn@4_-Hby!%yYEpU961hgUhyB_s;x%%MU%owk zpX9Y6Zu|Yp=GRMe#q@e2f4qqM+f9+jpd(4yT0muYb(&8>Tf?9ycUCD?M9RM63+$5` z+LXn$N`ML~zDE3$y$Q*HZZBwmt=4=lkt8mU7|`kWHLB{cid0@JE>whKQ_BKiHbXlJ z2p6(^N|cT$SDT>UZgCZ=)lJTp#^ASpXX-`Ta_q* z2Zf9B@qI)29bDb=T@`gUlb8f~RED~BL7jQisq))58meMSAtFKKZn12_m4$Kzh=ET8 zWXI7Ltye-S%0mJ0VKubmF+kk4a1QB>%bX&&q2@5^>t+*RNfH;W4Pfe;W0}%GUaY`8 zGIJ~m=V1oZ;C5)Eg|J4%ViDW4bLFmnpTb<84hU+uB>ckdw$7pAROeB>)Iy2u$Ytlo zZUU{RGb*SDJS+2dAUnSK1d%h`W7W{~+U41^vKs2b2Z}jj{1DxY@ z&N^n{B_ehZMgjoSvo&Bv#5*u$%fwhNxZe|OK#Sn4N?F4=6OWsMhu|SwG$gC(S4dD| zhmmo0lf_UQLW8}%W~}H_BScgZXM9tzyGX*4HRQHeZ)sG_2otso{^#wWC${cL?8j2t zcHUs^2~cN^A~vK+G;aK3Y%8|NH9+{#tojnJGThx@Y`}P3vkuk^v(b{nwPIb#ABSO%P{ySumD>L z755KF^n#~YTRKZ{+HcQ!8nt2yN*p+bKgTth>N`TQ1SzY1qoPke^o}$J?xOY;acM!F zceS0GT7-t{A5FPpIj~HLY{=~;LhBI$XPt_iGKbW^9HHztL223E4NY9zGRfg}dmP!W z7-SwdES)m?BS*XxwmPkD~@|V3)#Fz}}6h`o& zj%mee8(-?wGrnesImp~0=HTx&TLW{NI)+gjQ8_NRc~@}7bqDNBiYP7Y7xC2z1nL)1 zf(z2lZ%<--GtU2rk?B~v$5H0F~qZ?6aGb>5a28GN_A>ZeBmv;};4$Wsd0 zD=PrVm z4`SZ-m)z@9|MuqgYf45)(reciL2IRxN%d9Uz9R^@I)%@IsZTPDn%o3u!$vIcRAa(T zxCAHL=N{1^Adt1ABYIY@wmu6X&UikK*_ERa zVd%w3S2u=<1_L4Aw%y0Q^Je+?>)v%nj53pC05kWN`Uj|w*>FnGCaQV`2ytyMPcex4 zgk8}25CQq%L|0lOcLZY;gG2bByKtJ&~zxmsqhg3p;W3fgbS zMH&f0kcu*lJ4J2JtCb1Y0Y+-CM)$pXDb}UGtxKC`2(nf{q^qd}e@U6*`kojLTtXsB zeTe`>jCdEjSy({<^C)ko5O-7e*fmvev?L5}4JHCd`)zRBx+<2Dy9~w_8A=8|{QASz zS;@^%J^@@tfDY=v!}>FO#5aJ0x7s?XsJ&2F?s{4j1p2-`-C6dnQ|ZYgFLJ$gd%E%S zn$^LzyXW4UPP$BO$|Z*B5?ZKuoghSMX)l<8JF?F})Lr%lR}Cvf>uyi(*{pu6PbDO@ z0!_4L-UT&i?ad$NFNIPneyyp+)JO_AJ;*JtsD16-SWK6TT5FjkjwAYh<+%=n9tX~! zC8;?OoYi)NE|H|eVzcB?J1kD^p0~*|$gw2ZDDMe{RaKtu3{u@a;116)6Dtv+9gyvA zV26b@Je=_yS9ruWeFzvooytXN&9aKbAjQkQGeg7;qGiqQUh;Ge7~-B zAD@sM> ztQ=aj=5L!H_}kQOgXbNJSsDYQo1&1FUwZ8DZk)8i2W4xs9v{Oqu`iImDzv2lX<%%5|-KY@rKExZ2Q(m0f~rzJ4cZHjFl--T~^;jSYI8ONsybzjwM?-eMgb}6}-?9RdPO3dwj~;)BE718t zQXTCvKxykbhoNPbT2s@~y*o<@pD7bRKB~+8ezt(fW`NshTMlW!+?za1NLVF4Xk~Bw zfS(ulBg3+wAK11|8|vue{@RKHC&c+SGQ+<=&AL;6I$gw^@)gwZG#6*pkCYkeF-+T$ z%>FiDrm4s|N(Ouo!twJQnG7G!m-?kh$p95v=|>U{D>w63#k#%Y^A$rL>0c9}vTd^w_Ni)79CJ(Fto z;C-P|gSJe*Wr4|aLfCWZ=q~7}#ElxyDG#Z=G*35$hDS^{eF$ECYz~ zFOTNkUd8ZfL}p_goa+ZlN1a$khRB0rA`?;fuH19gI$Nn$XJ6VnAyq4h#5(N{1*eVj zFD0;qXfIgo9`+zXg=IWqL9H5TOnDo>)I}m8ol~<%J34?s2x8dx<31Xisdw{C|H98L5g5O z^F3G@VkPmEaB9H?Dt2O_8^X)03Yu6!!~1rWHUx81=#xN~xXbfvKPAy8g+vGMnAh)M zWxkR~J1j4WR78JEBi{8%qq~*(Ln4`Ph;@5d z0=f#G(P{2VX5-N(3a6uNCjv?b&+pfnpeIybME)Xc|J*bBw2W-ZD7I3xjUS&<(aarcglK1?$-_5Z1g zg!*?i<5$$mR>cyj;_pf5AC3%@wXOPDBa^W@^{f4tNN(d3p91pWEf`VUP>WKBN3wr4 z0AWSxEv9zfE{INuyyK@jY3QzbIbY^QXGA3M{mmIXq56h*t9m|_fUJ>HyR=k4e`J2H1PjaEnbsz7sX4)czuY69RIC&fa{8=%uaG|ks-(KIW=yDe|VlO@?pAlbA zs8)Z}w5hF!kFvXG?{%0$XYbz{Eg6?1EoGliv2rSb9KfMJqf$}JkyXkwqslQVF(JzM z$i}l?qf*q+R3C%vs#-!hm0!?{vfbX5T0F{%A^>o}_B&;JeNVxI)dP$;TLXrSse;Su z(6zmg@=Hkl4`;GJN3t{bsX90idSfzP8^6pkew`o5RY%Rnp4z`1MQ6K;I&XJp55NxS zysKob&MX*0OZ}^r^UgRfon}I4V6Yv(Fsj}6=j@YCibC9(>a9A$34i#g_yQAVoPZOl zx;)jnH8vQ6CD4gUZ1(jzq3g>gL1(+r07=KbCPBr`jEb92_gAhw|YT!UU`8cA>u-;0@M_!Bo z<{rSthI>VcXF#+h;n7OaUdYwlYUTe!hIFM>Q0^%^6E&f*9pbnfRM0jbSpMd+hSuv-Uw~zOy#ah7NmaH*8@iolfWL zWXx#f1cGq^VVa(*r@61$#qwr%cP_M5FIFhcqa^31K+;yX3`gpIEj5IL z&Bbmpa)tjqDXDKtNvcXQKEdAKe$3B@Y2Hy9ALd?VN(NRC3nz87OFi5Bio+rUlSd?| zHP-b7IfSv**GmiT1-?O$u6sV{ehudy=Y6h@`@uLm#;E<8{&^sLX8-Bg|HYH$hiB2` zjZsv6pU=hy7Kc<*Z+jG--@y>K+*rh=ZF$C?RaeZlA-ce$rj0wDVFhveRtNH%f|T9~ z06&VlL*w!pfDlGf+rlWM0pGc>VVPQt8d970sLc(YB-o*_Kx-ZHB1_f}guA{?rb8aq zwL2XWg>dOh3SZwaGFL6!FB$20z)&0NG=z`Zai1@*c=>&u_0SfZhA%Toie*yu+n0jO zzxXzg`ijz-n*~F-_$ANO{YD@z3f5i-H(_XQ(Cnfuinay5JZHh$}8e-=5RuTo(9B`1PZ zgubi;a_OAW(U%9rAXjS78@2!KM}PjL`QLx^=TDmd^iil+@WJDX+Tg$&4e08A%?jH( z-yX>ZGEr<&(S7MFmOk85r3D#kUvFc5&PG{s0?D_@+eA#4PU-1OZg1ZrYJ;I8{kFcQ zLoA*KxpL&@vhVlXP)L#Y4UQ^@gw}OBla;ybxQ8vP4nFrFRjY4mOz$yK%1Qv8oWuf5 zo#Ayqb|?SxDBs%5{{uZ0ubMW5;V}RJ0flKpLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ z#a~mUA}tOU6miH<1;K)-h@)1a2o*xD(5i#Ur5{3*h9t$sQE)9d__0`ZaBF-|=;i0AKIoJj?&wpCh8?Ed~Tc;u&U`Ht{;~)TV84-Y1T-lB^P+6OWp7LE=ZQ zD;~dbF1jr6%&3`3&k;w7#bO&PZOlrhMm$LzQ#GCPg{;Ra=Pk}!xyqXNBnx z!U>@B#c@7{fY2_`s5#E}vEwvOfZ#K5rMLW*Ixzi7dab3!j)0zR;NrTaDSN=>4$%K( z$foQ{L7GCL0KA{kH|2odTcCT@>#ezu(+40!U8Qb-gF|4rNZD&X@9t{v?cX!a{(b;K zZ*r5q>dsIA000JJOGiWi{{a60|De66lK=n!32;bRa{vG?BLDy{BLR4&KXw2B00(qQ zO+^Rg2Nw+~9oj4N#sB~WD@jB_R9M69n9olmWf;dlEi=r}maxzwN=RFXxPgmwi+h5- z$S$5dtY%}@>TOHn)dR`?0qT14WCTyT=)nVe(hw8P%En}+{5Y84E@q((1yf+b+L?LT z89E*qkn*Et0Np+KB$LULdEe*#KF{-g-}iaOW7{^T6#)?^aK_9W>4;kn$g0`_+;-Hs z1HiKvfHv566S%stVUBctwlWU%0tw(ZQ;38%*tToqBpmQL3&+chi2(8FIaxD>m;`iZ ze8+wpk_*p!fkY%64n@M@l5aoWx$}vvsvh7yQ;0M$0!-R(n$f~q^UznH`#P?@t&_M` z6)vnb5Alwt;Q3e?aLa)XAX(-05)20Se;aV#!$8`9>)|*sURY}$0+ONNcAy&@Js}`T zz@G5mdid_K0PJ|a6TUz5dD59o>0b8kX7Z-2s;j_=Da1JNB{1_`%SSywkDtFTRT&w0 z;{zbKJK47FvX7)FHzY-|T|UWuc9QnCOdhab!Sjyu?d`pOzuy&03!2s|t13Ty8zA;# zHPyb`q3W8Khl|AxO<(U!0xN;w($|$zkN}c?zn@4X;tD`IolZFO0eGyxHC$b@G@!3{ z#(*hc0yrFitg3y$xo}HMYn3F~>NdM~MNt%x)wm+0K)tqx2g zJb!3|ZLc2{fe(RLG#WjO?KCwt(cj?JUXIEr0jE#*Ugy6feF@OnEh>K4}1pWsgorRH9 zDpjHzhVkD5*x1#Ifc)@$2|+O>F5+S*hPX P00000NkvXXu0mjfrWc Date: Fri, 23 Jul 2021 15:57:26 +0200 Subject: [PATCH 08/10] Cannon: Update cannon asset --- assets/Whale/Cannon(32x32).png | Bin 644 -> 0 bytes assets/Whale/Cannon(50x30).png | Bin 0 -> 6807 bytes src/main.rs | 2 +- src/nodes/cannon.rs | 8 ++++---- 4 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 assets/Whale/Cannon(32x32).png create mode 100644 assets/Whale/Cannon(50x30).png diff --git a/assets/Whale/Cannon(32x32).png b/assets/Whale/Cannon(32x32).png deleted file mode 100644 index 422b5aae6c9155ec17c37c381799a82b572b7b98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmV-~0(EX>4Tx04R}tkv&MmKpe$iQ>8^Kf_5n4kfAzR5EXIMDionYs1;guFuC*#nlvOW zE{=k0!NHHks)LKOt`4q(Aou~|=H{g6A|?JWDYS_3;J6>}?mh0_0Yan9G^=YI(DbUA zO2oxXc2x|#B7gz(B7&gIEMrcRlJFc~_we!cF2=LG&;2?2)SSftpGZ8*46{nSK|H-# zH8}4RhgnfpiO-40Ou8WPBi9v|-#8Z>7IPWeK{ zWtH<5XRTagt$XqphI0DKGS_JiBY{OML4pVcHIz_B6){?MQY@rsKknfla{Lmx6mpfo z$gzM5G{}x0{11M2Yvm^=+@w$(=zg*7j}aiS3pDGt{e5iP%@e@?3|#4Lf29G;e3D*o zYtbX1e;c^CZfnXOaJd6So($QP9m!8q$mfCgGy0}1Fn9~}thv3l_Hp_Eq^Yaq4RCM> zj20++-Q(TC&ffk#)9UXB7TR)x5##E900006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_005LpL_t(o!|j!^4Zt7_1bJpikp;5_vv67)u7GI?NZ_JL eC6C9@i diff --git a/assets/Whale/Cannon(50x30).png b/assets/Whale/Cannon(50x30).png new file mode 100644 index 0000000000000000000000000000000000000000..dffabfc308616873ec36f6d5e921283a87df3b43 GIT binary patch literal 6807 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 Date: Fri, 23 Jul 2021 16:08:04 +0200 Subject: [PATCH 09/10] Add cannonball hit fxses --- src/main.rs | 8 ++++++++ src/nodes/fxses.rs | 1 + 2 files changed, 9 insertions(+) diff --git a/src/main.rs b/src/main.rs index 8a6165a576..738c32c5bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,7 @@ pub enum GameType { struct Resources { hit_fxses: EmittersCache, + cannonball_hit_fxses: EmittersCache, explosion_fxses: EmittersCache, life_explosion_fxses: EmittersCache, tiled_map: tiled::Map, @@ -65,6 +66,10 @@ struct Resources { pub const HIT_FX: &'static str = r#"{"local_coords":false,"emission_shape":"Point","one_shot":true,"lifetime":0.2,"lifetime_randomness":0,"explosiveness":0.65,"amount":41,"shape":{"Circle":{"subdivisions":10}},"emitting":false,"initial_direction":{"x":0,"y":-1},"initial_direction_spread":6.2831855,"initial_velocity":73.9,"initial_velocity_randomness":0.2,"linear_accel":0,"size":5.6000004,"size_randomness":0.4,"blend_mode":"Alpha","colors_curve":{"start":{"r":0.8200004,"g":1,"b":0.31818175,"a":1},"mid":{"r":0.71000004,"g":0.36210018,"b":0,"a":1},"end":{"r":0.02,"g":0,"b":0.000000007152557,"a":1}},"gravity":{"x":0,"y":0},"post_processing":{}} "#; +/// Has no size randomness, in order to make it clear to players which the radius is. +pub const CANNONBALL_HIT_FX: &'static str = r#"{"local_coords":false,"emission_shape":"Point","one_shot":true,"lifetime":0.2,"lifetime_randomness":0,"explosiveness":0.65,"amount":41,"shape":{"Circle":{"subdivisions":10}},"emitting":false,"initial_direction":{"x":0,"y":-1},"initial_direction_spread":6.2831855,"initial_velocity":73.9,"initial_velocity_randomness":0.2,"linear_accel":0,"size":64.0,"size_randomness":0.0,"blend_mode":"Alpha","colors_curve":{"start":{"r":0.8200004,"g":1,"b":0.31818175,"a":1},"mid":{"r":0.71000004,"g":0.36210018,"b":0,"a":1},"end":{"r":0.02,"g":0,"b":0.000000007152557,"a":1}},"gravity":{"x":0,"y":0},"post_processing":{}} +"#; + pub const EXPLOSION_FX: &'static str = r#"{"local_coords":false,"emission_shape":{"Sphere":{"radius":0.6}},"one_shot":true,"lifetime":0.35,"lifetime_randomness":0,"explosiveness":0.6,"amount":131,"shape":{"Circle":{"subdivisions":10}},"emitting":false,"initial_direction":{"x":0,"y":-1},"initial_direction_spread":6.2831855,"initial_velocity":316,"initial_velocity_randomness":0.6,"linear_accel":-7.4000025,"size":5.5,"size_randomness":0.3,"size_curve":{"points":[[0.005,1.48],[0.255,1.0799999],[1,0.120000005]],"interpolation":"Linear","resolution":30},"blend_mode":"Additive","colors_curve":{"start":{"r":0.9825908,"g":1,"b":0.13,"a":1},"mid":{"r":0.8,"g":0.19999999,"b":0.2000002,"a":1},"end":{"r":0.101,"g":0.099,"b":0.099,"a":1}},"gravity":{"x":0,"y":-500},"post_processing":{}} "#; @@ -161,6 +166,8 @@ impl Resources { ); let hit_fxses = EmittersCache::new(nanoserde::DeJson::deserialize_json(HIT_FX).unwrap()); + let cannonball_hit_fxses = + EmittersCache::new(nanoserde::DeJson::deserialize_json(CANNONBALL_HIT_FX).unwrap()); let explosion_fxses = EmittersCache::new(nanoserde::DeJson::deserialize_json(EXPLOSION_FX).unwrap()); let life_explosion_fxses = @@ -168,6 +175,7 @@ impl Resources { Ok(Resources { hit_fxses, + cannonball_hit_fxses, explosion_fxses, life_explosion_fxses, tiled_map, diff --git a/src/nodes/fxses.rs b/src/nodes/fxses.rs index 136ece8aa3..216be251fa 100644 --- a/src/nodes/fxses.rs +++ b/src/nodes/fxses.rs @@ -18,6 +18,7 @@ impl scene::Node for Fxses { let _z = telemetry::ZoneGuard::new("draw particles"); resources.hit_fxses.draw(); + resources.cannonball_hit_fxses.draw(); resources.explosion_fxses.draw(); push_camera_state(); From f8db6af3a0a568e1c3c9cd6dbb3c056fcdf79674 Mon Sep 17 00:00:00 2001 From: Saverio Miroddi Date: Fri, 23 Jul 2021 16:08:14 +0200 Subject: [PATCH 10/10] Cannonball: Use hit fx large --- src/nodes/cannonball.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nodes/cannonball.rs b/src/nodes/cannonball.rs index d11ce5614b..c7763d0bed 100644 --- a/src/nodes/cannonball.rs +++ b/src/nodes/cannonball.rs @@ -126,7 +126,8 @@ impl scene::Node for Cannonballs { } node.cannonballs.retain(|cannonball| { - let hit_fxses = &mut storage::get_mut::().hit_fxses; + let hit_fxses = &mut storage::get_mut::().cannonball_hit_fxses; + let explosion_position = cannonball.body.pos + vec2(CANNONBALL_WIDTH / 2., CANNONBALL_HEIGHT / 2.);