feat: restructure draw and movement

This commit is contained in:
uttarayan21
2024-06-19 20:24:26 +05:30
parent 046724c860
commit 39c1096b87
7 changed files with 138 additions and 62 deletions
+35
View File
@@ -0,0 +1,35 @@
pub trait Drawable {
fn draw(&self);
}
impl<T: Drawable> Drawable for Box<T> {
fn draw(&self) {
self.as_ref().draw();
}
}
impl<T: Drawable> Drawable for Vec<T> {
fn draw(&self) {
self.iter().for_each(|item| item.draw());
}
}
impl<T: Drawable> Drawable for Option<T> {
fn draw(&self) {
if let Some(item) = self {
item.draw();
}
}
}
impl<T: Drawable> Drawable for &T {
fn draw(&self) {
(*self).draw();
}
}
// impl<T: Drawable, I: Iterator<Item = T>> Drawable for I {
// fn draw(&self) {
// self.for_each(|item| item.draw());
// }
// }
+30
View File
@@ -0,0 +1,30 @@
use crate::{draw::Drawable, enemy::Enemy, gun::Bullet, player::Player};
pub enum Entity {
Player(Player),
Enemies(Enemy),
Bullet(Bullet),
Custom(Box<dyn Drawable>),
}
impl core::fmt::Debug for Entity {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Entity::Player(player) => write!(f, "Entity::Player({:?})", player),
Entity::Enemies(enemy) => write!(f, "Entity::Enemies({:?})", enemy),
Entity::Bullet(bullet) => write!(f, "Entity::Bullet({:?})", bullet),
Entity::Custom(_) => write!(f, "Entity::Custom(...)"),
}
}
}
impl Drawable for Entity {
fn draw(&self) {
match self {
Entity::Player(player) => player.draw(),
Entity::Enemies(enemy) => enemy.draw(),
Entity::Bullet(bullet) => bullet.draw(),
Entity::Custom(drawable) => drawable.draw(),
}
}
}
+24 -34
View File
@@ -1,46 +1,36 @@
use macroquad::prelude::*; use macroquad::prelude::*;
use crate::movement::*;
/// The shot made by a player or an enemy /// The shot made by a player or an enemy
#[derive(Debug, Default)] #[derive(Debug, Clone, Copy)]
pub struct Bullet { pub struct Bullet {
/// The position of the bullet movement: Movement,
pos: Vec2,
/// The bullet travels at constant speed
speed: f32,
/// The damage the bullet does /// The damage the bullet does
damage: u32, damage: u32,
/// Source of the bullet
source: Vec2,
} }
impl Bullet { impl Bullet {
pub fn new(pos: Vec2, speed: f32, damage: u32, source: Vec2) -> Self {
Self {
pos,
speed,
damage,
source,
}
}
pub fn draw(&self) { pub fn draw(&self) {
draw_circle(self.pos.x, self.pos.y, 4.0, GREEN); draw_circle(self.movement.pos.x, self.movement.pos.y, 4.0, GREEN);
} }
}
/// Every tick the bullet moves in the direction it was shot from source by speed
pub fn tick(&mut self) { pub struct Gun {
self.pos += self.source.normalize() * self.speed; pub direction: Vec2,
} pub bullets: Vec<Bullet>,
}
/// Spawns a bullet to the mouse position from source
pub fn shoot(source: Vec2) -> Self { impl Gun {
let mouse = mouse_position(); pub fn shoot(&mut self, pos: Vec2) {
let mouse = vec2(mouse.0, mouse.1); let bullet = Bullet {
Self { movement: Movement {
pos: (source - mouse).normalize(), pos,
speed: 10.0, direction: self.direction,
damage: 10, type_: MovementType::Speed(5.0),
source, },
} damage: 10,
};
self.bullets.push(bullet);
} }
} }
+3
View File
@@ -4,6 +4,9 @@ mod enemy;
mod gun; mod gun;
mod player; mod player;
mod world; mod world;
mod movement;
mod ecs;
mod draw;
fn window_conf() -> Conf { fn window_conf() -> Conf {
Conf { Conf {
+31
View File
@@ -0,0 +1,31 @@
use macroquad::prelude::*;
#[derive(Debug, Clone, Copy)]
pub enum MovementType {
Speed(f32),
Acceleration(Vec2),
}
#[derive(Debug, Clone, Copy)]
pub struct Movement {
pub pos: Vec2,
pub direction: Vec2, // Direction of the movement normalized to 1
pub type_: MovementType,
}
impl Movement {
pub fn tick(&mut self) {
match self.type_ {
MovementType::Speed(speed) => {
self.pos += self.direction * speed;
}
MovementType::Acceleration(acceleration) => {
self.direction += acceleration;
self.direction = self.direction.normalize();
self.pos += self.direction;
}
}
}
pub fn pos(&self) -> Vec2 {
self.pos
}
}
+10 -9
View File
@@ -4,35 +4,36 @@ use macroquad::prelude::*;
pub struct Player { pub struct Player {
pub pos: Vec2, pub pos: Vec2,
pub pointing: Vec2, pub pointing: Vec2,
pub direction: Vec2,
pub velocity: Vec2, pub velocity: Vec2,
} }
impl Player { impl Player {
pub fn new(pos: Vec2, pointing: Vec2, velocity: Vec2) -> Self { pub fn new(pos: Vec2, velocity: Vec2) -> Self {
let mouse_pos = mouse_position();
let pointing = vec2(mouse_pos.0, mouse_pos.1);
let direction = (pos - pointing).normalize();
Self { Self {
pos, pos,
pointing, pointing,
direction,
velocity, velocity,
} }
} }
pub fn handle_inputs(&mut self) { pub fn handle_inputs(&mut self) {
self.handle_mouse();
let distance = self.pos.distance(self.pointing);
// increase the velocity scaled to the distance
self.velocity = (self.pointing - self.pos).normalize() * distance / 15f32;
}
pub fn handle_mouse(&mut self) {
let mouse_pos = mouse_position(); let mouse_pos = mouse_position();
self.pointing = vec2(mouse_pos.0, mouse_pos.1); self.pointing = vec2(mouse_pos.0, mouse_pos.1);
self.direction = (self.pos - self.pointing).normalize();
let distance = self.pos.distance(self.pointing);
self.velocity = self.direction * distance / 15f32;
} }
pub fn draw(&self) { pub fn draw(&self) {
draw_circle(self.pos.x, self.pos.y, 16.0, BLUE); draw_circle(self.pos.x, self.pos.y, 16.0, BLUE);
} }
pub fn move_with_velocity(&mut self) { pub fn tick(&mut self) {
self.pos += self.velocity; self.pos += self.velocity;
} }
} }
+5 -19
View File
@@ -1,6 +1,7 @@
use macroquad::prelude::*; use macroquad::prelude::*;
use miniquad::window::screen_size; use miniquad::window::screen_size;
use crate::ecs::Entity;
use crate::enemy::Enemy; use crate::enemy::Enemy;
use crate::gun::Bullet; use crate::gun::Bullet;
use crate::player::Player; use crate::player::Player;
@@ -10,36 +11,21 @@ use crate::player::Player;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct World { pub struct World {
player: Player, player: Player,
enemies: Vec<Enemy>,
bullets: Vec<Bullet>,
center: Vec2, center: Vec2,
size: Vec2, size: Vec2,
tick: u64, tick: u64,
entities: Vec<Entity>,
} }
impl World { impl World {
pub fn new() -> Self { pub fn new() -> Self {
let (x, y) = screen_size(); let (x, y) = screen_size();
let center = vec2(x / 2., y / 2.); let center = vec2(x / 2., y / 2.);
Self {
player: Player::new(center, center, center),
enemies: Vec::default(),
center,
size: vec2(x, y),
..Default::default()
}
} }
pub fn handle_inputs(&mut self) { pub fn handle_inputs(&mut self) {
self.player.handle_inputs(); self.player.handle_inputs();
} }
pub fn draw(&self) {
self.player.draw();
self.enemies.iter().for_each(|enemy| enemy.draw());
self.bullets.iter().for_each(|bullet| bullet.draw());
}
pub fn spawn_enemy(&mut self) { pub fn spawn_enemy(&mut self) {
let enemy = Enemy { let enemy = Enemy {
pos: random_vec2_in_bounds(self.size), pos: random_vec2_in_bounds(self.size),
@@ -51,7 +37,7 @@ impl World {
pub fn tick(&mut self) { pub fn tick(&mut self) {
self.tick += 1; self.tick += 1;
self.player.move_with_velocity(); self.player.tick();
let enemies_count = self.enemies.len(); let enemies_count = self.enemies.len();
if enemies_count < 10 && (macroquad::time::get_time() / (2 * enemies_count) as f64) > 1.0 { if enemies_count < 10 && (macroquad::time::get_time() / (2 * enemies_count) as f64) > 1.0 {
self.spawn_enemy(); self.spawn_enemy();
@@ -61,10 +47,10 @@ impl World {
enemy.pos += enemy.velocity; enemy.pos += enemy.velocity;
} }
for bullet in self.bullets.iter_mut() { for bullet in self.bullets.iter_mut() {
bullet.tick(); // bullet.tick();
} }
if self.tick % 12 == 0 { if self.tick % 12 == 0 {
self.bullets.push(Bullet::shoot(self.player.pos)); // self.bullets.push(Bullet::shoot(self.player.pos));
} }
} }
} }