Merge pull request #14 from Ewpratten/player_texturing

Player animations!
This commit is contained in:
Evan Pratten 2021-04-24 13:11:41 -04:00 committed by GitHub
commit e739553cbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 482 additions and 32 deletions

Binary file not shown.

View File

@ -0,0 +1,82 @@
{ "frames": {
"Sprite-0005 0.": {
"frame": { "x": 0, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 1.": {
"frame": { "x": 11, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 2.": {
"frame": { "x": 22, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 3.": {
"frame": { "x": 33, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 4.": {
"frame": { "x": 44, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 5.": {
"frame": { "x": 55, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 6.": {
"frame": { "x": 66, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"Sprite-0005 7.": {
"frame": { "x": 77, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
}
},
"meta": {
"app": "http://www.aseprite.org/",
"version": "1.2.27-x64",
"image": "diveNormal.png",
"format": "RGBA8888",
"size": { "w": 88, "h": 21 },
"scale": "1",
"frameTags": [
],
"layers": [
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
],
"slices": [
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

View File

@ -0,0 +1,186 @@
{ "frames": {
"diveStroke 0.aseprite": {
"frame": { "x": 0, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 1.aseprite": {
"frame": { "x": 17, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 2.aseprite": {
"frame": { "x": 34, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 3.aseprite": {
"frame": { "x": 51, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 4.aseprite": {
"frame": { "x": 68, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 5.aseprite": {
"frame": { "x": 85, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 6.aseprite": {
"frame": { "x": 102, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 7.aseprite": {
"frame": { "x": 119, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 8.aseprite": {
"frame": { "x": 136, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 9.aseprite": {
"frame": { "x": 153, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 10.aseprite": {
"frame": { "x": 170, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 11.aseprite": {
"frame": { "x": 187, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 12.aseprite": {
"frame": { "x": 204, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 13.aseprite": {
"frame": { "x": 221, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 14.aseprite": {
"frame": { "x": 238, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 15.aseprite": {
"frame": { "x": 255, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 16.aseprite": {
"frame": { "x": 272, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 17.aseprite": {
"frame": { "x": 289, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 18.aseprite": {
"frame": { "x": 306, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 19.aseprite": {
"frame": { "x": 323, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
},
"diveStroke 20.aseprite": {
"frame": { "x": 340, "y": 0, "w": 17, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 17, "h": 21 },
"sourceSize": { "w": 17, "h": 21 },
"duration": 75
}
},
"meta": {
"app": "http://www.aseprite.org/",
"version": "1.2.27-x64",
"image": "diveStroke.png",
"format": "RGBA8888",
"size": { "w": 357, "h": 21 },
"scale": "1",
"frameTags": [
],
"layers": [
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
],
"slices": [
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

View File

@ -0,0 +1,50 @@
{ "frames": {
"diveStroke 0.aseprite": {
"frame": { "x": 0, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"diveStroke 1.aseprite": {
"frame": { "x": 11, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"diveStroke 2.aseprite": {
"frame": { "x": 22, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
},
"diveStroke 3.aseprite": {
"frame": { "x": 33, "y": 0, "w": 11, "h": 21 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 21 },
"sourceSize": { "w": 11, "h": 21 },
"duration": 100
}
},
"meta": {
"app": "http://www.aseprite.org/",
"version": "1.2.27-x64",
"image": "diveStrokeCharge.png",
"format": "RGBA8888",
"size": { "w": 44, "h": 21 },
"scale": "1",
"frameTags": [
],
"layers": [
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
],
"slices": [
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

View File

@ -1,9 +1,4 @@
use raylib::{
core::color::Color,
math::{Rectangle, Vector2},
prelude::{RaylibDraw, RaylibDrawHandle},
texture::Texture2D,
};
use raylib::{core::color::Color, math::{Rectangle, Vector2}, prelude::{RaylibDraw, RaylibDrawHandle, RaylibMode2D}, texture::Texture2D};
/// A wrapper around an animation spritesheet
pub struct FrameAnimationWrapper {
@ -29,8 +24,10 @@ impl FrameAnimationWrapper {
/// Start the animation
pub fn start(&mut self, handle: &RaylibDrawHandle) {
if self.start_time_seconds == 0.0 {
self.start_time_seconds = handle.get_time();
}
}
/// Stop (and reset) the animation
pub fn stop(&mut self) {
@ -48,16 +45,17 @@ impl FrameAnimationWrapper {
}
/// Draw the next frame to the screen at `position`
pub fn draw(&mut self, handle: &mut RaylibDrawHandle, position: Vector2) {
pub fn draw(&mut self, handle: &mut RaylibMode2D<RaylibDrawHandle>, position: Vector2, rotation: f32) {
let frame_id = self.get_current_frame_id(handle);
self.draw_frame(handle, position, frame_id);
self.draw_frame(handle, position, rotation, frame_id);
}
/// Draw a specified frame to the screen at `position`
pub fn draw_frame(
&mut self,
handle: &mut RaylibDrawHandle,
handle: &mut RaylibMode2D<RaylibDrawHandle>,
position: Vector2,
rotation: f32,
frame_number: u32,
) {
// Determine the col number
@ -75,8 +73,20 @@ impl FrameAnimationWrapper {
width: self.size.x,
height: self.size.y,
};
let frame_dest = Rectangle {
x: position.x,
y: position.y,
width: self.size.x,
height: self.size.y,
};
// Rotation origin
let origin = Vector2 {
x: self.size.x / 2.0,
y: self.size.y / 2.0
};
// Render
handle.draw_texture_rec(&mut self.sprite_sheet, frame_box, position, Color::WHITE);
handle.draw_texture_pro(&mut self.sprite_sheet, frame_box, frame_dest, origin, rotation, Color::WHITE);
}
}

View File

@ -0,0 +1,32 @@
use std::usize;
use raylib::prelude::*;
pub struct FrameRange {
pub min: usize,
pub max: usize,
}
pub struct ComplexAnimationTool {
sprite_sheet: Texture2D,
frames_per_second: f32,
frame_size: Vector2,
sprite_sheet_size_frames: Vector2
}
impl ComplexAnimationTool {
pub fn render_loop(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, bounds: Rectangle, rotation: f32, range: &FrameRange) {
}
pub fn render_frame(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, bounds: Rectangle, rotation: f32, id: usize) {
// Convert the ID to an xy
let col_id = id % self.sprite_sheet_size_frames.x as usize;
let row_id = id / self.sprite_sheet_size_frames.y as usize;
}
}

View File

@ -1,2 +1,3 @@
pub mod audio;
pub mod animation;
pub mod complexanimation;

View File

@ -9,7 +9,7 @@ const NORMAL_PLAYER_SPEED: i32 = 3;
const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2;
const CAMERA_FOLLOW_SPEED: f32 = 0.7;
const TURN_SPEED: f32 = 0.15;
const BOOST_DECREASE_PER_SECOND: f32 = 0.75;
const BOOST_DECREASE_PER_SECOND: f32 = 0.65;
const BOOST_REGEN_PER_SECOND: f32 = 0.25;
const BREATH_DECREASE_PER_SECOND: f32 = 0.01;
@ -84,10 +84,36 @@ pub fn update_player_movement(
// Decrease the boost
game_core.player.boost_percent -= BOOST_DECREASE_PER_SECOND * dt as f32;
game_core.player.is_boosting = true;
if game_core.player.boost_percent >= 0.9 {
game_core
.resources
.player_animation_boost_charge
.start(draw_handle);
game_core.resources.player_animation_regular.stop();
game_core.player.is_boost_charging = true;
} else {
game_core.resources.player_animation_boost_charge.stop();
game_core
.resources
.player_animation_boost
.start(draw_handle);
game_core.player.is_boost_charging = false;
}
} else {
// Set the speed multiplier
speed_multiplier = NORMAL_PLAYER_SPEED as f32;
// Reset boost animation
game_core.player.is_boosting = false;
game_core.player.is_boost_charging = false;
game_core.resources.player_animation_boost_charge.stop();
game_core.resources.player_animation_boost.stop();
game_core
.resources
.player_animation_regular
.start(draw_handle);
// Handle boost regen
if !user_request_boost {
game_core.player.boost_percent = (game_core.player.boost_percent
@ -104,6 +130,9 @@ pub fn update_player_movement(
let player_real_movement = game_core.player.direction * speed_multiplier;
if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
game_core.player.position += player_real_movement;
game_core.player.is_moving = true;
} else {
game_core.player.is_moving = false;
}
// Move the camera to follow the player
@ -139,7 +168,7 @@ pub fn render_player(context_2d: &mut RaylibMode2D<RaylibDrawHandle>, game_core:
x: player.position.x as i32 as f32,
y: player.position.y as i32 as f32,
},
boost_ring_max_radius ,
boost_ring_max_radius,
boost_ring_max_radius + 1.0,
0,
(360.0 * player.breath_percent) as i32,
@ -147,16 +176,31 @@ pub fn render_player(context_2d: &mut RaylibMode2D<RaylibDrawHandle>, game_core:
TRANSLUCENT_WHITE_96,
);
// TODO: tmp rect
context_2d.draw_rectangle_pro(
Rectangle {
x: player.position.x,
y: player.position.y,
width: player.size.x,
height: player.size.y,
},
player.size / 2.0,
player_rotation.to_degrees() + 90.0,
Color::BLACK,
// Render the player based on what is happening
if player.is_boost_charging {
game_core.resources.player_animation_boost_charge.draw(
context_2d,
player.position,
player_rotation.to_degrees() - 90.0,
);
} else if player.is_boosting {
game_core.resources.player_animation_boost.draw(
context_2d,
player.position,
player_rotation.to_degrees() - 90.0,
);
} else if player.is_moving {
game_core.resources.player_animation_regular.draw(
context_2d,
player.position,
player_rotation.to_degrees() - 90.0,
);
} else {
game_core.resources.player_animation_regular.draw_frame(
context_2d,
player.position,
player_rotation.to_degrees() - 90.0,
0,
);
}
}

View File

@ -9,7 +9,10 @@ pub struct Player {
pub size: Vector2,
pub coins: u32,
pub boost_percent: f32,
pub breath_percent: f32
pub breath_percent: f32,
pub is_moving: bool,
pub is_boosting: bool,
pub is_boost_charging: bool
}
impl Player {

View File

@ -1,19 +1,61 @@
use failure::Error;
use raylib::{RaylibHandle, RaylibThread, texture::{Image, Texture2D}};
use raylib::{
math::Vector2,
texture::{Image, Texture2D},
RaylibHandle, RaylibThread,
};
use crate::lib::wrappers::animation::FrameAnimationWrapper;
/// This struct contains all textures and sounds that must be loaded into (V)RAM at the start of the game
pub struct GlobalResources {
// Branding
pub game_logo: Texture2D
pub game_logo: Texture2D,
// Player
pub player_animation_regular: FrameAnimationWrapper,
pub player_animation_boost_charge: FrameAnimationWrapper,
pub player_animation_boost: FrameAnimationWrapper,
}
impl GlobalResources {
/// Load all resources. **THIS WILL HANG!**
pub fn load_all(raylib: &mut RaylibHandle, thread: &RaylibThread) -> Result<GlobalResources, String> {
pub fn load_all(
raylib: &mut RaylibHandle,
thread: &RaylibThread,
) -> Result<GlobalResources, String> {
Ok(GlobalResources {
game_logo: raylib.load_texture_from_image(&thread, &Image::load_image("./assets/img/logos/game-logo.png")?)?
game_logo: raylib.load_texture_from_image(
&thread,
&Image::load_image("./assets/img/logos/game-logo.png")?,
)?,
player_animation_regular: FrameAnimationWrapper::new(
raylib.load_texture_from_image(
&thread,
&Image::load_image("./assets/img/character/diveNormal.png")?,
)?,
Vector2 { x: 11.0, y: 21.0 },
8,
100 / 8,
),
player_animation_boost_charge: FrameAnimationWrapper::new(
raylib.load_texture_from_image(
&thread,
&Image::load_image("./assets/img/character/diveStrokeCharge.png")?,
)?,
Vector2 { x: 11.0, y: 21.0 },
21,
100 / 4,
),
player_animation_boost: FrameAnimationWrapper::new(
raylib.load_texture_from_image(
&thread,
&Image::load_image("./assets/img/character/diveStroke.png")?,
)?,
Vector2 { x: 17.0, y: 21.0 },
21,
30,
),
})
}
}