From db3be2e76fe19748c586093fbc3e0eb689cfbeeb Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 14 Apr 2022 14:45:23 -0500 Subject: [PATCH 1/3] Implement Fish Schools Part of #337 --- assets/maps/test_level.json | 96 ++--- assets/textures.json | 45 +++ .../textures/items/FishSchoolIcon(64x64).png | Bin 0 -> 603 bytes assets/textures/items/SmallFish1(13x9).png | Bin 0 -> 171 bytes assets/textures/items/SmallFish2(13x9).png | Bin 0 -> 163 bytes assets/textures/items/SmallFish3(13x9).png | Bin 0 -> 170 bytes src/editor/gui/windows/create_object.rs | 2 +- src/editor/mod.rs | 23 +- src/game/mod.rs | 9 +- src/map/fish_school.rs | 347 ++++++++++++++++++ src/map/mod.rs | 2 + src/utils/ease.rs | 68 ++++ src/utils/mod.rs | 1 + src/utils/timer.rs | 5 + 14 files changed, 527 insertions(+), 71 deletions(-) create mode 100644 assets/textures/items/FishSchoolIcon(64x64).png create mode 100644 assets/textures/items/SmallFish1(13x9).png create mode 100644 assets/textures/items/SmallFish2(13x9).png create mode 100644 assets/textures/items/SmallFish3(13x9).png create mode 100644 src/map/fish_school.rs create mode 100644 src/utils/ease.rs diff --git a/assets/maps/test_level.json b/assets/maps/test_level.json index 6a0431fbe2..a0218c4917 100644 --- a/assets/maps/test_level.json +++ b/assets/maps/test_level.json @@ -809,6 +809,30 @@ "kind": "object_layer", "has_collision": false, "objects": [ + { + "id": "fish_school", + "kind": "environment", + "position": { + "x": 312.14642, + "y": 615.9121 + } + }, + { + "id": "fish_school", + "kind": "environment", + "position": { + "x": 466.00787, + "y": 497.32727 + } + }, + { + "id": "fish_school", + "kind": "environment", + "position": { + "x": 622.8744, + "y": 246.50894 + } + }, { "id": "crab", "kind": "environment", @@ -853,8 +877,8 @@ "id": "trident", "kind": "item", "position": { - "x": 786.3906, - "y": 677.3542 + "x": 702.3754, + "y": 287.63873 } }, { @@ -945,38 +969,6 @@ "y": 518.0 } }, - { - "id": "jellyfish", - "kind": "item", - "position": { - "x": 696.2978, - "y": 647.9329 - } - }, - { - "id": "galleon", - "kind": "item", - "position": { - "x": 500.0, - "y": 650.0 - } - }, - { - "id": "volcano", - "kind": "item", - "position": { - "x": 350.0, - "y": 650.0 - } - }, - { - "id": "shark_rain", - "kind": "item", - "position": { - "x": 300.0, - "y": 50.0 - } - }, { "id": "grenades", "kind": "item", @@ -1001,22 +993,6 @@ "y": 388.0 } }, - { - "id": "shoes", - "kind": "item", - "position": { - "x": 770.0, - "y": 147.0 - } - }, - { - "id": "curse", - "kind": "item", - "position": { - "x": 772.0, - "y": 266.0 - } - }, { "id": "cannon", "kind": "item", @@ -1049,22 +1025,6 @@ "y": 552.0 } }, - { - "id": "life_ring", - "kind": "item", - "position": { - "x": 435.33334, - "y": 547.3333 - } - }, - { - "id": "flippers", - "kind": "item", - "position": { - "x": 500.0, - "y": 650.0 - } - }, { "id": "kick_bomb", "kind": "item", @@ -1802,10 +1762,10 @@ "58": [ "jumpthrough" ], - "56": [ + "60": [ "jumpthrough" ], - "60": [ + "56": [ "jumpthrough" ] } diff --git a/assets/textures.json b/assets/textures.json index 7829b80ca0..dbb56dec86 100644 --- a/assets/textures.json +++ b/assets/textures.json @@ -436,6 +436,51 @@ "y": 8 } }, + { + "id": "small_fish1", + "path": "textures/items/SmallFish1(13x9).png", + "type": "spritesheet", + "sprite_size": { + "x": 13, + "y": 9 + } + }, + { + "id": "small_fish1", + "path": "textures/items/SmallFish1(13x9).png", + "type": "spritesheet", + "sprite_size": { + "x": 13, + "y": 9 + } + }, + { + "id": "small_fish2", + "path": "textures/items/SmallFish3(13x9).png", + "type": "spritesheet", + "sprite_size": { + "x": 13, + "y": 9 + } + }, + { + "id": "small_fish3", + "path": "textures/items/SmallFish2(13x9).png", + "type": "spritesheet", + "sprite_size": { + "x": 13, + "y": 9 + } + }, + { + "id": "fish_school_icon", + "path": "textures/items/FishSchoolIcon(64x64).png", + "type": "spritesheet", + "sprite_size": { + "x": 64, + "y": 64 + } + }, { "id": "sword", "path": "textures/items/Sword(65x93).png", diff --git a/assets/textures/items/FishSchoolIcon(64x64).png b/assets/textures/items/FishSchoolIcon(64x64).png new file mode 100644 index 0000000000000000000000000000000000000000..e47d40080a347ab06906797866d60d7bef215b9d GIT binary patch literal 603 zcmV-h0;K(kP)06-6h;ppGC@XAp+a?LFyal|8^}-w(rW`7p20N>79PPXFvSyPN>DHB?RG|sf31LmK?*xB4 zoVXoMew{@T6aelbxWM5aJizP6`(j0i5+H;VA|u&y(L)57h<=b3u;#qQoVRUxY@<;E zG>J}m2@g~3dHr~A%guGRMCb(x-M}d~NA#seUuwTj6ib-}tRJkqcI75;s<$2bQd7O{ zqMzp_qE5dd1yEi;hs2o`C&U;+0{j%*(**t-mXri3H%9=~d;B>Are#PPCUrlpupoQ-*TD!`$+(%l8>if0wqbjpabqn``HjW-)!2 zy2P3hy)f6+w!23l;EWi<2TQFL7pAl9+w;Ypt9Qe>mSt@%=L63#E(^Zh+*xnMc%RwO UX{JO=1<-Z|Pgg&ebxsLQ00;FzcmMzZ literal 0 HcmV?d00001 diff --git a/assets/textures/items/SmallFish2(13x9).png b/assets/textures/items/SmallFish2(13x9).png new file mode 100644 index 0000000000000000000000000000000000000000..9de07d790d10efb208def6e3a428746645844c4c GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp@K+MU(1|(lrEz1H@S)MMAAre#PPTa_QK!Jya-)-T7 zghf3kT=Zg6L@y_;g9$(&X?mfmw@AU7R&PeeSkx?9%^B7>~voMMS@{Iu5jz N!PC{xWt~$(6993-KNtW2 literal 0 HcmV?d00001 diff --git a/assets/textures/items/SmallFish3(13x9).png b/assets/textures/items/SmallFish3(13x9).png new file mode 100644 index 0000000000000000000000000000000000000000..d62a20a70b42897b9fb285652207acb2d6ef3b5d GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp@K+MU(1|(lrEz1H@g`O^sAre#PPCUrlpupoQ&-b{| z*m%YUM&(V7oW>R34j5G|^fi=H{vYz9UUff%$-S%dew~ZiHG5{162t3l(e~Y$Tz9fM znG57*em?OkGNq*yw4A}y)z4*}Q$iB}T){q3 literal 0 HcmV?d00001 diff --git a/src/editor/gui/windows/create_object.rs b/src/editor/gui/windows/create_object.rs index 5a5c1ccb95..92320eb02d 100644 --- a/src/editor/gui/windows/create_object.rs +++ b/src/editor/gui/windows/create_object.rs @@ -132,7 +132,7 @@ impl Window for CreateObjectWindow { .keys() .map(|k| k.as_str()) .collect::>(), - MapObjectKind::Environment => vec!["sproinger", "crab"], + MapObjectKind::Environment => vec!["sproinger", "crab", "fish_school"], MapObjectKind::Decoration => resources .decoration .keys() diff --git a/src/editor/mod.rs b/src/editor/mod.rs index f1bac22bb7..ef98e8f248 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -1,7 +1,11 @@ use std::any::TypeId; use std::path::Path; -use crate::{exit_to_main_menu, map::CRAB_TEXTURE_ID, quit_to_desktop, Resources}; +use crate::{ + exit_to_main_menu, + map::{CRAB_TEXTURE_ID, FISH_SCHOOL_ICON_TEXTURE_ID}, + quit_to_desktop, Resources, +}; mod camera; @@ -1488,6 +1492,19 @@ impl Node for Editor { color::WHITE, ); } + "fish_school" => { + let texture_res = resources + .textures + .get(FISH_SCHOOL_ICON_TEXTURE_ID) + .unwrap(); + + draw_texture( + texture_res.texture, + object_position.x, + object_position.y, + color::WHITE, + ); + } _ => { label = Some("INVALID OBJECT ID".to_string()); } @@ -1624,6 +1641,10 @@ fn get_object_size(object: &MapObject) -> Vec2 { let texture_res = resources.textures.get(CRAB_TEXTURE_ID).unwrap(); res = texture_res.meta.frame_size; } + "fish_school" => { + let texture_res = resources.textures.get(FISH_SCHOOL_ICON_TEXTURE_ID).unwrap(); + res = texture_res.meta.frame_size; + } _ => label = Some("INVALID OBJECT ID".to_string()), }, } diff --git a/src/game/mod.rs b/src/game/mod.rs index 8f971a020c..6a18bc569b 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -35,7 +35,8 @@ use crate::effects::active::projectiles::fixed_update_projectiles; use crate::effects::active::triggered::fixed_update_triggered_effects; use crate::items::spawn_item; use crate::map::{ - fixed_update_sproingers, spawn_crab, spawn_decoration, spawn_sproinger, update_crabs, + debug_draw_fish_schools, fixed_update_sproingers, spawn_crab, spawn_decoration, + spawn_fish_school, spawn_sproinger, update_crabs, update_fish_schools, }; use crate::network::{ fixed_update_network_client, fixed_update_network_host, update_network_client, @@ -121,6 +122,7 @@ impl Game { .add_system(update_player_inventory) .add_system(update_player_passive_effects) .add_system(update_player_events) + .add_system(update_fish_schools) .add_system(update_crabs); fixed_updates_builder @@ -151,6 +153,7 @@ impl Game { .with_thread_local(debug_draw_physics_bodies) .with_thread_local(debug_draw_rigid_bodies) .with_thread_local(debug_draw_active_effects) + .with_thread_local(debug_draw_fish_schools) .build(); let res = Game { @@ -270,6 +273,10 @@ pub fn spawn_map_objects(world: &mut World, map: &Map) -> Result> { let crab = spawn_crab(world, map_object.position)?; objects.push(crab); } + "fish_school" => { + let fish_school = spawn_fish_school(world, map_object.position)?; + objects.push(fish_school); + } _ => { #[cfg(debug_assertions)] println!("WARNING: Invalid environment item id '{}'", &map_object.id) diff --git a/src/map/fish_school.rs b/src/map/fish_school.rs new file mode 100644 index 0000000000..8c32e4f252 --- /dev/null +++ b/src/map/fish_school.rs @@ -0,0 +1,347 @@ +use core::Transform; + +use fishsticks::error::Result; +use hecs::{Entity, World}; +use macroquad::{ + prelude::{collections::storage, vec2, Color, Rect, Vec2}, + rand, +}; + +use crate::{ + player::Player, + utils::{ease::Ease, timer::Timer}, + Drawable, PhysicsBody, Resources, RigidBody, SpriteParams, +}; + +/// The texture of the fish school icon ( used in the editor to represent a school of fish ) +pub const FISH_SCHOOL_ICON_TEXTURE_ID: &str = "fish_school_icon"; + +/// List of fish textures +const FISH_TEXTURE_IDS: &[&str] = &["small_fish1", "small_fish2", "small_fish3"]; +/// The default and most-likely to ocurr number of fish in a school +const FISH_COUNT_BASE: u32 = 5; +/// The ammount greater or less than the base number of fish that may spawn +const FISH_COUNT_RANGE: u32 = 2; +/// The distance from the spawn point on each axis that the individual fish in the school will be +/// initially spawned within +const FISH_SPAWN_RANGE: f32 = 64.0; +/// The distance that the fish wish to stay within the center of their school +const TARGET_SCHOOL_SIZE: f32 = 100.0; + +/// Minimum draw order +const DRAW_ORDER_MIN: u32 = 0; +/// Maximum draw order +const DRAW_ORDER_MAX: u32 = 100; + +/// The color to debug draw school bounds +const GROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR: Color = Color { + r: 0.0, + g: 1.0, + b: 0.0, + a: 1.0, +}; +/// The color to debug draw school bounds when the school is not grouped +const UNGROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR: Color = Color { + r: 1.0, + g: 0.0, + b: 1.0, + a: 1.0, +}; + +pub struct FishSchool { + pub spawn_pos: Vec2, + pub fish_entities: Vec, +} + +pub struct Fish { + state: FishState, + state_timer: Timer, +} + +#[derive(Debug)] +pub enum FishState { + /// Moving to a location + Moving { from: Vec2, to: Vec2 }, +} + +pub fn spawn_fish_school(world: &mut World, spawn_position: Vec2) -> Result { + let rand_bool = || rand::gen_range(0u8, 2) == 0; + + let mut fish_count = FISH_COUNT_BASE as i32; + if rand_bool() { + let sign = if rand_bool() { -1 } else { 1 }; + for _ in 0..FISH_COUNT_RANGE { + if rand_bool() { + fish_count = fish_count.saturating_add(sign); + } + } + } + + let mut fish_school = FishSchool { + spawn_pos: spawn_position, + fish_entities: Vec::with_capacity(fish_count as usize), + }; + let fish_school_entity = world.reserve_entity(); + + let fish_spawn_min = spawn_position; + let fish_spawn_max = spawn_position + Vec2::splat(FISH_SPAWN_RANGE); + + for _ in 0..fish_count { + let spawn_point = vec2( + rand::gen_range(fish_spawn_min.x, fish_spawn_max.x), + rand::gen_range(fish_spawn_min.y, fish_spawn_max.y), + ); + + let texture_index = rand::gen_range(0, FISH_TEXTURE_IDS.len()); + let texture_id = FISH_TEXTURE_IDS[texture_index]; + + let fish_entity = world.spawn(( + Fish { + state: FishState::Moving { + from: spawn_point, + to: spawn_point, + }, + state_timer: Timer::new(rand::gen_range(0.2, 1.0)), + }, + Transform::from(spawn_point), + Drawable::new_sprite( + rand::gen_range(DRAW_ORDER_MIN, DRAW_ORDER_MAX + 1), + texture_id, + SpriteParams { + is_flipped_x: rand_bool(), + ..Default::default() + }, + ), + )); + + fish_school.fish_entities.push(fish_entity); + } + + world.insert_one(fish_school_entity, fish_school).unwrap(); + + Ok(fish_school_entity) +} + +pub fn update_fish_schools(world: &mut World) { + let mut schools = Vec::new(); + + for (_, school) in world.query::<&FishSchool>().iter() { + let school: &FishSchool = school; + + let school_info = if let Some(info) = get_school_info(world, &school) { + info + } else { + continue; + }; + + schools.push(school_info); + } + + for school in &schools { + let school: &SchoolInfo = school; + + let mut collider_rects = world + .query::<(&Transform, &PhysicsBody)>() + .with::() + .iter() + .map(|(_, (transform, body))| body.as_rect(transform.position)) + .collect::>(); + + collider_rects.extend( + world + .query::<(&Transform, &RigidBody)>() + .iter() + .map(|(_, (transform, body))| body.as_rect(transform.position)), + ); + + for fish_entity in &school.fish_entities { + let (mut fish, drawable, transform) = world + .query_one_mut::<(&mut Fish, &mut Drawable, &mut Transform)>(*fish_entity) + .unwrap(); + let sprite = drawable.get_sprite_mut().unwrap(); + let pos: &mut Vec2 = &mut transform.position; + let padding = 20.0; + let rect = Rect::new( + pos.x - padding / 2.0, + pos.y - padding / 2.0, + sprite.texture.width() + padding, + sprite.texture.height() + padding, + ); + + let mut collides_with = None; + for body in &collider_rects { + if rect.overlaps(body) { + collides_with = Some(body); + break; + } + } + + let rand_bool = |true_bias: u8| rand::gen_range(0u8, 2 + true_bias) > 0; + let rand_delay = |min, max| Timer::new(rand::gen_range(min, max)); + + let pick_next_move = || { + if !school.is_grouped { + let target_point = pos.lerp(school.center, rand::gen_range(0.1, 0.4)); + + ( + FishState::Moving { + from: *pos, + to: target_point, + }, + rand_delay(0.2, 0.7), + ) + } else if rand_bool(0) { + let target_point = vec2( + pos.x + rand::gen_range(-20.0, 20.0), + pos.y + rand::gen_range(-20.0, 20.0), + ); + ( + FishState::Moving { + from: *pos, + to: target_point, + }, + rand_delay(0.5, 1.5), + ) + } else { + let target_point = pos.lerp(school.spawn_pos, rand::gen_range(0.10, 0.25)); + ( + FishState::Moving { + from: *pos, + to: target_point, + }, + rand_delay(0.5, 1.5), + ) + } + }; + + fish.state_timer.tick_frame_time(); + + if let Some(collision_rect) = collides_with { + let collision_center = collision_rect.point() + collision_rect.size() / 2.0; + let diff = *pos - collision_center; + fish.state = FishState::Moving { + from: *pos, + to: *pos + diff.normalize() * rand::gen_range(30.0, 60.0), + }; + fish.state_timer = rand_delay(0.2, 0.6); + + // We tick the timer an extra time here to make sure that the fish gets moving + // immediately without waiting for an extra frame, because if we keep colliding we + // may just keep re-setting the timer and the fish get's stuck until it stops + // colliding. + fish.state_timer.tick_frame_time(); + } else if fish.state_timer.has_finished() { + let (state, timer) = pick_next_move(); + fish.state = state; + fish.state_timer = timer; + } + + match &fish.state { + FishState::Moving { from, to } => { + let lerp_progress = Ease { + ease_in: false, + ease_out: true, + function: crate::utils::ease::EaseFunction::Sinusoidial, + progress: fish.state_timer.progress(), + } + .output(); + + sprite.is_flipped_x = from.x > to.x; + + *pos = from.lerp(*to, lerp_progress); + } + } + } + } +} + +pub fn debug_draw_fish_schools(world: &mut World) { + for (_, school) in world.query::<&FishSchool>().iter() { + let school: &FishSchool = school; + let school = if let Some(info) = get_school_info(world, school) { + info + } else { + continue; + }; + + macroquad::shapes::draw_rectangle_lines( + school.bounds_rect.x, + school.bounds_rect.y, + school.bounds_rect.w, + school.bounds_rect.h, + 1.0, + if school.is_grouped { + GROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR + } else { + UNGROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR + }, + ); + + macroquad::shapes::draw_circle_lines( + school.center.x, + school.center.y, + 2.0, + 1.0, + if school.is_grouped { + GROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR + } else { + UNGROUPED_SCHOOL_BOUNDS_DEBUG_DRAW_COLOR + }, + ); + } +} + +#[derive(Clone)] +struct SchoolInfo { + spawn_pos: Vec2, + center: Vec2, + bounds_rect: Rect, + is_grouped: bool, + fish_entities: Vec, +} + +fn get_school_info(world: &World, school: &FishSchool) -> Option { + let resources = storage::get::(); + let fish_sprite = resources.textures.get(FISH_TEXTURE_IDS[0]).unwrap(); + let fish_size = fish_sprite.meta.frame_size.unwrap(); + + let fish_transforms = school + .fish_entities + .iter() + .map(|&x| world.get::(x).unwrap()) + .collect::>(); + + if fish_transforms.is_empty() { + return None; + } + + let mut school_bounds_min = fish_transforms[0].position; + let mut school_bounds_max = fish_transforms[0].position; + + for transform in &fish_transforms { + let pos: &Vec2 = &transform.position; + + school_bounds_min.x = school_bounds_min.x.min(pos.x); + school_bounds_min.y = school_bounds_min.y.min(pos.y); + school_bounds_max.x = school_bounds_max.x.max(pos.x + fish_size.x); + school_bounds_max.y = school_bounds_max.y.max(pos.y + fish_size.y); + } + let bounds_rect = Rect::new( + school_bounds_min.x, + school_bounds_min.y, + school_bounds_max.x - school_bounds_min.x, + school_bounds_max.y - school_bounds_min.y, + ); + + let size = school_bounds_max - school_bounds_min; + let center = school_bounds_min + size / 2.0; + let is_grouped = size.x.max(size.y) < TARGET_SCHOOL_SIZE; + + Some(SchoolInfo { + spawn_pos: school.spawn_pos, + center, + bounds_rect, + is_grouped, + fish_entities: school.fish_entities.clone(), + }) +} diff --git a/src/map/mod.rs b/src/map/mod.rs index 648da58fc9..687d20339c 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -6,10 +6,12 @@ use serde::{Deserialize, Serialize}; mod crab; mod decoration; +mod fish_school; mod sproinger; pub use crab::*; pub use decoration::*; +pub use fish_school::*; pub use sproinger::*; use core::math::URect; diff --git a/src/utils/ease.rs b/src/utils/ease.rs new file mode 100644 index 0000000000..6506cbf876 --- /dev/null +++ b/src/utils/ease.rs @@ -0,0 +1,68 @@ +use std::f32::consts::PI; + +/// Simple easing calculator +pub struct Ease { + pub ease_in: bool, + pub ease_out: bool, + pub function: EaseFunction, + pub progress: f32, +} + +pub enum EaseFunction { + Quadratic, + Cubic, + Sinusoidial, +} + +impl Default for Ease { + fn default() -> Self { + Self { + ease_in: true, + ease_out: true, + function: EaseFunction::Quadratic, + progress: 0.0, + } + } +} + +impl Ease { + pub fn output(&self) -> f32 { + let mut k = self.progress; + + // Reference for easing functions: + // https://echarts.apache.org/examples/en/editor.html?c=line-easing&lang=ts + // + // TODO: Add tests to make sure easings are correct + match (&self.function, self.ease_in, self.ease_out) { + (EaseFunction::Quadratic, true, true) => { + k *= 2.0; + if k < 1.0 { + 0.5 * k * k + } else { + k -= 1.0; + -0.5 * (k * (k - 2.0) - 1.0) + } + } + (EaseFunction::Quadratic, true, false) => k * k, + (EaseFunction::Quadratic, false, true) => k * (2.0 - k), + (EaseFunction::Cubic, true, true) => { + k *= 2.0; + if k < 1.0 { + 0.5 * k * k * k + } else { + k -= 2.0; + 0.5 * (k * k * k + 2.0) + } + } + (EaseFunction::Cubic, true, false) => k * k * k, + (EaseFunction::Cubic, false, true) => { + k -= 1.0; + k * k * k + 1.0 + } + (EaseFunction::Sinusoidial, true, true) => 0.5 * (1.0 - f32::cos(PI * k)), + (EaseFunction::Sinusoidial, true, false) => 1.0 - f32::cos((k * PI) / 2.0), + (EaseFunction::Sinusoidial, false, true) => f32::sin((k * PI) / 2.0), + (_, false, false) => k, + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 1227065ce2..e5224f4c09 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1 +1,2 @@ +pub mod ease; pub mod timer; diff --git a/src/utils/timer.rs b/src/utils/timer.rs index 6f0928984a..a1c4977f74 100644 --- a/src/utils/timer.rs +++ b/src/utils/timer.rs @@ -24,6 +24,11 @@ impl Timer { self.elapsed } + /// Return the percentage completion of the timer as a number between 0 and 1 + pub fn progress(&self) -> f32 { + self.elapsed / self.duration + } + /// Get whether or not the timer has finished pub fn has_finished(&self) -> bool { self.elapsed > self.duration From 2c8f3333e285538eebabd1aa5167fed485504f10 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 14 Apr 2022 15:42:25 -0500 Subject: [PATCH 2/3] Update Crab Sprite - Add crab animations --- assets/textures.json | 6 ++--- assets/textures/items/Crab(15x8).png | Bin 215 -> 0 bytes assets/textures/items/Crab(17x12).png | Bin 0 -> 12400 bytes src/editor/mod.rs | 34 ++++++-------------------- src/map/crab.rs | 33 +++++++++++++++++++++---- 5 files changed, 39 insertions(+), 34 deletions(-) delete mode 100644 assets/textures/items/Crab(15x8).png create mode 100644 assets/textures/items/Crab(17x12).png diff --git a/assets/textures.json b/assets/textures.json index dbb56dec86..8de778f5b9 100644 --- a/assets/textures.json +++ b/assets/textures.json @@ -429,11 +429,11 @@ }, { "id": "crab", - "path": "textures/items/Crab(15x8).png", + "path": "textures/items/Crab(17x12).png", "type": "spritesheet", "sprite_size": { - "x": 15, - "y": 8 + "x": 17, + "y": 12 } }, { diff --git a/assets/textures/items/Crab(15x8).png b/assets/textures/items/Crab(15x8).png deleted file mode 100644 index 9972446f129bbea1ce8090ef218a3a3383c197e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmV;|04V>7P)$RGxJT9lLO_?+8Lj0)$>dm);SS-b8wnjuh$A1O%iDh*Uv} zNKruqDPQoMd+#~#_l|FjJHGe*ca!X7@3rQ9=A6%Z*4o))?^s=J6;dJwA^-qDs-~)> zkNIW8Y$ODDm~Z?w*9ZWB8R2heiq?nufZRM>ZBb505ZccT2}1g!Yykk@g_5UR?i{V@ zkym|jqCoRZ?3?w>Rj0q05Xp)!0+wUu;<+BZuFzbKV+W+ZzdCs}cz)wb-Fvy;(7^?A z|ME5M(*vpUAE)B`K6dLDL05iPmu~}um*-C}d%hd4+W7`KA22Qse&7F&HU4C*=;)Ke zUS~Vw%GHEyja9J4cBlMA%#m*=-RFbIu;9zpkCK(==cCo>wFa37Ob;uLKg`TZHhu5< zI~{w;vD;*R^(YQjnn?#K!GauV*vNx^sFZ%dJ*#7tJw#k%_^KOV%(1!{hH z*x9!wdr?CX6#IVp$IB~^^C1QkS%1BAQDIqwtJ7_j&jwfYlTT*0&bm0xhfFWePe;C= zDDYqWRQ%cT>dJqsV@2ii*Z2B1RF~FIje#+<<3)(@BWB^#HwVQsrM@g*p`T^(JXg|B zdCzsE_)jXo8a*FYv*fD?J`}a|%%x_bTk=?9dU-IuQ~Gj1dJu&-w^YB84PvxQ?X8}O zs+gqq?rv}@BybCf=zk_&zJvF3edJQVEmiua=4Mo@P>;)?XKd0UOB0PtA$Eqw`NN9& zwBrXM`-2oXrs9O`NZ6Edrv(|Maz80tGK#m)yWg9k^n=ej}Z@k!C zt~!0n(^>b>Ho;Egv?YQnhhuooopq~-eO;L+Kflw%w(`;B9nayLsR||>rie@ezjb0?bT(NbIZQp!5KOIR_L5g09U2n1Y zOdt$yb3S21SOjNp`^S~ZLH8oeEHwG|GPjmfK;)J$W*<7qKYOrAVArHK3xSm>gx|mK z&1lD9Wx{Qj!dBBijcUrzoAm54574Rh|CsK8E!k^|)8Vr$ncoFh;k>-Ffi%t|skfWb zwObkkrnWcv7p}fL^{`p_?qp(OB|PVy!_{IxI{N82+k6uWU<6`wrtD_%s*=SDSHs1A z9Bod~zdupd5_!34{>;yau6IK9yCwHM0##>I<9J&f>EQk;1)U4{67J`yr@lbbnsM5`8gr&wOIcTo?OfHu)Op?JT>)owUF zMpBm1h}R?K7e97uE~lghzQyxeuWtt1ieE(Z0i>pOMn?mw=&|V1O#OCv{fp6azygel zQaw&r^DNY3)3~7+a+VJ#*jeyXw#qIuw^o{3Y>o8c%Wjjm9Z9rw=;%R8)U+FmAO$MC z`41E?@0-WElrTR}OAD~dk7Y5`Xj1BpAt;qDp_2e z6mF&xk6eD^Q>5U%`ng**PbA~`)V>)sR(-HzM1&LG%phD$*_@DCs9<;}?ui3@##1Dj z_Or};oVD1Qyh}c>cMnkf3l5b&{w45PBD)_H@;QCK24f3I=^TL7w1>jk0;T>~3v-zz zA)lQy(mQJ3*S45^An={h#P^UI9dK2yu*0V91}p)f`{rl)zZCBiuEsvn7?hr+uO9V2 zzXy6!Lrl~C9IHZYuAn>|D@vxo>Bl@;!q+!!=l;CM`ufr>vnLe>qCXcuxKIm*V8!H- z)4h|G3Q21i_SRQV`7Hg+N6r3Nh&UE6H56OlV}RRl3d_OyQ($-pf*kO;cU#UyZY&X} zDb$8OlF>I|O&+g{K*^&&vvxwuVcD+Zq zUDbG-Bimedz1z!kI7sXBYqo)uEdJRju2FdA$hm9a#7n@3c=@!cIHuyCfJrR*uP1K`Gb`THDeU{+TY+buvAH+X zr7O#9yOsX-G(Mg(>{GskLq?Y+`z#h~ApzxLD#_Q5Oy5w1KlI&XK<25tA6czWWwvdJ zoNJR}e`E{rq1%^gKY&bTb(o~QxODipx9IMusVtf<#s>hh69`jX!d_yRyFE`g`}Fgo z34Z`~KP;q$VwJgH!Ii`nq+HL?5vZv$NW#EM8^tjqCK(1oL2+yG4N{46{h@9QEw04K z3~R#4#L1e#{6+5PN)F}y);pi649Hu_p0*p1KPTHQ__*n}Kx!H>0_PHo44PPMk&U3% z+=|PuMK80ir#!;;ugiM6X+A`7G)01KUNkMdGtLc+gW6?3lIVe10$Og_aG2^{1g-;R`zJ7A0CkqI^MJUbkOg8sqtG zIE8L=5uc6u%|xP*<{irDrnSxcNuBcR zh=#jG7M5I5Vw1&CDi@kHUag2nTqr_4dr&6Cgo1x#p7O{giD{dk-`AyXjVwO0z~Z== zVR~PLzBfE!=sU-LXm#C~1n~lS@HKMo9HzpZZ&bZ;^qdalRxP6Zb_K6VZ(Akc1MkH%m|2 zbhD`w)=Oos=WND}KPkL0e?jd;u@Mk+I;j$K`xsvb)d|E`mOb!|u;$DnhIQY-BCGCs zOMHlLgFfm>Y4A4`7ZH1gvn5$PAfG#7Jto@!skk;wRDu%6#$nP0{4=CP-j))?mU~-6 zAVdSq%ACibkd~5;YqQFOdb3327Cj4YQYn4rb6HC+dF%TP3dXg!4+XjP)Y!E%l^2~M zQLJ(x9#aHWaq%%405;7LYn`@G7BUvH6^#ZKN7^s8JWQ`$K{uZ-f|W+z1d*_o=Ey1= zfRDev>T{Z5atbhDxj|!g8krt#o~Y$6#HGUHRZS|tA}ZNmF!-52EaBo=Y^iqWy?p;W zma6BRq226dmB4g-CT7l-i!5CnTWgJle5oR#xNr^zlWk)ZV^-|J@aCkbh4+x;IbNk~ z{=#{`gRUJbe23F^X1sJSi%vd_04J=KSIqY#;maeuL)hjaI4Y*FE+D5|x|_`8RR&YJ z4YRK`Qq74P=k-mR;dOoN+Hhf|wlg5ro<#yE^$lUD@1O=YRIdf@%2u^wOBS zqajD#*7Pwv{iXnJ+w_l$@mC?1EiA}W)lZjI(W$>KDn60Y6udiRH{Ir=AFw`SeWI&p z@94*;4Q_90913eYGBsIflHmJpSKU9P&{hl!V_5u>UGts-&%?(g)q7N`Bup<8J0b#q zz;X$T(ESOeXx95JZ@TOcFD%s;9YXQX?jFNTtR~TF%9N8cTO^8mR@>2>j*n!(I+x_~ z8|V^lB;H=K{Gudf)=K$UXY1Om|B`9Sy`st<_PW&mBHcp=mXOUFhcp5C#m!k_RsrIx zr%9E%F?Bq!lu2IaP_M3!kLfu{w&aMcY$$}o>^C4u8n9atiX%Eed!V9}cj(@rs0BE4-Cu1tCx_v(rBZYX)Up)O)rH))+?LM^rChO;stD` zq`3J$Hf~K3gG?R959EU8b2mqyuf3I5E*0%@Q|uHf$#HheNE_JLJi4hqRi0>3EJ zy)oFlNwmxb%6FGqmHoQrEh=}>jrb82yJVBG?PaN`u_{j99x8HtMQ+ve5 z0E>7cf1z?*oSWx68@wo5*B90INAIlrv7-}(eeB4prBiSyiNQUJmUQcj+KeVQNpO$& zLH#8qQjf^Ll@WtrBc%OQ1?HWf#Y2wG<@=7u?bb}vq(N@&*k3ytyYaNA^e-#}kqS)RrZ5v+8dqb$CCi!RR8|8~2ciNXVsEHA% zXS3MgsYKZb*0rownb5B`K0{u4_V#OjCRU8MfHj4;I%$V!e^R)ss!BHAEp!Pf+veTO zj>b2*iI<*YH_f3(<1a~v|q>@=1h!#R*X6n<~V-qqA6IoN4 z6fblWW5(r35_1nDhv2O7><_@ncKKM2Lri|MXPPN--zcdG@=Ls|qiXe|AK&T*hKlx* ztxlK_RxdSTh4c7v#*9^uF`7M1^2%_8{oTq2sAyJV2i9(&b-hR!uf zovNzf-N*ZhiELCx(c$_R@4?+f#{jBu9PMM8I@p2}?{?{9O-0@Aon9P&azX&EKv5tT zV}0$|G|h~GzlppZwjurdIC+O)k;Fg=8+>-Q81MT*ORpDr2Iom^h=b!rddx;Mbd(}u za@9**HD#AZb4oM!&Teyb&zmEa(h5i?d|>yBEb}v4(=z0T%(tl($!i(DRe_kXCNucc z%hHDKl`9hCpa~z)qP}swIZrO>@kKbwadq6=eBBNFh@2rpS=4!NM<^XdzI*lyUX8sd z@UZ=nrjB20$6fUs=CGfcx3EH-QF3iYL6KFWZ(#3tX?(jJ8EP(Loi&OjFw+bgXVD z;`!VF;blY^$7mZm087&yW!N~d*GnIAD5Hcd^V7Vk)X(^IP+#0Ca(YK&pwLLPGzKfZ zKSg+0L~fGHaKL&!aEyVU)v)Atn7bk|oSPY6QO{5pTX1I6V5$a>bhSW1ZKgee91&76 zAiIhlj$zzU&&;Ns#$7Wm5zceINfXi=OA1}W_8Rx#cZq+MKlG8nJl-NKkF}p^q5S(o zhq5RoX=*RfQejOv;q@RUSZ-S;M z?`YHeP$qtBu`ewW@iBXP5wEFeI;VTfStX<}hNOBhA2b|8=9ky#PZDD6ke(HKYk^Tu z{}R_S``{s=B{ctuxbBdK5n9SkfpU^*64}8H+BxIBV_2yS^p8@MzawCnb=%5KhI% zmEKRdpMBeJKV?neBzht+L~hTeMyV384SXBwB4c$o)=w(-TeHj3t*m6q(1dDECP7z? zggEUBMH*jcoWqEGMga%wa1Og63nSkOeKe(c4-+#Bz0Gv0Lzl_wmEhm*EbD8PrKwV4`P1V7@`;(B z^;JdQmB@$@XAds;)`{wQXupFOQjK8#l2@_Q`P{8@j`%j|1%S49T=BOj(C0ckq~C=qEQO+!XkPn#X7bl zeA$Ty%1@u{geGva%&V@l>iPIp+|cyIx8Z)O8PI!C;WWY0>E$&Mv(`qp5ZuSLXA8`n z77TrgBSNH06ny%G^a9U2K!l@|dj!|0ngGu|GMR{f7mY^<@Iw?mNk0h~8&yebyUn>& zMLRvb`3=uJJn435S~@T?O5`2o17YT$PDC*;(<4?7HyV{bJs06n=^F)I75TW(VR!P9 zhYkQA?W+@-PI>)$n^sTf36NoQAEv=qBAg?VB**S33DZ$!HQ|5co8;hU*slm~BnnLb zl=@lv+jg5#q_|f{TS^(Z6KrPWM9jG{ z7XyB{Ps}hg>?D_Ev^#CFJNr1jjOe+V&-3-NE)gqSF3hD`|4W_LR2Hir#cwV%%UyOe zqaAK+%5$?*;ERIert%uLHTFLk5Sr3IQ#t?<(IyV8>Nn={ zYiZEb;m!#!G*1q1g`|IXA@_Z^hKpG}B?oq1ZiZFyXnEmTyU^TH1rQ5~C-&@ZCZ^mr z$ZTAs5mL^QrSgmVm>)Gu?5M$G1JC%W0Pf?zdga(KP}bWcHm zF|gQ*`L(iFDXe*He4w#tHd&Y&-QODE{3fY=>dG2!!W0^nftPQfqs98r6J2N08IVX; z&~abYN6T4%HXh9*@ zAuzMAW7W51cL|DHNEOESsEpRT-*1VL&>?D;dSa>|a<|ejvf{iToOpu(#LG?7LE?>N zO;7DOk)+Cozmm!+`s$&m0)+`;WXNQoJ|>aS_=TY#I~m?wFK1shW$R+KdAACe z+J}XPSv!_9mG?DU)4Q5#TU}c-y^I5C-4%kZ?ljlt!XWgI0*q*EI9t*c< z#T}N!_A9>FkmlduyKm1F`%{1;`Q>ZXoA@&&w?DTGl%&Wo`l+_E|NJTvXEJNn7?bj> zg^g)Ek)TAfQ4ObC=*YTUvUJ9)u5)LPdlK?R+B^EtTbHG71301RIyEjqpMQ!^(bTF<%{jwE`a86~(V{9JW~ zeIyt8eyv*OV@C{$tq6U$+Sdm)!OL!R`&KFMa@Xx@R@O;Y5BP>Jx(6q_s4e#s@7VJd z%dPw%mQ+hfjYV6LMJ?xYQt) zl?#`&{7{b+R@%P%lw;Fjr=DQE4tT>XBBnogbQQ{;km*19mGIfwpzOBkmnyv)e^hn) z94v-|_Hx>R0`YjB84B>n#<|3;R*_&L=Rzk~!&f{TGfQtZG=rPQKe;LC{xX1!yZj=Z zJOOA0#;~KTK5oGF+YD(eWgbAI25Z_%4fMa^m@hl43-7d4R(zXWV3n2MD#bz%S*iuM z-MJl#x&cM)=GZ-TKS^s1nETgryAIsr?6 z#&-u#0(7Y!%2pYqeF^eurYFEt%&|xh1#H8t@82PQF>2f=IjNyJ9dgEPo~SaQes+Jl z`gUQMh_vhN6&bNt=t~x+^P^gk>FHOv@btDED!jL^Tf7e4qg7ZlWe?8aj68Fj#U@YV zNwKt?7XV;^j?_eSjXQn0NwQbF1EaxXb1Wsi1mw*IQ=LAiD&B^Xw23^LKxB0#7dAk*>_w;79%nFR~vZE^A zJE6ONjNyy6@WT57FKUj+_j}T@1w~QhK`i%XLAh*sEtO=vqP^#-IKvC$-%ZG+DE1|| zrcjDQa|-XYA;+h&80v!~a>N*f-|Z{RH%+|uL{YF2x@nrF~@Pml>4Yf+RrZ8^gz z*C#>c1B_$7?4;<%_lvs`-l;2jY6g|i0L|)@(T#0y)i_(NL!ssvp5C1#A{^1SbfbD4 z!|`U=ZXat~h)gEub=R|_a^xTJ~0xyN+(opQ4OP!{1np@J3xo)b- zy(x99RL}O=#paBU;*Yk}twm6w!G>f%w-qk}uHn%z0>&F+GB@B1f{BPaSL}YEL`@H5k8%rC6fiN{2_k-#gB=^CVKe{KDj zWsaTS+y&$;E$j^-PfltC-N&{J%3W?mkNxV`Gft=e==sq-oL}{P$m{(l@iETm3n^g- zgz)!%J)44=*B*2YFA6AiC+eR)`>kK#(A>J0#Z z%oBxqB*9cm6AE{A=7%9%ZIJxF&Tbg(002_5zHTtMBN7d=LE52Qq}dMIU$KEu2x&GG zQ7y2RnIXE!aaf5N+X{>cJ{4*_48n}8rcSisp?;IAH@Xk~8<$e#)Qw;rB` zm?t{~^pT#fULJ6yvNzHN&Hh&i1pJ@=ZeAWvzso_u1&~fiXN;*QCaU1yLaL}~>HgE> zngTnNv)gYk4B3CPM5Ao~Mb_VPyYBg2&R-M3xc?LPZ`S{){kJj3N=pl>ksVHh032bO?A_(YK65_~Y2padUW5Md)EBqAsX7Pb8gl$wht z8s-8=UPEEP`B4}gxG2QNRtO=;2a~YDKuCy-@kxLowtS+tUtV4y_A5jKM2NO3+J5eY#)5g~{OA0`W1J~%=cE`kA-5R*XuhC;xh_gp=k zVVL1WIm7Ib0&XsLzdNo8hsx`!NwW#@ga6f{>jXpFVjQH|G*K>IzW?elL^&f3(6DPZ z1;s?cfFmEK{cOZ=4A6;;Jn2Q|}Grt9{=P3e)hW))C_1_GdEes)q6c&c?iAx|Q_(a5Q z#Q1EGLSQ}^L_$IkApsM!5f=YDil?hB+6U%=l()lFjHwDEq~BG6xPMd1^LJ|>d*n4= zV9Xo`i|`4G843zQMa3~6KCmbh3}zGf|1I_J;r_c45jGI84FZAWLkJ2ZFwzzjkSCV&Y{ON;-l5Hl<_xl z$jKp+M5l#Z}+dFFAm&al+us<=We8#diaFRi^dKM1#CV0o_eZ{3CnRLhTGS zdw|u6GLO5#Jy>F8Gc9}b%syTMkwvFZ!VllHJlYlU&TJnciu_VkUX`a1LI3LyxFOAg9Zpy!W1PiJ#9!%%=xxzl8$8)u0l_0^C4Nz0o KR;p334*Ne?)I)>- literal 0 HcmV?d00001 diff --git a/src/editor/mod.rs b/src/editor/mod.rs index ef98e8f248..291730597f 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -1454,9 +1454,15 @@ impl Node for Editor { } } MapObjectKind::Environment => match object.id.as_str() { - "sproinger" => { + "sproinger" | "crab" | "fish_school" => { + let texture_id = match object.id.as_str() { + "sproinger" => "sproinger", + "crab" => CRAB_TEXTURE_ID, + "fish_school" => FISH_SCHOOL_ICON_TEXTURE_ID, + _ => unreachable!(), + }; let texture_res = - resources.textures.get("sproinger").unwrap(); + resources.textures.get(texture_id).unwrap(); let frame_size = texture_res.meta.frame_size.unwrap_or_else(|| { @@ -1481,30 +1487,6 @@ impl Node for Editor { }, ); } - "crab" => { - let texture_res = - resources.textures.get(CRAB_TEXTURE_ID).unwrap(); - - draw_texture( - texture_res.texture, - object_position.x, - object_position.y, - color::WHITE, - ); - } - "fish_school" => { - let texture_res = resources - .textures - .get(FISH_SCHOOL_ICON_TEXTURE_ID) - .unwrap(); - - draw_texture( - texture_res.texture, - object_position.x, - object_position.y, - color::WHITE, - ); - } _ => { label = Some("INVALID OBJECT ID".to_string()); } diff --git a/src/map/crab.rs b/src/map/crab.rs index b26d13607a..4f9abf20f9 100644 --- a/src/map/crab.rs +++ b/src/map/crab.rs @@ -8,8 +8,8 @@ use macroquad::{ }; use crate::{ - player::Player, utils::timer::Timer, CollisionWorld, Drawable, PhysicsBody, PhysicsBodyParams, - Resources, + player::Player, utils::timer::Timer, Animation, CollisionWorld, Drawable, PhysicsBody, + PhysicsBodyParams, Resources, }; pub const CRAB_TEXTURE_ID: &str = "crab"; @@ -69,6 +69,15 @@ pub fn spawn_crab(world: &mut World, spawn_position: Vec2) -> Result { size.y as i32, ); + let crab_animations = &[Animation { + id: "idle".to_string(), + row: 0, + frames: 2, + fps: 2, + tweens: Default::default(), + is_looping: true, + }]; + Ok(world.spawn(( Crab { spawn_position, @@ -76,7 +85,12 @@ pub fn spawn_crab(world: &mut World, spawn_position: Vec2) -> Result { state_timer: Timer::new(1.0), }, Transform::from(spawn_position), - Drawable::new_sprite(DRAW_ORDER, CRAB_TEXTURE_ID, Default::default()), + Drawable::new_animated_sprite( + DRAW_ORDER, + CRAB_TEXTURE_ID, + crab_animations, + Default::default(), + ), PhysicsBody::new( actor, None, @@ -169,15 +183,24 @@ pub fn update_crabs(world: &mut World) { } // Apply any component modifications for the current state + let sprite = drawable.get_animated_sprite_mut().unwrap(); match &crab.state { - CrabState::Paused => body.velocity.x = 0.0, + CrabState::Paused => { + sprite.is_playing = true; + + body.velocity.x = 0.0; + } CrabState::Walking { left } => { - drawable.get_sprite_mut().unwrap().is_flipped_x = *left; + sprite.is_flipped_x = *left; + sprite.is_playing = false; + let direction = if *left { -1.0 } else { 1.0 }; let speed = direction * WALK_SPEED; body.velocity.x = speed; } CrabState::Running { scared_of } => { + sprite.is_playing = true; + let scary_pos = world.get::(*scared_of).unwrap().position; let direction = (pos.x - scary_pos.x).signum(); From 08d608e50360052af3519641621bbae2496fec4b Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 14 Apr 2022 17:12:55 -0500 Subject: [PATCH 3/3] Update Fish School Sprites --- assets/textures.json | 45 ++++++++++++++++++ .../items/ArabianAngelfish(19x12).png | Bin 0 -> 10707 bytes .../items/BandedButterflyFish(19x11).png | Bin 0 -> 9265 bytes .../items/BlueGreenChromis(22x11).png | Bin 0 -> 9339 bytes assets/textures/items/BlueTang(19x9).png | Bin 0 -> 9572 bytes .../textures/items/FishSchoolIcon(64x64).png | Bin 603 -> 11293 bytes assets/textures/items/RoyalGramma(25x11).png | Bin 0 -> 9397 bytes assets/textures/items/SmallFish1(13x9).png | Bin 171 -> 202 bytes assets/textures/items/SmallFish2(13x9).png | Bin 163 -> 207 bytes assets/textures/items/SmallFish3(13x9).png | Bin 170 -> 216 bytes src/map/fish_school.rs | 43 +++++++++++++---- 11 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 assets/textures/items/ArabianAngelfish(19x12).png create mode 100644 assets/textures/items/BandedButterflyFish(19x11).png create mode 100644 assets/textures/items/BlueGreenChromis(22x11).png create mode 100644 assets/textures/items/BlueTang(19x9).png create mode 100644 assets/textures/items/RoyalGramma(25x11).png diff --git a/assets/textures.json b/assets/textures.json index 8de778f5b9..d4493e961e 100644 --- a/assets/textures.json +++ b/assets/textures.json @@ -436,6 +436,51 @@ "y": 12 } }, + { + "id": "blue_tang", + "path": "textures/items/BlueTang(19x9).png", + "type": "spritesheet", + "sprite_size": { + "x": 19, + "y": 9 + } + }, + { + "id": "royal_gramma", + "path": "textures/items/RoyalGramma(25x11).png", + "type": "spritesheet", + "sprite_size": { + "x": 25, + "y": 11 + } + }, + { + "id": "arabian_angelfish", + "path": "textures/items/ArabianAngelfish(19x12).png", + "type": "spritesheet", + "sprite_size": { + "x": 19, + "y": 12 + } + }, + { + "id": "blue_green_chromis", + "path": "textures/items/BlueGreenChromis(22x11).png", + "type": "spritesheet", + "sprite_size": { + "x": 22, + "y": 11 + } + }, + { + "id": "banded_butterfly_fish", + "path": "textures/items/BandedButterflyFish(19x11).png", + "type": "spritesheet", + "sprite_size": { + "x": 19, + "y": 11 + } + }, { "id": "small_fish1", "path": "textures/items/SmallFish1(13x9).png", diff --git a/assets/textures/items/ArabianAngelfish(19x12).png b/assets/textures/items/ArabianAngelfish(19x12).png new file mode 100644 index 0000000000000000000000000000000000000000..73f541293a01adec4bd803f67954a8924f93eb07 GIT binary patch literal 10707 zcmeHtcT`i`_HO9CNmtN-N>Ks{fdB!dmms|(Afy2iDUwhH=^#}=M5IYasx%c4rFW!B z6$PYAN06?*py!@@&U<&fG46Q3_uolIlAX2Y{N|kB{Px<}dnZC)SA&7}EG+;4U_fZ9 z8WKOXi7$F;O5%HGzoiBMz{&1oY)&vldIDYDT8FJlOHB9A8nhLmL|DRCX0<1Djhob2D~+{`7qMbE_a}IK%Lr zr3+}QV0Y;K%sD0-|HWgOu&?*-{Y?CJXnpc+N$=o?+N{Qt=ZC9L<^68{{JwKAM`~k3 zIX&`JbXdXj!OoaX^yccZ3+K^CprhK+J%3S&Yn!!f$VSXlS7 z^2PUw58vyzOZ%5xwryVRbTq^iZFGOf`wVqKsID!YSXhisCsNtaJw-d$gTF%D{1lc> ztVwCVy;)ycl07-d@plYW7+Fi(dgXuPaN~x(rH{d36|~{ij}Fg<7a3u`rn{D_ss1+; z{8!D7x4%7j+Q1q4?Ul{^g?&AR>Du&u&o5(7`&oB(dcyoy#@|eCzP9&(XyquZR~2r8 z-cE1Bw``{9WUf0l9atVtO+Dxf5ALQYgDpSxEg45=w@D?{%-xsD*k6sj8Y=jRkWew2 zXxhEWByYKb!%DtczBq-cT}tOQFX6m$xnT1}xwvz2S?RuWU%Kafp0HcR0qV;IU%8*V z3`aF)bIdunp1g%?$DoFmE9l*IpL%oiM(i66A8{NUUpyhPw$-Cr-AS65n4#WTJyX@* zQ2uCI-Coq}@F;ZF;TTV%)mnPhF+wk&BCE{`9o1x5$t9foKC@}aNE9~|XzutyMEp_j zvc=b2%N>rW&Fe;fLu36&b+`e(N8QEeyhL##?Y$CduCtP3hK^1nMPoNLdP=K5+^7-= z<9&d=YFhf_iRG)$6H#U^&KpyHyTed=tGlbCZ}zWI?(r}x@p`gNqH-Bz8(%BJsiJSc1H zAOG=Vo2iaN!TP#O!LIW0pya(UDvU0%3a)-n}R_vZDk?-KR3?1&w8&O2pQ4l0%RoUJ_sPRtjlveuKQ zN=-)NEALElXjv4eHTM*BP#pKk^>zqpv@PU+(#wN6ii%cj^o5hgKIHy@xT~w8B4tUg zUMx7wFXh9|4>tdt+vP`ArDsy(J;$4Bf(-M?Gm%`7xls2-%40q|md?#VqTcT-b)sua z*qXHV(F$}@XNgqrt?k2S8iNZA-Wstm_Vb*oPH~jWx-Vqm1MXd_DSmUUM_9xC+dyjV z`O)`0Z};J;+c>Lgl^5?>OA&JcC0@rb&BI6Dz)&!BaXs0I!NYbK=s8SxS+bPxO=sWN zb7d|=FJf!7qoTu~r`o^v+j4QPvEP-9|2(8O6)v0Y@WN)M7nj0;IBxvFj%D8QGQ$|cQ z!MpZ4{Z++g^8HXT($&lnH{8IZUZJVnJtg+QN6_#+{RcGRG2NHS`KXNnZPe^7GOw(S zknQ902|jl6&Q9WbQoDY;D;6+}?DwXq4T`+r!?(LPnD9&I`4j{K7eyXavIUHHkcUnP6?)&zo#=Qz82)<(o-6O2hXv6KI^kp0QC) z9xi*PpTe^#wWK^Sr01TOSs^62zJ+uv%+$1}GMMIIYWX;@c`~oggC@qOCD~%UlZ5ri^=dQt)zEg%TN81e4(3#neEv}?oW@RC~7(~ z_40Ry252HZv%Jn8_-ILa&~eom5k=OZ zMj9xDb{BviahX~7vhjDwwJc2uLjy3;HR$jhlFM_nQWxW_tb)!DL~4KO7)~6mX~8dF zGWt+iL%04y4QQ(5Rc!GvzznR|!yQXLox5lVc%E=b$&v}614K#z?-%iF2Pg4D zLSwJr*ZY(znMp;*OO+bisvn8x8ja3A0KlSId|8InLW|vRC8WsYX1f6^ykn^tB{EH<)%mop_TD9up zoNb2Y!PcX|=^0XLt)E=71}xcageET9NQVn!(=}SOUD|%_qT~$c>su2Q=ttXP#w|QE zjQvyP1fC9ReB>%N6maga?WK*F!`SDu1*4EJ+FdenYzVew2sPoUY5#Z z9y9JU28D5Cea;6adDd_oBn#$LAJ~~%Kv=WMtopREXKXz$_IPZCKtXnmxUCo+^Ff|-l-&QMs`Nh030jZ%pFgof%d7r$9hJoG(*k3yt!*l zC9@dha=>=W_r{6da8F*PN3QC&Wm_k4djnJ37x|OEV7u$}I09-(6#CUAXqXIwl^bXy zUOyyrE*mDSP=~4)UwZDBgjPkqPF}qIEyloB;~+2hMKp^SGmfxKFq7>=p1^|e=iI%$PJF${l&ab*C1D2N zE}n}(sPqijPf!O9mRer(l^?H@=HM7(3oxgyA{688`(tWgm5fr5e8xQFqUeBVXsDh# zNMJXuTT!8tB_S*dgj4g-D6wiQDq9;9{-X?Be1Nzuzcc*2KEl=zuHZkMml@jgC za|WThF);7KkIc{puKt|yj-JAnPMWSZm~$GC^-!~QK%90BW5C`;cu74waFv%sqjG^K zS~e!Tj2`>&e(;Of=P=OwnMC`WauVYO0s3HFruN`C6$*;+pui^^4(8!88_kn*k@Z8C zLQyjzSBvAW=Z+^vJIhvU%h^$HbDYqAeC77+sg4{KS#v$yCR-7uq2Ga8An<*TB2YV!=mJ<(RClL}7f8j`8;$$1+&UGk8PVqf^l%nZL3`A#B=>50lWlzYuJ zTxa5o>n0H?0-rY>jIrlywaAhy`8AhCH0>`k0k?1!>r{`G4{bYHY}P0F7%1>3BV5ws zBk3a2S^dddz&F3FI^)=auFLe*|`&KvO(!e0X78Jqdwz-V0iJ@9v9o&e|cqpZ;4 zT7kl{n0TWKm#Ty6<%2_!3pt(9E5T-bFec(*UTTGTL_9=(y`$r>_^V zfI(KCSqMNTAl()5t^I)6jqP?ol3m*NXV$vzFnuBE$z&|}eG0$V;|8?JgT1m#v@>^t zq8}j$wqDDatnryy!$%SBb!AW;oJZ_Da${r#Xw3%c4IVcdy2-+C%I=U#87awP|5-#- z!9CHNr%CP7;JYU-z;}kS;BHUuNGmg{xwXP_rJ)~MHR~_lF4I>9Fmbh(^s%Az5VNHT zlks&eK=gw~;}7sbuBFdKiUMTdkCMtwaiq%xmpfF3wuQ5#wjw7q)+?aq8|D&U6{J$u z&R9sBHz;{~;P;qsPHPQK7_4D@;J;Nh{zAtO+6#rX~X3vk`&A3oI`$A zE(G_O++8P#<_4{G*M%;;NjfR&)dWO_qVpx?Sg?I--fD7u7J7cNsb$DY;C#u9vRLTQ zXW6L|1;kQ6%Sf=(6XO^-na@5#>X#bCB|i|M|Ef-BhR^Oxc;q%$Ot z!j5lLkAG!Za#Y?Hr5G;fGE02?Wnl4?TqqO%$>U(a?R>|GG%fiD5*UKrf7A@E{va>`Cfr~)GZ!)>c-9N2h;!y zN~(Zp3FVO67g*zcLV6m&^Mf?U$$_R_X3yA@Y!wc+_Km4&1dqr_Ydm_Dm?hsEU_zO{ zDKOb~kdVdE!dp#`9wymd9lW3z!)?7q-`%EL@R3UMgLfC`L)*YB?rf_v+zJq})o4lg zJw1s+LHa)PVAuDgD_avHW>gW>7hSVRn3sW9$b?i$#TDoiKTsb&Jd+Un#2KokO;h8J4 z@urK0w=xJN`I{s!2v-!zNvhW8>78j)+dYg_ED$KjwYYw7yuP5Xl!S5$wUGhmnxqjh zG}skz?iuVE$c~M&gAz_!Tir;Ld3@N-gKQ{>ap7syG*X#Tk4o0lzG~;QBEsX6YgEv8 zA5@mXgibmcH0#Y;*4X~b-O=_<20wF}zsi9hE(og^XmWtIyQ#|FBtS8!8jy&0GE z?hguQN;3$@#>=GfuQuKOaNKF5ffQS6S)>}NSF;atydDINF8p~hgfL&Bl6;+MWc%dO z^)xvU7IC0UAYZPI_<`~fO=ODfGRx(*lCKbUKDwW|E4WH9 z>Yde-hyCTdT1Fkc2K_)XNb%Y=+C#3&F@()%?ThCx0ZR9C^-DUAYj_nJ4;n#W;fFyF z)UyYRz6+g&zGQ~2UI`9dZA9{STat~$G9KoiF;u-}&M!7rczqCJ!JQsWSy!V!^qJ+% zVTR+*Czh7H{m(rEN(aDPmDcd&>z}w449*%xq}y!1H^IcRA3$LS9N3VxpuUOl4EHZy zB9VdBq^1|!luZb3FWkL)Ubc!hQYl<5?b$}^-98(vHL6>K5XfGck?3TM+bQ3OEb^IB zt)1>OAjHJn-sMw?-y5F|wh3YF93Z(6q0f06zYw&$GQ=LuO|4HpHm66bAgBCLpTm`l z;>u9<6UJ3nM|owe>Mc!t``QVs6KZOlQ^Z*AO9kd~4IRK3JDb2=ltr-u413wXB$NZZ z$RfzbTuf>_MHL*Nh#Y`;z+Z`{CkWFn2P&E~OYwd#rar69%11x_G#7C>U#*J$FhWHm zOyUx+O~S4F7|mNlb1um|6CLl)%Lo6w^)|zU)R3HPr#|zMi1tldf_J}4?kuVqEI2R5PPY$MI~alNlBcZI zv48yLVYqjfi`41MJkR>ZaAJ|l#Fm7#AWuVI*H0?S3{G+-#jE1x*zY7t3=V-Yk=nwzSyz31a~!Bw{$2u$!$Vas0w<;sFAv#a!kUG!waMg|K^tYWS8r;(o8(JbHBhoWJ!98 zPR(iK*|F#-Q`O_@fxaA-ry`}?o89%xwLg@-^Y~Lq_0BQvP+@@wb^PDPjF7%>3LYQ3 zT4vmGR`t3!NN0NP^_yKD(dF^-j4&wV>%LLbm(}6dv2A=3zGsD>GnHhm`Z}TRSehJo zikw#;`$i5B133T?sg8M$3ckvXI7?yXI!w zhzGh4AcZ1vBZJlHg_i=jpR|tV%IAQThA!lu)8yQWKH&>OFfEri*6g?jnR1d%B*&T= z>Zx=((6_nFE4SmP!v?eL9(=v5MNWbqVUDLxB`jFN>eLbNr*=UqW_xN^cYpRdi@zLLX6cEkmdHO}bd^~)-??jpL-%#|wSLWeoiRYrxsK zEVxD7mDy(|Ldv1~SF2ZS-M(Cqz-by<@lcEf1uI0EP;uH@^IB0TZBexjb|D7Uv`$2Y ztM6~e&Yhn+o_hRx6X0LfZ48wrd6t637$W!{+psG?r$z&PL<>TD=Yvs*vD*CE9G zf#L?ku)W-MFgf*42O zKJ+MG4(vs@TUzVq_;hZUq|@;EkW^z6AJ{Z|&HaJrzQ_Lhbc)B%djQ95x7=dd(s=-Y z5sxF@LowIUhNE4aM3ER56js#B$(5)b06@v) z)B)?bs$d;(nm%q=BOhI3w2vcN2E(s#jaJSJP6Tkm5|BVIr`yhWxR*TtFI+fr`*c{0 zANb3J;3&^;uA>iBadE=}B}64e!5}p+oQF97HCmvY8^#W9sH*-41o4|ZzXO5b3KtXe z^z;<BXg8wZaW2llQ%oev z#hoC}&rh5O{wqHxR~?-{;hph+ut4NP%nRu%1`!2|IXQ{_)dNpZ^B{u!k1yZnuAxgF%a7Z)2T^rg&mh$lpS0AawNq^f;x! z9_Qrx%Zo_%-z*6@yML4Qx7e!5}-VoeW3Pc7(1A>I2!W{3WJ8LySOkZuFm$qCQb>5E9oQT`Nc)S{~po5jU?C+9pw47an9~u|DG_$Ibn?m$Wt~UFi9{( zTuNF-5-bgtmV*A<$Q0{_Co1t269N{6{>D9R3!GRCkyzxZPKf}&JczZxRot*hf{UB6 zi_2|!{?n9zr=Gv$4V3%c6ipnSXyJXT_&+pnguV0o+wWcAHtyFH5co^Ba3uP75IoWY z`us;a+69w;LNAN_tVU_HO6%(r>3h7r>K%rlh3jZqpPis#H>?vPh;ywkva$^5y`{jsgM*mjK|4k0pP8TjbaVfRO z5ggo6qNgjJk1-bQjQkzqHtrAa|1IF((SO_iWql<&{T?H(+r-0w*q_INKRQHY=l|#9 z50U@>3;_iG6Xd_*_aD0cq3ge5;J-5dM_vEW^ zb3Saue*==FBUF`)H9HoPDz3LEvb8r9tI_7Q74mSETJT$k{9p-^=HRW9iMT8Hs*G{s zdV%vN@g(J+_mv;tN}?`hhDY!Ld81X1`*PJ+FPjY!KdqBX%C-%97a^uw$>6|{+)a2K`R>wmCfGyC+*pz65@&dZJ5$teISRm2c1q;NIaCQIyX*lbVqvyFi zrqDxZ1S16nJD5Ms5lekCKsn)_|Jb&!@XBD`0o*c&{%QU}-PHHRbh+=r_cG%yb`QTu z)=<_4DKP~&tSzIJtQy%MNRqYgYfu)f~Dm*TP7+5RCQWR*-Pv4a%c{^cMyOdgBKorgx&p-i-Kfw@Yb4zM%_ss|jm+cNT+)EmPjfYi4^n z-!0NRJM51oFjy>C)E&;wN!>YNEn0$YPT26XE-_+!_Vm7(qb@G%d)1(uu974H3Yfft zfBt$dm2cUa#aLVKt0M}l*#D+HEk`D;D)jPw7pQm9W^m_fuiWljwKB7iRohej{M^{H zf=Y=~sT+kBnwMs4BA)BtoKTsOo2T?ed=T5Rp;jLsKB^IS7a76s*!V-lU7aU} z7*9YOU^5Or8(pU&U%s@c{}$16E!E$c?}kiqAA;@ukj#Ksm3zaD;8zzKPS53)G<`JI z%M%~qxRz&bE;hCz8*&Bkwz(qmqf>V{)?6=j%UHYiYwM4Am*gyW83?G44kBaDajjg+ zveV*y*hv1&X65uLU(l1SH`=2wd{c3G3LK$I76|XT7e3~vu4C;?s%>)uA0!&_dp6@4 zW0pzWd`NrZF^{}~N6&DM_3Rc_y*97A>nul}l$8=D%nP5=@3iU(mp_4i8Fg~Hwzv|O z800b|DYhJP8C3bDl1-xLCI$S`C!exhipa4Jb-rNXo`~=nSo_{gGj%bjpfng~xVm(8s092) zC!=^80uAbDQ1F$4zEXbrAYK#tXwt{x9c^8n2X&!M-q5uQ213#c=Jy+j28nkggeOWN z>l6Vr7LmCr^_{*`_Fw7xk`;0AQvd0phR^m+2b>0eol>DxFJm8(-k(r*bx`=SfTjFZa0eyuFhz8ZkK@ z{jgakY`#?~=U$0$@i8Gsi3`u?5)~=10>{p@@#k@mFWb9p8^`Rikvl_uee z>aAB!GmAWfkyt#CjP9Zzugz$RcE`U&4JpQI>2TF{K3N0y=vdiwH5nF}-k*WpXW*ZsP1{>ELg)V9=D+2EmWyV4D0vipM-38SL^W65DVp}VX& zKZbc7Z?)~Z+AG4_DJS>ynJc9-HVg!cIn{G`)^Qh=K#8MsA52~_S@Uq&${Pq@wyBM^ z8aP*_kNS~7AFVsM-XPUAX%s4CbB>jH(4o*1czmTHslGqxfYsL2-0!sG+LdW#M!ON= zvP=8@DZRW^CmjQxr>rt}Dh7=?Mo;?UFRDBo>Wew2<@JG9>DF1=S?XqQ;gMjrlWQe+ zLwUY7UheA3-{@#8Q}d>gw%9k{UN_A6P}5zgj$;PUH@gWuOp4kRhe{jHTr@@*GwZ&6 zog(j6t#oZGL}-iW`b|c=Le6MN3n`u#ao6OS9%M8+by4JA_8L)P;5A1*Pl6Tv4aZ|7#luGX`^RhPYf()_ z7Zf}nF3WxYq58F=kZ@cu;O%Pd>D|>cVd0Z)qlvK(zRQcp>8r%3>W0`uxb1v4W$T6P9uy9M z&`W1-8zU=3K4-^h^4JwcCKMGg&jARDOYd=K?MP=jyz>OdDm*XDk2>2vKn^kT=zq?3 zNshtrW1$*FAV_BPqkl>RMMou`xxZP;s)I(vvSlHTyGv(*b_IkIj&!3M{KG zP875de3T7EPZ*?_a_i3pawCh%F9w_qIxAI+dA!ECX;DHpP4pQ&o4ys z0rGtMmJO6wvW`(RGd~Ns4I87`XY0QeTZe5bYEAJ{nPp)8>|-Hy9M2^RSM--P*RHxl zYIelFQA&t>xm`T{<7|lT#Dmx$Hkiyu&jcsyzc{eg?A)P@xWeZmd#$7Ekw=(}8WSwW z@N^P|2B(AKebF_Gm6&Etj!9<~$uogPmv|AM*Ap^xW?w3C@)T>o_s+lTFBi(~FAukfoaHnuC= zEX#u=KhEntyg3eZ5lkAc$5{+c<_wrZ3fEm58iO0pL}Ys#>sVPn4!OP8oeq^NM)3yj&`w_DTzhOIv-giV46lajb=Yh{5rqa*eayXP#j7%P>x9A=6`VRJu*d zrzR1jdiSF`J;ZNYIA!wBXs3*_3HIG}lJ>pUo_$f#3Cy3_bgL(?iG`B3Q#1-o?c2vB z`)pi)q}^Mkm*OH_{6yhorxzRkZmMa;umoSzY3+p|yk%q< zE-)Civ%kBTmd)7|=JcILGk49PTxlVw!$qrCJaIFDPIdR! z;1U4c`D4oFgbpskZ41-_pO@Q*^tbnwe1;w}j)v!vvgbSY)a5tn1>IVTd;QO+L_AT0^%vlD#co{VspYj#hGqd_& z-k&g{pyJ*Cw68VX=Pxx5vXVGVBGy4wYIydV)M@pG^%WHfr-kR4CL8Zt;89qeo#I+} z&(gVbnlsf(Lq`0c5nUs8@kUyZ-E7`;GkMG>FZ1_2)e{Te0?Q#Ltiv?T!qcr#Lt>>0 zb)VpLdvi=Wr2ax)FI!o%C+(D@$FwK5Vyk#Kt@68N^14QDe^(Y|T^GYunyc6EyzMkH zcrkHdk0GuxFw_n0?7i24Q>5k~+ED}ExL8~e-bU_QQKZ$^!6X7ItB}*zlf4==cg=OW z8tPQBgDljkF>?MJ2S|!$m(V!29zdzGqeR$V{8DR}7L^n88vXuGD>8^C}IIvKH!(=uNvEjbAKC)?jRDmuMR$>$i`F{->m($+2r_2EKJ-G~OORAe_9gXIA1 zxurWZIS=K$LoOs+y(b6$9VG^tARz?iNef>OR zt(5xI-crlVnOp_WDN^ki_ID^5MwBoX(*_u+r6YA8yr`pPJ;q^7wRCViE~ZUndj4ej zg0N*|f#lS9XC3=`vCFGbu8v%%Pz!%A4ui$evk6-ZYye(mu5z8x5U;&-VYz~Ic4)1J zmX`$G#q%I)Plqnp7fVOw;r2s(R~Bg{$Oj}!*IyH`duLu(M?csrh?P-CJ&XIp%Nc5p z+ENz7^IfEvof+;|^t1STjZ%fP1}ZD({lI|4)%n;Uu7%2LF(Z~tFq+`fVg=L9V|&+B zAc~u74c(JQtgK#Ytm50l_m)J`htPY{3jzm5*$TUB9A_Ey$E-s6>WtH9L!IdtG8K5g z0eVI{>FVQp`My4+q@OnuibN+hZl>-%LZb3ItE_uk0(2U-Yga85-(eyx{jdJW!4W$; zZ;01EHB*ohaAtVZX0B(FU@~% zzXEEvy7jJH8cTbsj?=eYJ9Ab+<~Rmy^}avqX1FA@86C#B+ek5Hf7OHCk*_B`<6%k3 z;Y}6vaT~j7=S#y}D(AU7D2KR~d2ZcTWfL(T8q)|Hy2#@CCFB|>%bZfn*Ga*|3wzP& zA5U_VXoWs|Fq}0}O{r|xje;{O**35oC{^zQr_1ySNJ1cBv5|r^G3>$uf_~Zz zOXK%2Ck-&S>)@{OTw@C@EUxCIo;2V0_*>&F9}_m~I@2Bas9!QI#GS4vVx?1YcM<+X zvv!6_gKJ2;KKnlK@+b~m_j+=75GL@vk58SnO8s(ysX?$i!@cjYBB8klIRH~xx>P$l znh8waj5&~|)LDCJz*Tim7oh|^;MBJVJsQb!OD+Gfa>O3grqMy^L8F7)# zG_wS2ZL+aV$(gQAO-M|NU~ktrr8ggIcBNf@^gQLjSfUX2tjY6kNO6~ZjNFSB_iWu$ z(wJnpz^L5oVzf5T2;&fY9cxfr1!GhHP+EGf#$?iWV2n|Z443W)RD`2vV?U)2>L76; zu*GGoxU~vpVm45hwmWfVy+LeX%KvT7mt#ce8S`%nehL(6@zmjqK~#>lrFb0HG&!U9V4P_1hS`H83iu{_!9#|=(^&% zRE^>mHw4_OkhjxO-L{Fq!`qopOh08a*;AYKRF9P3Rd0KI9aTO#_^|w(FOzXAm4BMj z-q=`GQTuuOqP!VhnqG~p@#^(V=z#Ep^mB5K8Rz2iaygg)0E$qYnwo)@n%cj1hscSf z_{SMeX(&{5QO27Mi%^31Gj=zBCpbL z+gl1)P^qrcyzOq$>ekTyE+txado6nA)cF4RgEwCRfu*g+P&h?y5*A~mb^3ud*Tq6w z+aNniwmXl$rHEut$=9q*&FovI*n1Bg$bU zPrC+7A-^|!41JR8I2V4P2)%)UZoDOqK&*xIYcZQy(+f;uXPa1l z(A4@mo)G518^P%|s|L55L|BKZ%$Y`hD3>qy)3K7M3(BHv`;XfxYY~WLgKVrr)KUcs zNmVo!E97hBN(?fZ^YJIpiJLpnZ`q1q62oTxYk$Y|nN5mjqrx7!y86>#lguTLdtN)9 zJIfPEo`(Sd$4s}UdGz_S006T)j=WuGs;h%Q6P%?`7=kTUisbA<77qZRs6ui$<369dJk=H|!N3J!7tY*1;V6YQea6963$avNSPj}=!UUF z7^!Ri20{L$B;-IOx*$LxFE1}CFQ^p3%^n1imzM{Dr9sltl4J`>cW*oqMUuq3pE-i~ zg`tjhN4t>~k0aoLN0=yEf(KDaNQgWS{8xU?F1otE!{gn5V}Z;Eh=g(hL8QPSXJ^o# zJ=}>Jo@9{U68euG?#AR@PmmGTo#5ey#%g$C@x(KKhQOeI_jmDdbNX2h1`WbGVV%jQ z?&PSDzl6M`rEBoJ#}NhgIA@oiUSzWWVoAi={Xy1Wayy#&S`xH-ZaA_kQBHr(>Ie!$hLV*gTT8>Rk}w&Jtt3oNMo!Wef`&_iF<4n!S$R1- z%x~FX&RUgcI&J?|%#USM*=De_CJ3PQS*;>o)mo0QCF!z;7Ko(&zu< z?KhGCKSm%!{}beI@%s;5|Iqcf82DSp|ETL9y8adef6MqEb^V{wMgPZ@Boqz*Vdx<9VYxlbOUb3vN9lmAn~arC4BB&G0>2Wf~}x*9Z}kF&DE zD7>#Xx{`MiVzks%jgd`biPhT2R9Tx2Uxiq>f?|Zc20ooGLpo>VpAFRj0v%9KfTmAb znRU>p3$#y*kVrm;Mb2-m1E1X9Ro9)+iY;|btiI=0r01ar~h`{(gD{W>*X^)|S`TB0zG-Nykv{?h>rk+;+WI1+QomJ}Wa;{gCb5I%=$ z!rf~;PBilRK)34^h^{GRP!e*w%Ur#!U9+Um=gO+m_DcDw_~3WXE(hA3moStqzMU9j zL>a`p{JeShM7LXBMeqIde34fMc9;7eo?D;x>!bp}ql5c=o@lPK#q?9u9V}l}9sS@D ze)rw8w)m`oZ${e34=6SX5fzqPrulL)Mh&hhI<22~VwGy6Oif2CPxRru1xwKWfgJtbiZ%O11$HyTEb0J zDr=PIBqTB>D6ht>5lxVv9;+DO3H-1&5Yim~bVB386$IgnMYgAHxaQgS%qUo)9`83^e(Uo1Om!Z6Q z>zJqd+MZ=p?EL(xvp(YrH&uRky#d3=&L-^dst7Nem-lyJhvW(9+U2-s-#o7m&u>h; z9^dYrJt+FRHM}!-nEG_7{eVC8=0%M!HLbpwslyURzca4|@UI}N;yH3%0y_i3A-e+} z+c!fAxAzZUH|UB>3;bA2HHqk#Lozry?zDZiWogtWUA8n*pW^_(tbNOI)w^llpA^6H zs$ligjUzga|6>Y*chXQ%X`hPFJ620=|j#vqw5Z}RShxSxeqLS=W88a z${Ci~eabVxrX7l5WvetRb+*UaxOCOuQ{#MfbET={YJ*5=r^H?_o+vU=+Wz!e!E4eW zhcsa@tkb!MFj~=~K`WT*_6?tZLDu7~_TN->;xRH@g_|6z3r1n3_0JtKZEp_Vu%CPHo0+W~yGg%wz4KQGe# zdhAOrgYMdoZzH#tu4k;vZ-NdVbW#&WZ+{)py|p)7=(JV1L0V{50^736Ed}`K{TN%3$ELapUh;-CCcE9CQ~Ft2<(k?3rlF?M%D}Kbl|zAUvC!(slH!g8jeXT z#Gf{yjUC2NpS*w4pW||k893#kHc65&Fyho&aji;1`@`KlQAC^L(6Oli?jkcRvqJfu zFEqzQ3k((ou7<#k=P0AN=zCf$?Bl2yKNc!Y!&aXdsq7oK)2rAIjTquy`-Qg#rJky+ z47m@wKls`I^%HHco{+T5dP!EnX6>D57uIpLIWwI`s@1kUNsxU%O?@%p+`-V$bT<%{ zHfZ5o3z$Pa73$v|73w~{U!Hhs_v>0;d~9K@>e#2vp@(xDW=-bqJ*L7&;dUZ+@V=4E zp{7t%W)Q%#xI_PT$@^h}7`fV>^1={RMbAulw(y*$zGv9VYz%*h;x0%VJnRK%V>?UpsqtVpA3hcF(p+6XgG z6X@fCUal$jU%9nu=li)GNk5`${&=#hHXa)9f zS*XYwOW^&MprK}Wj-F3U*9uPDn3Bfml$vSvMQ`K21ZQ-xO1*2JNa$hE&G>qZLO0v5 zd_t)A+7i+^SfC)4?!}&BZzh2y%*bIZs4ZzO{&-+_uC&Lu+;Y?pj(ID~>wEUa;fH-! zx9r7EZ2*k;#S=NHv?z;Iug6W)?B=9ioVzvKm+kwIL8#haF{A!2&GLp+z&o)T{R7eo z8$ev`(5IdReSf7rR^iZtB>Bu|BbD^3VGQ(9xn+X85og6MMM@@&9Tr(BA7q=l7h|*a z89X1{&=*>l5b$`)ihDa1<;V8@-ReN)LPh-9v}7xJuRg$5p+S>sWS{x*h9U$p~ zA*@8rHi$28cCNukS=jmnW>_me7fi^XHA@IKq16v(Q%R+v%Pr}EG=pw9=2E`(1WJBVvG%P2qo!vumW6N|-W|ibDSDc~H75gSUxOAhA5uKcKtSNn;*jGLA zajs5Ve=HB2F3HOsCz&HBcLAeuUVl+1jHKgB`(ndDY3 z1vPWJZ@FnY>hJksq0=!40F#JsM`198VI7hg4WJFy8*e?PuMm;GjF8FMYfNM}($z9O z_iliCBY>7&+dZ7!hcZW?`-yWFB#G9G6nU_^Tjls3bibn`V|&#CL>Sy?!;20 zS%L%B>Oi?yMG;obn0u=%c$_g#<_f0>+_OeJT?>Lk&bz+XHn#F~zgYLM&YqU*Muy0X zocYOS6bGy7Z4br4=JjJA?bIoqQ+Y2?*3ee@B88|o)4O{IMkqaC54*1TZ(1ye*YGLO zxX=2Cus0NI_3)}|5eACR2Komlrm_l}fIgrJ$Vk~2XD;2V{{j6NloPj0f|m>{nWiB> z^WigL1tW|+RusfHp`{#nzWM}PMNJNuPAAtMeva6?afVQ*G{Fu!%@N14G#p>Wl_|d2 z4FzZUiMWe1iw#+4RvIb!D1)GmY$MT3S}flU8+9m7`__->-z-VBkP%2@38Q}!pzm%T zc$zvW;Ptvh4SNSe#Zz7CR5(Ddd$h?PRbk!_zO$X_Bu=Z!C>l0fYhYG2uXCHrfi{sF zzs#599zT(0$0N48C99~!=ZJsy__o!R1h}cpW|%&#HlSQ%K{2h1$27rUz>YJVX()p6 zS+L@g2m1wf<2Xf3@HYxi*&GwLmnUF7g(VsJUD&2&R0Rss!;>2@+$ntWYJ&%7K&bbW z9sOZNzykLN%6*q&IzAS?I@J`l7@ftSou;keTU@Wu_rDJL7ekdF3om?}XTG1Vv$XBy^ekllez@R_bufcm0 zB)pFl3NBI!u@nedDSx~&pTqR}%xS+=wub(!hN48JZ8Jj%@cXkyWi6?fEgs;emY@qX zo(_@v!wAB040c5(vaUAz_@|w!R`#%ZYIF%_jDn$%I`!OndyAW2sH|lSM;45DL92+t zjy^%?RXtZ8Q5rFfp3=cGS1Susrr4HTz9_XHi(p>t{5rdSaP)xScE*D!7xfDTG;Ir* zDsPzx6(!^QZ_S!x`PlCP98^;|Jd`b2g~etjd0|aA8;8%CB&!`vH!?2_T!FS{2z4x8 zbSd&!rUDx8AQKbp2}5`9#Gj|epGv=kooK- zpkD%$G*h;Pf^W>jhwL7YHj!N>7>OK?>XI*WPh(E*EH)_kus84TBeIbhBREepHhP$UW0G%{7`ry_}(XH&b~nAtPiKv4X$B?i*XzB5%7Q(mXSw$V`v?me*Cwh@biN zlE28e+b&V#VZWH>djW3`msz#re*CM7j|S6}QFm<1B3Ug%m$lnE;@bE$8`PAVCY$+a zpRCcfeZpAD;IxC!$nPjI3YuoxJUY#+%9Av%aM`~(F#0tV!-sfG$0x-)yvmwz$u;ZbI4)Ie zTuvN`ZR7f?rzY5~mc8*1JYm6M#oLq9hO7QrV>;nrH#h@?wrh0uTjD zuh0+3s!dxZeO?Yl<&+4z<|~Q(@k`pw+&lp_Rn0s2t0wkoi@5wUM!v5M@nsYbmO>$Y zY~?m7O8MAapz@a^B^6V#2b>q~@v<aKvdg?ubv9%FaQHd;$Et zLB0m;yp}2K;xun{EXUeA-rmeeJ16_}y!@?7&QP)OmACbr@C_oX2d!~dWN4)Pqb(c$ z(c^&XW2(-5QS(fEW!$Y?M9QnLxcM`a;v)CB7qIck!H?}Y>{c?LKE5m^FtkopZAzz^ zAbU2$WoGvK=UaKf+7HV12cGW^XsD^*ea`aaG+uSVf5pmG|~5iI`A>&(v)t# z-llpJbi-CaE{dg;Wu)n2y*WI60X29cTlg`BYkH?6_tGpS`y8(0xORvIR?Tg(Gw_SOuM$d0{cYRUw=>;;rb!95j-?x%q zyR6zc*_J#5V32>M?~S>6BmTv)JBTmme0NeI8xcV=8P{UHA%d)@kug{fiayte-Q2nW(?xR|jKzeN^2dwp<({ECJxy)~r zV1Z+T2WEVx?kK8-i-f#Z9GoS-Y^^?Vj^Ni@J&1f>X;_mP=kk#G(nh08cB^^Q;Xbi@ zKelJp6wx3#2k03-l>}IN(-))L!|bOeEf;dIB8@*RbqOBV*h>%L+t(R76ycim?D>J4 zq%Xee$jmL<$H_;T8=K9Bff44u|$cYz;JcA6TANDx$OY#~x!2Pufip%$r2KUYh*8XP$!d?ms~6-V1C4q$|k0BQ*lY zc+$qoNS%94`bPKJrifFnL89vWt?q-nOoSd zW#7Eri3wRdgDW?~E&6^xdxv4D9oCPJ<_S>|Q49v0b2ror36Wal5V`~-rLC`=lJ<+g z0jmzgRusRz^9bbPnu-PKWG(>H7V)%z##bV!aCNG-8vY0o0 zR9HC;0;z0(nQ4$lv`{+v743~B07|#oRy~F-V;X!WU`uQ_PX^+}uwGDg%OU;qIz_8N zQIBL@Juk#4Yr#F%bIW6EaXi`M&=25{<(Bh|zTgW0aFU28@Aa8zUqRXsoJ7&K1Z#|_ zmy-)wJOF@*T?SjJC;njWIFjswa3~hWI zY!J3Uc{zF+FC-bj2}45jcsV&b6OmrBz@NBC^6}9y7|8R}gybL#G||@MK@r?AJaAFC zC+~2+-$K(17+3UAjscjfp#R43la?W^z;<<6cZ)5;lNM?0s)4=z%Uqy zYyl#AJCo2}AZH@q5yUSHWem~AjjVV)!I|d>6Kzd!C&>bV%z0t^GT^Gx0YT z$b5jk&@N!8CZEd77!N&b4Jq=}9;8A>}Ex`tFi~MIlmA2uc!*fMO9gAZr-Z8U!b20Fn~7 zhJwUlHgK$sBn%Fd5c`>ptqoF@;O2xTw-fJ##$muN&bXfwM}#94^)zIGFj2@KBYKW# z5|->B3%r7NcK7;Y!VvF-xk^GGu?dwBhd^PH2r)4+2ow$#|HH@#<3=Pa@dy(N5f%G| zd(;*rxfn9B=p&ty0e*UrYeAyiFlZ9N&5%HFlm#B8#B=2NQ{Fr>znY?sCz36^j}-r# z=C5L0e|`IP3OM3_PVw;klr0i%^D77u?SZlV8HnunYs$tB?To{a&u{S2d1{L$q5nFM z|2It&gJLCZ5pXO>;%BQQt;tM7uow^wP3Bn21`D^9`bEI+QHTUA$rJ5{QN)oeCRark z($A`R1bY~SCCY%07O;OcR|fn)+b=^_ zv&}EX{BLrQJ6gDi<53i*{vM19kF*=&BT>v%X6! zCyQ{qzGK(zx_Z!IK%LME*oEQyDM)BV)3vq?8Yd(8GePolj@<$}+YLLKPB>^f{&8ozKy{t^hPyDMF6X)!8 z;{0CQcU};GOKH@3=9qcL@L}!!uxGI463{#IVCNX*L%j&MiU}WRu2~3WPhNoH;lXUp z@l+;2o%htbu@r8lxbW$#i)psCF9jG2&PD7YghV~JlCw`PT?gH;ys={qROvK7^P#XW zxAN(CWF%K#wA5aQsa&i7T3f|tgq7>Idf=>=67|NHwA&d5lrsaX3WJ^!m7>UfCFpkI&?Z&HOWMh>+s<- u(QttzV^@_C_3lh_BW8(FcVEiJ%5lNa2ElZW%dX_!0W?%}lna%t0{;sgueDYH literal 0 HcmV?d00001 diff --git a/assets/textures/items/BlueTang(19x9).png b/assets/textures/items/BlueTang(19x9).png new file mode 100644 index 0000000000000000000000000000000000000000..2c8243c561fb46d9bacf4fbe7344fb07f1a4acae GIT binary patch literal 9572 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 Z%y(dC|Jr&g4??ORKnG=@QLJVY_Fp!EG}r(D literal 0 HcmV?d00001 diff --git a/assets/textures/items/FishSchoolIcon(64x64).png b/assets/textures/items/FishSchoolIcon(64x64).png index e47d40080a347ab06906797866d60d7bef215b9d..862ea7954dab0b6c3fd60710ba1a5c0bbb33ec14 100644 GIT binary patch literal 11293 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 HvwZwt^5}qk delta 579 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

