suck air bubble animation

This commit is contained in:
Evan Pratten 2021-04-24 20:07:19 -04:00
parent cf342aa932
commit c5a2877efd
6 changed files with 109 additions and 17 deletions

@ -6,9 +6,10 @@ pub trait EnemyBase {
fn render(
&mut self,
context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
player: &mut Player,
resources: &mut GlobalResources,
dt: f64,
);
fn handle_logic(&mut self, player: &mut Player, dt: f64);
fn handle_getting_attacked(&mut self, stun_duration: f64);
fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64);
}

@ -28,6 +28,7 @@ impl EnemyBase for JellyFish {
fn render(
&mut self,
context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
player: &mut Player,
resources: &mut GlobalResources,
dt: f64,
) {
@ -85,7 +86,7 @@ impl EnemyBase for JellyFish {
}
}
fn handle_getting_attacked(&mut self, stun_duration: f64) {
fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64) {
self.stunned_timer = stun_duration;
self.max_stunned_time = stun_duration;
}

@ -1,7 +1,25 @@
use crate::{
lib::utils::calculate_linear_slide,
pallette::{TRANSLUCENT_RED_64, TRANSLUCENT_WHITE_64},
player::Player,
};
use super::base::EnemyBase;
use rand::{prelude::ThreadRng, Rng};
use raylib::prelude::*;
use serde::{Deserialize, Serialize};
const OCTOPUS_SUCK_AIR_DELAY: f64 = 3.5;
const OCTOPUS_SUCK_AIR_RANGE: f32 = 70.0;
const OCTOPUS_SUCK_AIR_DURATION: f64 = 1.0;
// const RNG: ThreadRng = rand::thread_rng();
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
struct OctopusAirBubble {
position: Vector2,
speed: f32,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct Octopus {
pub position_a: Vector2,
@ -14,6 +32,11 @@ pub struct Octopus {
pub stunned_timer: f64,
#[serde(skip)]
pub max_stunned_time: f64,
#[serde(skip)]
pub suck_air_time_remaining: f64,
#[serde(skip)]
suck_air_bubbles: Vec<OctopusAirBubble>,
}
impl Octopus {}
@ -22,29 +45,76 @@ impl EnemyBase for Octopus {
fn render(
&mut self,
context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
player: &mut Player,
resources: &mut crate::resources::GlobalResources,
dt: f64,
) {
let is_octopus_stunned = self.stunned_timer > 0.0;
// Simple sine position
let h_trans = if is_octopus_stunned {
0.0
} else {
(context_2d.get_time() / 8.0).sin().abs() as f32
};
let h_trans = (context_2d.get_time() / 8.0).sin().abs() as f32;
// Modify the current pose
let dist_a_to_b = self.position_b - self.position_a;
self.current_position =(dist_a_to_b * h_trans) + self.position_a;
self.current_position = (dist_a_to_b * h_trans) + self.position_a;
// Render the stun ring
if self.max_stunned_time > 0.0 && self.stunned_timer > 0.0 {
let stun_ring_alpha =
calculate_linear_slide(self.stunned_timer / self.max_stunned_time);
context_2d.draw_circle_v(
self.current_position,
20.0,
TRANSLUCENT_RED_64.fade(0.55 * stun_ring_alpha as f32),
);
self.stunned_timer -= dt;
}
// Every once in a while, start sucking air
if (context_2d.get_time() % OCTOPUS_SUCK_AIR_DELAY) < 0.1 {
self.suck_air_time_remaining = OCTOPUS_SUCK_AIR_DURATION;
// Spawn a few air bubbles if the player is in range
if player.position.distance_to(self.current_position).abs() <= OCTOPUS_SUCK_AIR_RANGE {
for _ in 0..3 {
self.suck_air_bubbles.push(OctopusAirBubble {
position: player.position,
speed: rand::thread_rng().gen_range(0.8..1.3),
});
}
}
}
// Handle sucking air bubble animation
if self.suck_air_time_remaining > 0.0 {
// Render and update all bubbles
for bubble in self.suck_air_bubbles.iter_mut() {
// Get the direction from the bubble to the octopus
let direction = (self.current_position - bubble.position).normalized();
// Render the bubble
context_2d.draw_circle_v(bubble.position, 2.0, TRANSLUCENT_WHITE_64);
// Move the bubble
bubble.position += direction * bubble.speed;
}
// Reduce time
self.suck_air_time_remaining -= dt;
} else {
self.suck_air_bubbles.clear();
}
// TODO: TMP
context_2d.draw_circle_v(self.current_position, 10.0, Color::RED);
}
fn handle_logic(&mut self, player: &mut crate::player::Player, dt: f64) {}
fn handle_logic(&mut self, player: &mut crate::player::Player, dt: f64) {
if self.suck_air_time_remaining > 0.0 {}
}
fn handle_getting_attacked(&mut self, stun_duration: f64) {
todo!()
fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64) {
self.stunned_timer = stun_duration;
self.max_stunned_time = stun_duration;
}
}

@ -3,7 +3,12 @@ mod playerlogic;
use raylib::prelude::*;
use crate::{entities::enemy::base::EnemyBase, gamecore::{GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer, pallette::{SKY, WATER, WATER_DARK}};
use crate::{
entities::enemy::base::EnemyBase,
gamecore::{GameCore, GameState},
lib::wrappers::audio::player::AudioPlayer,
pallette::{SKY, WATER, WATER_DARK},
};
use super::screen::Screen;
@ -128,11 +133,21 @@ impl Screen for InGameScreen {
// Render entities
for jellyfish in game_core.world.jellyfish.iter_mut() {
jellyfish.handle_logic(&mut game_core.player, dt);
jellyfish.render(&mut context_2d, &mut game_core.resources, dt);
jellyfish.render(
&mut context_2d,
&mut game_core.player,
&mut game_core.resources,
dt,
);
}
for octopus in game_core.world.octopus.iter_mut() {
octopus.handle_logic(&mut game_core.player, dt);
octopus.render(&mut context_2d, &mut game_core.resources, dt);
octopus.render(
&mut context_2d,
&mut game_core.player,
&mut game_core.resources,
dt,
);
}
// Render Player

@ -79,7 +79,7 @@ pub fn update_player_movement(
let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
if user_request_action {
game_core.player.begin_attack(&mut game_core.world);
game_core.player.begin_attack(&mut game_core.world, draw_handle.get_time());
}
// Move the player in their direction

@ -98,7 +98,7 @@ impl Player {
}
/// Try to attack with the stun gun
pub fn begin_attack(&mut self, world: &mut World) {
pub fn begin_attack(&mut self, world: &mut World, current_time: f64) {
if self.inventory.stun_gun.is_some() && !self.is_stunned() {
self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
@ -107,7 +107,12 @@ impl Player {
for jellyfish in world.jellyfish.iter_mut() {
if jellyfish.position.distance_to(self.position).abs() <= stun_reach {
jellyfish.handle_getting_attacked(self.attacking_timer);
jellyfish.handle_getting_attacked(self.attacking_timer, current_time);
}
}
for octopus in world.octopus.iter_mut() {
if octopus.current_position.distance_to(self.position).abs() <= stun_reach {
octopus.handle_getting_attacked(self.attacking_timer, current_time);
}
}
}