renamed renderer, and worked more on the anicode

renamed spritesheet.rs to animation.rs, and i will be putting all of the
animation related code in there
pull/4/head
Milk.H 2024-04-26 09:46:29 +01:00
parent ef8760a70f
commit 8cee2b5661
Signed by: milk
GPG Key ID: 94C7CB70FFF80593
6 changed files with 292 additions and 64 deletions

View File

@ -1,6 +0,0 @@
/// Render Module
/// all of the code pertaining to Rendering will be written here
/// this also includes all Bevy Components and Resources relating to rendering
pub mod shader;
pub mod spritesheet;

View File

@ -1,57 +0,0 @@
use glow::HasContext;
use std::path::Path;
/// SpriteSheet Struct for Representing a Spritesheet
/// feel free to clone
#[derive(Clone)]
pub struct SpriteSheet
{
texture_id: glow::NativeTexture,
// NOTE where the spritesheet is saved
path: String,
cuts_x: u32,
// NOTE possibly making it check vertically
//cuts_y: u32,
// NOTE maybe add an offset for each sprite
// offsets: Vec<cgmath::Vec2<f32>>
// NOTE Hold frames, if 0 it means it will be displayed for only 1 frame, 1 means it will be held for 2 etc
// hold: Vec<u32>
}
/// load texture from a filepath and return the ID
/// NOTE this function does not check if the texture has already loaded
fn texture_from_file(path: &str, gl: &glow::Context) -> glow::NativeTexture
{
let texture_id;
unsafe {
texture_id = gl.create_texture().unwrap();
let img = image::open(&Path::new(&path)).expect("texture failed to load");
let img = img.flipv();
let format = match img {
image::DynamicImage::ImageLuma8(_) => glow::RED,
image::DynamicImage::ImageLumaA8(_) => glow::RG,
image::DynamicImage::ImageRgb8(_) => glow::RGB,
image::DynamicImage::ImageRgba8(_) => glow::RGBA,
_ => panic!("unknown image format at {path}")
};
let data = img.as_bytes();
gl.bind_texture(glow::TEXTURE_2D, Some(texture_id));
gl.tex_image_2d(glow::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
0, format, glow::UNSIGNED_BYTE, Some(&data));
gl.generate_mipmap(glow::TEXTURE_2D);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST_MIPMAP_NEAREST as i32);
}
texture_id
}

View File

@ -17,7 +17,7 @@ use glutin::{prelude::*, context::Version};
use glutin_winit::{self, GlWindow};
use glutin::display::GetGlDisplay;
pub mod Renderer;
pub mod renderer;
fn main() {
// NOTE initialization code here

186
src/renderer/animation.rs Normal file
View File

@ -0,0 +1,186 @@
use glow::HasContext;
use std::{collections::HashMap, path::Path};
use bevy_ecs::prelude::*;
/// SpriteSheet Struct for Representing a Spritesheet
///
/// WARNING while it is very fast to clone the spritesheet, it is assumed that that
/// the spritesheet object is the only one of it's kind, when it gets dropped it will unload
/// the underlying texture
#[derive(Clone)]
pub struct SpriteSheet
{
texture_id: glow::NativeTexture,
// NOTE where the spritesheet is saved
// really only use here is just to stop saving copies
path: String,
// NOTE amount of Horizontal Cuts, a spritesheet with 5 frames of animation will have 5 horizontal cuts
cuts_x: u32,
// NOTE possibly making it check vertically for saving multiple animations in one Texture?
//cuts_y: u32,
// NOTE maybe add an offset for each sprite
// offsets: Vec<cgmath::Vec2<f32>>
// NOTE Hold frames, if 0 it means it will be displayed for only 1 frame, 1 means it will be held for 2 etc
hold: Vec<u32>
}
impl SpriteSheet
{
/// creates a new Spritesheet
pub fn new(path: &str, gl: &glow::Context, cuts_x: u32, hold: Vec<u32>) -> Self
{
let texture_id = texture_from_file(path, gl);
SpriteSheet
{
texture_id,
path: String::from(path),
cuts_x,
hold
}
}
}
/// Animation Component
///
/// currently it's using a hashmap with String keys
///
/// current also uses a String to identify the spritesheet
#[derive(Component)]
pub struct Animator
{
// NOTE sprite sheets in a hashmap
pub spritesheets: HashMap<AnimationType, SpriteSheet>,
// NOTE current is possibly unneeded as it would be the job of a different System/Component to manage that
pub current: AnimationType
}
// TODO should pre-jump and jump frames be seperate?
// WIP all the animations that *could* show up, most of the air ones are expected to exist
// However just because an AnimationType is in this list doesn't mean it has to exist or be loaded in
pub enum AnimationType{
// Basic Animations, universal
Idle,
StandUp,
CrouchDown, // <- this is the animation of crouching down after standing
Crouch, // <- this is for the loop of being crouching
WalkingForward,
WalkingBackward,
Guard,
CrouchGuard,
AirGuard,
JumpNeutral,
JumpBackward,
JumpForward,
Fall,
// Extra Movement animations, not universal
AirDash,
AirBackDash,
Running,
BackDashing,
// Normals, Universal
StandLP,
StandMP,
StandHP,
StandLK,
StandMK,
StandHK,
CrouchLP,
CrouchMP,
CrouchHP,
CrouchLK,
CrouchMK,
CrouchHK,
AirLP,
AirMP,
AirHP,
AirLK,
AirMK,
AirHK,
// hit animations, expect more complicated ones to show up, Universal
CrouchHit,
StandHit,
AirHit,
// command Normals, maybe would be Better to have them in the Specials
CommandNormal01,
CommandNormal02,
CommandNormal03,
CommandNormal04,
CommandNormal05,
CommandNormal06,
CommandNormal07,
CommandNormal08,
CommandNormal09,
CommandNormal10,
// Specials, any Miscallenous Animations will also end up here
// This includes fireballs
// Rekkas will be seperated into different Animations
Special01,
Special02,
Special03,
Special04,
Special05,
Special06,
Special07,
Special08,
Special09,
Special10,
Special11,
Special12,
Special13,
Special14,
Special15,
// Supers
Super01,
Super02,
Super03,
Super04,
Super05,
}
/// load texture from a filepath and return the ID
///
/// NOTE this function does not check if the texture has already loaded
fn texture_from_file(path: &str, gl: &glow::Context) -> glow::NativeTexture
{
let texture_id;
unsafe {
texture_id = gl.create_texture().unwrap();
let img = image::open(&Path::new(&path)).expect("texture failed to load");
let img = img.flipv();
let format = match img {
image::DynamicImage::ImageLuma8(_) => glow::RED,
image::DynamicImage::ImageLumaA8(_) => glow::RG,
image::DynamicImage::ImageRgb8(_) => glow::RGB,
image::DynamicImage::ImageRgba8(_) => glow::RGBA,
_ => panic!("unknown image format at {path}")
};
let data = img.as_bytes();
gl.bind_texture(glow::TEXTURE_2D, Some(texture_id));
gl.tex_image_2d(glow::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
0, format, glow::UNSIGNED_BYTE, Some(&data));
gl.generate_mipmap(glow::TEXTURE_2D);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST_MIPMAP_NEAREST as i32);
}
texture_id
}