Mkp6&$-r!RSy-+q#o&&rj{pjehZUM7pf& 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 UX{JO=1<-Z|Pgg&ebxsLQ00;FzcmMzZ diff --git a/assets/textures/items/SmallFish2(13x9).png b/assets/textures/items/SmallFish2(13x9).png index 9de07d790d10efb208def6e3a428746645844c4c..0030b73900344af9b88b9570a08714f2b79cf6cb 100644 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^CP2)|!3HF2=kU(}Qqw$L978O6?@l%3Yf#{Em6vO6 zJSbf0;{W8r!PO6(cmofv;&l7Zk{j7jvV(#P$L561n8b@Lh z=Uut^RMU{JBhE$kb)0GY0SjLSp4xb;1+6<{)eF^@1*dbZVak+^Hm*!g_h}F0ioYn` zvvcA4j9ia&>)k08f^&Tn%x|Bap(6ZwceoyV-_;g9$(&X?mfmw@AU7R&PeeSkx?9%^B7>~voMMS@{Iu5jz N!PC{xWt~$(6993-KNtW2 diff --git a/assets/textures/items/SmallFish3(13x9).png b/assets/textures/items/SmallFish3(13x9).png index d62a20a70b42897b9fb285652207acb2d6ef3b5d..981f074d6f398f3f83386ae23ef2e8597c702717 100644 GIT binary patch literal 216 zcmV;}04M*6P)l##B30W8G7!4W#|P*C<)ZG5>fh3VEfrvG5`=MD^~n9`KyWv7z4!MojA6=XtXP@=K{d=m`exLFkjb6oQfI5nF6ao zTF2f@-qR34j5G|^fi=H{vYz9UUff%$-S%dew~ZiHG5{162t3l(e~Y$Tz9fM znG57*em?OkGNq*yw4A}y)z4*}Q$iB}T){q3 diff --git a/src/map/fish_school.rs b/src/map/fish_school.rs index 8c32e4f252..17256f48c0 100644 --- a/src/map/fish_school.rs +++ b/src/map/fish_school.rs @@ -10,16 +10,25 @@ use macroquad::{ use crate::{ player::Player, utils::{ease::Ease, timer::Timer}, - Drawable, PhysicsBody, Resources, RigidBody, SpriteParams, + AnimatedSpriteParams, Animation, Drawable, PhysicsBody, Resources, RigidBody, }; /// The texture of the fish school icon ( used in the editor to represent a school of fish ) pub const FISH_SCHOOL_ICON_TEXTURE_ID: &str = "fish_school_icon"; /// List of fish textures -const FISH_TEXTURE_IDS: &[&str] = &["small_fish1", "small_fish2", "small_fish3"]; +const FISH_TEXTURE_IDS: &[&str] = &[ + "blue_tang", + "royal_gramma", + "arabian_angelfish", + "blue_green_chromis", + "banded_butterfly_fish", + // "small_fish1", + // "small_fish2", + // "small_fish3", +]; /// The default and most-likely to ocurr number of fish in a school -const FISH_COUNT_BASE: u32 = 5; +const FISH_COUNT_BASE: u32 = 3; /// The ammount greater or less than the base number of fish that may spawn const FISH_COUNT_RANGE: u32 = 2; /// The distance from the spawn point on each axis that the individual fish in the school will be @@ -65,6 +74,10 @@ pub enum FishState { } pub fn spawn_fish_school(world: &mut World, spawn_position: Vec2) -> Result { + let resources = storage::get::(); + let fish_school_icon_sprite = resources.textures.get(FISH_SCHOOL_ICON_TEXTURE_ID).unwrap(); + let fish_school_icon_sprite_size = fish_school_icon_sprite.meta.frame_size.unwrap(); + let rand_bool = || rand::gen_range(0u8, 2) == 0; let mut fish_count = FISH_COUNT_BASE as i32; @@ -78,7 +91,7 @@ pub fn spawn_fish_school(world: &mut World, spawn_position: Vec2) -> Result Result().iter() { let school: &FishSchool = school; - let school_info = if let Some(info) = get_school_info(world, &school) { + let school_info = if let Some(info) = get_school_info(world, school) { info } else { continue; @@ -158,7 +179,7 @@ pub fn update_fish_schools(world: &mut World) { let (mut fish, drawable, transform) = world .query_one_mut::<(&mut Fish, &mut Drawable, &mut Transform)>(*fish_entity) .unwrap(); - let sprite = drawable.get_sprite_mut().unwrap(); + let sprite = drawable.get_animated_sprite_mut().unwrap(); let pos: &mut Vec2 = &mut transform.position; let padding = 20.0; let rect = Rect::new( @@ -176,7 +197,7 @@ pub fn update_fish_schools(world: &mut World) { } } - let rand_bool = |true_bias: u8| rand::gen_range(0u8, 2 + true_bias) > 0; + let rand_bool = || rand::gen_range(0u8, 2) > 0; let rand_delay = |min, max| Timer::new(rand::gen_range(min, max)); let pick_next_move = || { @@ -190,7 +211,7 @@ pub fn update_fish_schools(world: &mut World) { }, rand_delay(0.2, 0.7), ) - } else if rand_bool(0) { + } else if rand_bool() { let target_point = vec2( pos.x + rand::gen_range(-20.0, 20.0), pos.y + rand::gen_range(-20.0, 20.0), @@ -247,6 +268,8 @@ pub fn update_fish_schools(world: &mut World) { .output(); sprite.is_flipped_x = from.x > to.x; + sprite.current_frame = + (sprite.animations[0].frames as f32 * lerp_progress).floor() as u32; *pos = from.lerp(*to, lerp_progress); }