diff --git a/assets/worlds/mainworld.json b/assets/worlds/mainworld.json index 368ba0d..5c86b0f 100644 --- a/assets/worlds/mainworld.json +++ b/assets/worlds/mainworld.json @@ -183,5 +183,100 @@ "should_remove": false, "rotation": 0 } + + ], + "pufferfish": [ + { + "position" : { + "x": 261, + "y": 387 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 195, + "y": 694 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 635, + "y": 731 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 169, + "y": 1104 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 478, + "y": 1333 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 499, + "y": 1775 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + }, + { + "position" : { + "x": 74, + "y": 1259 + }, + "is_knocking_back": false, + "time_knocking_back": 0.0, + "inflate_timer": 0.0, + "is_large": false, + "stun_timer": 0.0, + "puffer_state": "SmallIdle" + + } + ] } \ No newline at end of file diff --git a/src/entities/enemy/mod.rs b/src/entities/enemy/mod.rs index 18acd78..91246eb 100644 --- a/src/entities/enemy/mod.rs +++ b/src/entities/enemy/mod.rs @@ -1,4 +1,5 @@ pub mod base; pub mod jellyfish; pub mod octopus; -pub mod whirlpool; \ No newline at end of file +pub mod whirlpool; +pub mod pufferfish; \ No newline at end of file diff --git a/src/entities/enemy/pufferfish.rs b/src/entities/enemy/pufferfish.rs new file mode 100644 index 0000000..9f72119 --- /dev/null +++ b/src/entities/enemy/pufferfish.rs @@ -0,0 +1,154 @@ +use raylib::prelude::*; + +use serde::{Deserialize, Serialize}; + +use crate::{lib::utils::calculate_linear_slide, pallette::TRANSLUCENT_RED_64}; + +use super::base::EnemyBase; + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +pub enum PufferState { + SmallIdle, + Growing, + LargeIdle, + Blowing, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Pufferfish { + pub position: Vector2, + pub is_knocking_back: bool, + pub time_knocking_back: f64, + + pub inflate_timer: f64, + pub is_large: bool, + pub stun_timer: f64, + pub puffer_state: PufferState, +} + +impl EnemyBase for Pufferfish { + fn render( + &mut self, + context_2d: &mut RaylibMode2D, + player: &mut crate::player::Player, + resources: &mut crate::resources::GlobalResources, + dt: f64, + ) { + + let is_stunned = self.stun_timer > 0.0; + + // Render the stun ring + if is_stunned { + println!("Stunned"); + let stun_ring_alpha = + calculate_linear_slide(self.stun_timer / 1.0); + context_2d.draw_circle_v( + self.position, + 12.0, + TRANSLUCENT_RED_64.fade(0.55 * stun_ring_alpha as f32), + ); + + self.stun_timer -= dt; + } + + + let angle = player.position.angle_to(self.position).to_degrees(); + + + match self.puffer_state { + PufferState::SmallIdle => { + resources.pufferfish_small.draw( + context_2d, + Vector2 { + x: self.position.x, + y: self.position.y, + }, + angle, + ); + + if self.position.distance_to(player.position).abs() <= 100.0 && self.inflate_timer > 1.0{ + self.puffer_state = PufferState::Growing; + } + self.is_large = false; + }, + PufferState::Growing => { + self.inflate_timer = 0.0; + resources.pufferfish_expand.draw( + context_2d, + Vector2 { + x: self.position.x, + y: self.position.y, + }, + angle, + ); + + if resources.pufferfish_expand.get_current_frame_id(context_2d) == 3 { + self.puffer_state = PufferState::LargeIdle; + } + self.is_large = true; + + }, + PufferState::LargeIdle => { + self.inflate_timer = 0.0; + resources.pufferfish_big.draw( + context_2d, + Vector2 { + x: self.position.x, + y: self.position.y, + }, + angle, + ); + + if self.position.distance_to(player.position).abs() <= 65.0{ + self.puffer_state = PufferState::Blowing; + self.is_knocking_back = true; + self.time_knocking_back = 0.0; + } + + self.is_large = true; + }, + PufferState::Blowing => { + + resources.pufferfish_attack.draw( + context_2d, + Vector2 { + x: self.position.x, + y: self.position.y, + }, + angle, + ); + + + if resources.pufferfish_expand.get_current_frame_id(context_2d) == 3 && self.inflate_timer > 1.0{ + self.puffer_state = PufferState::SmallIdle; + self.inflate_timer = 0.0; + } + self.is_large = false; + }, + } + } + + fn handle_logic(&mut self, player: &mut crate::player::Player, dt: f64) { + + + + self.inflate_timer += dt; + self.time_knocking_back += dt; + + if self.time_knocking_back >= 0.5{ + self.is_knocking_back = false; + } + + if self.position.distance_to(player.position).abs() > 120.0 && self.is_large { + self.puffer_state = PufferState::Blowing; + self.inflate_timer = 0.0; + } + + } + + fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64) { + + self.stun_timer = stun_duration; + + } +} diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs index d1aa504..9f9970a 100644 --- a/src/logic/ingame/mod.rs +++ b/src/logic/ingame/mod.rs @@ -253,6 +253,17 @@ impl Screen for InGameScreen { } + // Iterates over pufferfish + for pufferfish in game_core.world.pufferfish.iter_mut(){ + + pufferfish.handle_logic(&mut game_core.player, dt); + pufferfish.render(&mut context_2d, &mut game_core.player, &mut game_core.resources, dt); + + + + } + + // Removes whirlpools set for removal game_core.world.whirlpool.retain(|x| !x.should_remove()); diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs index bf194bf..0eee09e 100644 --- a/src/logic/ingame/playerlogic.rs +++ b/src/logic/ingame/playerlogic.rs @@ -86,7 +86,7 @@ pub fn update_player_movement( game_core .player .begin_attack(&mut game_core.world, draw_handle.get_time()); - println!("{{\"x\":{}, \"y\":{}}},",f32::round(game_core.player.position.x),f32::round(game_core.player.position.y)); + //println!("{{\"x\":{}, \"y\":{}}},",f32::round(game_core.player.position.x),f32::round(game_core.player.position.y)); } // Move the player in their direction @@ -209,6 +209,44 @@ pub fn update_player_movement( } + for pufferfish in game_core.world.pufferfish.iter_mut(){ + + if pufferfish.is_knocking_back{ + // Calculates info for formulas + + // Deltas between positions + let net_pose = game_core.player.position - pufferfish.position; + + // Angle between: UNITS: RADIANS + let angle = net_pose.y.atan2(net_pose.x); + + // Calculates force + let force = 1.0; + + // Calculates componets of force + let mut force_x = (force as f32 * angle.cos()).clamp(-1.0, 1.0); + let mut force_y = (force as f32 * angle.sin()).clamp(-1.0, 1.0); + + // Prevents Nan erros + if force_x.is_nan(){ + force_x = 1.0 * net_pose.x; + } + + if force_y.is_nan(){ + force_y = 1.0 * net_pose.y; + } + + game_core.player.additional_vel.x += force_x; + game_core.player.additional_vel.y += force_y; + + should_apply_friction = false; + + } + + + + } + if should_apply_friction { game_core.player.additional_vel.x /= PLAYER_FRICTION; game_core.player.additional_vel.y /= PLAYER_FRICTION; diff --git a/src/player.rs b/src/player.rs index b11b086..c173602 100644 --- a/src/player.rs +++ b/src/player.rs @@ -103,6 +103,11 @@ impl Player { if whirlpool.position.distance_to(self.position).abs() <= stun_reach { whirlpool.handle_getting_attacked(self.attacking_timer, current_time); } + } + for pufferfish in world.pufferfish.iter_mut() { + if pufferfish.position.distance_to(self.position).abs() <= stun_reach { + pufferfish.handle_getting_attacked(self.attacking_timer, current_time); + } } } } diff --git a/src/resources.rs b/src/resources.rs index d14c0b0..589a8fd 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -28,6 +28,10 @@ pub struct GlobalResources { pub octopus_animation_regular: FrameAnimationWrapper, pub octopus_animation_attack: FrameAnimationWrapper, pub whirlpool: FrameAnimationWrapper, + pub pufferfish_big: FrameAnimationWrapper, + pub pufferfish_small: FrameAnimationWrapper, + pub pufferfish_attack: FrameAnimationWrapper, + pub pufferfish_expand: FrameAnimationWrapper, // Darkness layer pub darkness_overlay: Texture2D, @@ -255,6 +259,42 @@ impl GlobalResources { 4, 4, ), + pufferfish_big: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/enemies/pufferFishBigIdle.png")?, + )?, + Vector2 { x: 19.0, y: 19.0 }, + 3, + 2, + ), + pufferfish_small: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/enemies/pufferFishIdle.png")?, + )?, + Vector2 { x: 19.0, y: 19.0 }, + 6, + 2, + ), + pufferfish_attack: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/enemies/pufferFishAttack.png")?, + )?, + Vector2 { x: 39.0, y: 25.0 }, + 4, + 2, + ), + pufferfish_expand: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/enemies/pufferFishExpand.png")?, + )?, + Vector2 { x: 19.0, y: 19.0 }, + 4, + 2, + ), breath: Sound::load_sound("./assets/audio/breath.mp3")? }) } diff --git a/src/world.rs b/src/world.rs index e1e1e00..15f592b 100644 --- a/src/world.rs +++ b/src/world.rs @@ -4,14 +4,7 @@ use failure::Error; use raylib::math::{Rectangle, Vector2}; use serde::{Deserialize, Serialize}; -use crate::{ - entities::{ - enemy::{jellyfish::JellyFish, octopus::Octopus, whirlpool::Whirlpool,}, - fish::FishEntity, - - }, - player::Player, -}; +use crate::{entities::{enemy::{jellyfish::JellyFish, octopus::Octopus, pufferfish::Pufferfish, whirlpool::Whirlpool}, fish::FishEntity}, player::Player}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct World { @@ -31,6 +24,7 @@ pub struct World { pub jellyfish: Vec, pub octopus: Vec, pub whirlpool: Vec, + pub pufferfish: Vec }