use crate::{
general::{color::Color, direction::Direction},
gl_utils::{
gl_texture::LoadableTexture, gl_texture::Texture,
shader_creator::ShaderProgram,
},
math::matrix::{IdentityMatrix, Matrix},
shapes::shape::Shape,
};
use super::drawable::Drawable;
use std::marker::PhantomData;
#[derive(Debug, Clone)]
pub struct Sprite<'a, TShape>
where
TShape: Shape + 'a,
{
shape: TShape,
direction: Direction,
pub name: String,
texture: Texture,
phantom: PhantomData<&'a TShape>,
transformation: Matrix<f32>,
}
impl<'a, TShape: 'a> Sprite<'a, TShape>
where
TShape: Shape + 'a,
{
pub fn new(shape: TShape, texture: Texture) -> Sprite<'a, TShape> {
Sprite {
shape,
name: texture.image_name.to_owned(),
direction: Direction::Stationary,
texture,
phantom: PhantomData,
transformation: Matrix::<f32>::generate_identity(4),
}
}
pub fn with_transformation(
shape: TShape,
texture: Texture,
trans: Matrix<f32>,
) -> Sprite<'a, TShape> {
Sprite {
shape,
direction: Direction::Stationary,
name: texture.image_name.to_owned(),
texture,
phantom: PhantomData,
transformation: trans,
}
}
pub fn move_sprite(&mut self, direction: Direction, amount: f32) {
match direction {
Direction::Right => {
self.move_right(amount);
}
Direction::Left => {
self.move_left(amount);
}
Direction::Up => {
self.move_up(amount);
}
Direction::Down => {
self.move_down(amount);
}
Direction::UpRight => {
self.move_right(amount);
self.move_up(amount);
}
Direction::UpLeft => {
self.move_left(amount);
self.move_up(amount);
}
Direction::DownRight => {
self.move_right(amount);
self.move_down(amount);
}
Direction::DownLeft => {
self.move_left(amount);
self.move_down(amount);
}
_ => {}
}
}
pub fn flip_vertical(&mut self) {
self.shape.flip_texture_corners_y()
}
pub fn flip_horizontal(&mut self) {
self.shape.flip_texture_corners_x()
}
pub fn transform(&mut self, transformation_matrix: Matrix<f32>) {
assert!(
transformation_matrix.get_num_rows() == 4
&& transformation_matrix.get_num_columns() == 4,
"Not a valid transformation_matrix"
);
self.transformation = transformation_matrix;
}
pub fn load_texture(&mut self) {
self.texture.load_texture();
}
pub fn set_x(&mut self, x: f32) {
self.shape.set_x(x);
}
pub fn set_y(&mut self, y: f32) {
self.shape.set_y(y);
}
pub fn get_x(&self) -> f32 {
self.shape.get_x()
}
pub fn get_y(&self) -> f32 {
self.shape.get_y()
}
pub fn get_height(&self) -> f32 {
self.shape.get_height()
}
pub fn get_width(&self) -> f32 {
self.shape.get_width()
}
pub fn move_up(&mut self, amount: f32) -> bool {
let new_amount = self.shape.get_y() + amount;
if new_amount >= 0.8 {
return false;
}
self.shape.set_y(new_amount);
return true;
}
pub fn move_down(&mut self, amount: f32) -> bool {
let new_amount = self.shape.get_y() - amount;
if new_amount <= -0.7 {
return false;
}
self.shape.set_y(new_amount);
return true;
}
pub fn move_right(&mut self, amount: f32) -> bool {
let new_amount = self.shape.get_x() + amount;
if new_amount > 0.7 {
return false;
}
self.shape.set_x(new_amount);
return true;
}
pub fn set_color_overlay(&mut self, color: Color) {
self.shape.set_color(color);
}
pub fn move_left(&mut self, amount: f32) -> bool {
let new_amount = self.shape.get_x() - amount;
if new_amount <= -1.0 {
return false;
}
self.shape.set_x(new_amount);
return true;
}
}
impl<'a, TShape> Drawable<'a> for Sprite<'a, TShape>
where
TShape: Shape + 'a,
{
fn set_texture_uniform(&'a self, program: &ShaderProgram) -> () {
self.texture.set_uniform(program);
}
fn get_corner_count(&'a self) -> i32 {
self.shape.get_coordinate_corners().len() as i32
}
fn get_elements(&self) -> Vec<i32> {
return vec![0, 1, 2, 2, 3, 0];
}
fn load_texture(&'a self) -> () {
self.texture.load_texture();
}
fn get_vertices(&self) -> Vec<f32> {
let mut vertices = Vec::<f32>::new();
let shape = &self.shape;
let coordinate_corners = &self.shape.get_coordinate_corners();
let texture_corners = &self.shape.get_texture_corners();
for i in 0..4 {
let [x, y] = coordinate_corners[i];
vertices.push(x);
vertices.push(y);
vertices.push(shape.get_color().r);
vertices.push(shape.get_color().g);
vertices.push(shape.get_color().b);
vertices.push(shape.get_color().a);
let [tx, ty] = texture_corners[i];
vertices.push(tx);
vertices.push(ty);
vertices.push(self.texture.texture_id as f32);
for entry in self.transformation.get_inner_ptr() {
vertices.push(entry.to_owned());
}
}
return vertices;
}
}
impl<'a, TShape> From<&Sprite<'a, TShape>> for Sprite<'a, TShape>
where
TShape: Shape + Clone,
{
fn from(sprite_ref: &Sprite<'a, TShape>) -> Self {
Sprite::new(sprite_ref.shape.to_owned(), sprite_ref.texture.to_owned())
}
}