103
src/renderer/mod.rs Normal file
View File

@ -0,0 +1,103 @@
/// Render Module
///
/// all of the code pertaining to Rendering will be written here
///
/// this also includes all Bevy Components and Resources relating to rendering
pub mod shader;
pub mod animation;
use core::slice;
use bevy_ecs::prelude::*;
use glow::HasContext;
/// OpenGL context Resource
#[derive(Resource)]
pub struct GL(pub std::sync::Arc<glow::Context>);
/// Default Vertex Array Object, Every 2d Square object with a texture would only need this
#[derive(Resource)]
pub struct DefaultVAO(pub glow::NativeVertexArray);
/// Default Shader, this will be much more likely to be different
///
/// for all systems The Default Shader is assumed to be the animation shader located at data/shaders/AnimationShader
#[derive(Resource)]
pub struct DefaultShader(pub shader::Shader);
// NOTE systems start here
// a square with texture coordinates
//
// in a line
const VERTICES: [f32; 20] = [
// X Y Z xTex yTex
0.5, 0.5, 0.0, 1.0, 1.0,
0.5, -0.5, 0.0, 1.0, 0.0,
-0.5, -0.5, 0.0, 0.0, 0.0,
-0.5, 0.5, 0.0, 0.0, 1.0
];
// indices for the
const INDICES: [u32; 6] = [
0, 1, 3,
1, 2, 3
];
pub fn initialize_defaults(mut commands: Commands, gl: Res<GL>)
{
// create vertex array
let vao = unsafe {
Some(gl.0.create_vertex_array().unwrap())
};
unsafe {
// create buffers
let vbo = Some(gl.0.create_buffer().unwrap());
let ebo = Some(gl.0.create_buffer().unwrap());
gl.0.bind_buffer(glow::ARRAY_BUFFER, vbo);
// pass buffers
let data = core::slice::from_raw_parts(
VERTICES.as_ptr() as *const u8,
VERTICES.len() * core::mem::size_of::<f32>()
);
gl.0.named_buffer_data_u8_slice(vbo.unwrap(), data, glow::STATIC_DRAW);
gl.0.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, ebo);
let data = slice::from_raw_parts(
INDICES.as_ptr() as *const u8,
INDICES.len() * core::mem::size_of::<u32>(),
);
gl.0.named_buffer_data_u8_slice(ebo.unwrap(), data, glow::STATIC_DRAW);
let size = core::mem::size_of::<f32>() as i32;
// Vertex Info
gl.0.enable_vertex_attrib_array(0);
gl.0.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, size*5, 0);
// Texture Coordinates
gl.0.enable_vertex_attrib_array(2);
gl.0.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, size*5, size*3);
// unbind buffers and arrays
gl.0.bind_buffer(glow::ARRAY_BUFFER, None);
gl.0.bind_vertex_array(None);
}
// insert Default Vao
commands.insert_resource(DefaultVAO(vao.unwrap()));
let shader = shader::Shader::new("AnimationShader", &gl.0);
commands.insert_resource(DefaultShader(shader));
}

View File

@ -20,11 +20,13 @@ pub struct Shader {
impl Shader
{
/// Shader Constructor, will read, Compile and Create a GLSL Program for use
///
/// currently panics if the files can't be found or the shader is wrong
///
///
/// # Example
/// `let shader = Shader::new("Example", &gl);`
///
/// if the String given was "Example" the Program expects both shaders to be in the directory "data/shaders/Example/"
/// with the vertex shader being called "shader.vert" and fragment "shader.frag"
pub fn new(path: &str, gl: &glow::Context) -> Shader