commit
3ba8505104
assets/worlds
src
@ -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"
|
||||
|
||||
}
|
||||
|
||||
]
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod base;
|
||||
pub mod jellyfish;
|
||||
pub mod octopus;
|
||||
pub mod whirlpool;
|
||||
pub mod whirlpool;
|
||||
pub mod pufferfish;
|
154
src/entities/enemy/pufferfish.rs
Normal file
154
src/entities/enemy/pufferfish.rs
Normal file
@ -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<RaylibDrawHandle>,
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")?
|
||||
})
|
||||
}
|
||||
|
10
src/world.rs
10
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<JellyFish>,
|
||||
pub octopus: Vec<Octopus>,
|
||||
pub whirlpool: Vec<Whirlpool>,
|
||||
pub pufferfish: Vec<Pufferfish>
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user