diff --git a/assets/img/map/fish.aseprite b/assets/img/map/fish.aseprite new file mode 100644 index 0000000..1883247 Binary files /dev/null and b/assets/img/map/fish.aseprite differ diff --git a/assets/img/map/fish.json b/assets/img/map/fish.json new file mode 100644 index 0000000..324ec8a --- /dev/null +++ b/assets/img/map/fish.json @@ -0,0 +1,26 @@ +{ "frames": { + "fish 62.aseprite": { + "frame": { "x": 806, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 50 + } + }, + "meta": { + "app": "http://www.aseprite.org/", + "version": "1.2.27-x64", + "image": "fish.png", + "format": "RGBA8888", + "size": { "w": 819, "h": 9 }, + "scale": "1", + "frameTags": [ + ], + "layers": [ + { "name": "Layer 1", "opacity": 255, "blendMode": "normal" } + ], + "slices": [ + ] + } +} diff --git a/assets/img/map/fish.png b/assets/img/map/fish.png new file mode 100644 index 0000000..29054a8 Binary files /dev/null and b/assets/img/map/fish.png differ diff --git a/assets/img/map/fishIdle.aseprite b/assets/img/map/fishIdle.aseprite new file mode 100644 index 0000000..6514d45 Binary files /dev/null and b/assets/img/map/fishIdle.aseprite differ diff --git a/assets/img/map/fishStill.json b/assets/img/map/fishStill.json new file mode 100644 index 0000000..f8f5e3b --- /dev/null +++ b/assets/img/map/fishStill.json @@ -0,0 +1,130 @@ +{ "frames": { + "fishIdle 0.aseprite": { + "frame": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 1.aseprite": { + "frame": { "x": 13, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 2.aseprite": { + "frame": { "x": 26, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 3.aseprite": { + "frame": { "x": 39, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 4.aseprite": { + "frame": { "x": 52, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 5.aseprite": { + "frame": { "x": 65, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 6.aseprite": { + "frame": { "x": 78, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 7.aseprite": { + "frame": { "x": 91, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 8.aseprite": { + "frame": { "x": 104, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 9.aseprite": { + "frame": { "x": 117, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 10.aseprite": { + "frame": { "x": 130, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 11.aseprite": { + "frame": { "x": 143, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 12.aseprite": { + "frame": { "x": 156, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + }, + "fishIdle 13.aseprite": { + "frame": { "x": 169, "y": 0, "w": 13, "h": 9 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 13, "h": 9 }, + "sourceSize": { "w": 13, "h": 9 }, + "duration": 100 + } + }, + "meta": { + "app": "http://www.aseprite.org/", + "version": "1.2.27-x64", + "image": "fishIdle.png", + "format": "RGBA8888", + "size": { "w": 182, "h": 9 }, + "scale": "1", + "frameTags": [ + ], + "layers": [ + { "name": "Layer 1", "opacity": 255, "blendMode": "normal" } + ], + "slices": [ + ] + } +} diff --git a/assets/img/map/fishStill.png b/assets/img/map/fishStill.png new file mode 100644 index 0000000..44c6967 Binary files /dev/null and b/assets/img/map/fishStill.png differ diff --git a/src/entities/fish.rs b/src/entities/fish.rs index 8982d0b..6cae1ab 100644 --- a/src/entities/fish.rs +++ b/src/entities/fish.rs @@ -2,7 +2,11 @@ use rand::{prelude::ThreadRng, Rng}; use raylib::prelude::*; use crate::{ - gamecore::GameCore, lib::utils::triangles::rotate_vector, player::Player, world::World, + gamecore::{self, GameCore}, + lib::utils::triangles::rotate_vector, + player::Player, + resources::GlobalResources, + world::World, }; const FISH_FOLLOW_PLAYER_DISTANCE: f32 = 30.0; @@ -25,9 +29,11 @@ pub struct FishEntity { direction: Vector2, velocity: Vector2, pub following_player: bool, + current_frame: u8, + animation_counter: u32, size: Vector2, + color: u8, rng: ThreadRng, - color: Color, } impl FishEntity { @@ -35,16 +41,16 @@ impl FishEntity { let mut rng = rand::thread_rng(); Self { position: position, - direction: Vector2::zero(), + direction: Vector2 { + x: rng.gen_range(0.0..1.0), + y: rng.gen_range(0.0..1.0), + }, velocity: Vector2::zero(), following_player: false, + animation_counter: 0, + current_frame: 0, size: Vector2 { x: 5.0, y: 8.0 }, - color: Color { - r: rng.gen_range(128..225), - g: rng.gen_range(128..225), - b: rng.gen_range(128..225), - a: 140, - }, + color: rng.gen_range(0..6), rng, } } @@ -138,21 +144,17 @@ impl FishEntity { // Distance and direction to player let dist_to_player = player.position - self.position; let dist_to_player_lin = self.position.distance_to(player.position); - let mut direction_to_player = dist_to_player; - direction_to_player.normalize(); // Handle player picking up fish if player.position.distance_to(self.position).abs() <= player.size.y * 2.2 { self.following_player = true; self.velocity = self.direction.normalized(); + self.current_frame = 0; + self.animation_counter = 0; // Add currency to the player player.coins += 1; } - - // Look at the player; - self.position = self.position; - self.direction = direction_to_player; } pub fn update_position(&mut self, player: &mut Player, dt: f64, other_fish: &Vec) { @@ -163,40 +165,45 @@ impl FishEntity { } } - pub fn render(&self, context_2d: &mut RaylibMode2D) { + pub fn render( + &mut self, + context_2d: &mut RaylibMode2D, + resources: &mut GlobalResources, + ) { // Direction - let direction = - Vector2::zero().angle_to(self.direction.normalized()) + (90.0 as f32).to_radians(); + let direction = (Vector2::zero().angle_to(self.direction.normalized())).to_degrees(); - // Get the corners of the fish - let fish_front = rotate_vector( - Vector2 { - x: 0.0, - y: (self.size.y / 2.0) * -1.0, - }, - direction, - ); - let fish_bl = rotate_vector( - Vector2 { - x: (self.size.x / 2.0) * -1.0, - y: (self.size.y / 2.0), - }, - direction, - ); - let fish_br = rotate_vector( - Vector2 { - x: (self.size.x / 2.0), - y: (self.size.y / 2.0), - }, - direction, - ); + self.animation_counter += 1; - // Draw the fish as a triangle with rotation - context_2d.draw_triangle( - self.position + fish_front, - self.position + fish_bl, - self.position + fish_br, - self.color, - ); + // swimming + if self.following_player { + if self.animation_counter % 3 == 0 { + self.current_frame += 1; + if self.current_frame == 8 { + self.current_frame = 0; + } + } + resources.fish_animation_swim.draw_frame( + context_2d, + self.position, + direction, + (self.current_frame + self.color * 9) as u32, + ); + // idle + } else { + if self.animation_counter % 10 == 0 { + if self.current_frame == 0 { + self.current_frame = 1; + } else { + self.current_frame = 0; + } + } + resources.fish_animation_idle.draw_frame( + context_2d, + self.position, + direction, + (self.current_frame + self.color * 2) as u32, + ); + } } } diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs index 3f2bce6..ea95cf2 100644 --- a/src/logic/ingame/mod.rs +++ b/src/logic/ingame/mod.rs @@ -62,7 +62,7 @@ impl InGameScreen { let fish_clone = game_core.world.fish.clone(); for fish in game_core.world.fish.iter_mut() { fish.update_position(&mut game_core.player, dt, &fish_clone); - fish.render(context_2d); + fish.render(context_2d, &mut game_core.resources); } // Render the world texture diff --git a/src/resources.rs b/src/resources.rs index 4dfe7c7..ee128e5 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -17,6 +17,10 @@ pub struct GlobalResources { pub player_animation_boost_charge: FrameAnimationWrapper, pub player_animation_boost: FrameAnimationWrapper, pub player_animation_stunned: FrameAnimationWrapper, + + // Fish + pub fish_animation_idle: FrameAnimationWrapper, + pub fish_animation_swim: FrameAnimationWrapper, // Cave pub cave_mid_layer: Texture2D, @@ -80,6 +84,24 @@ impl GlobalResources { 4, 100 / 8, ), + fish_animation_idle: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/map/fishStill.png")?, + )?, + Vector2 { x: 13.0, y: 9.0 }, + 14, + 30, + ), + fish_animation_swim: FrameAnimationWrapper::new( + raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/map/fish.png")?, + )?, + Vector2 { x: 13.0, y: 9.0 }, + 63, + 30, + ), cave_mid_layer: raylib.load_texture_from_image( &thread, &Image::load_image("./assets/img/map/cave.png")?,