Vector cleanup

master
Mark 2023-12-22 17:24:53 -08:00
parent a511a06709
commit 6e13c91d37
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
10 changed files with 97 additions and 197 deletions

View File

@ -1,17 +1,19 @@
use crate::{physics::Cartesian, Camera, Sprite}; use cgmath::{Deg, Point2};
use crate::{physics::Pfloat, Camera, Sprite, Spriteable};
pub struct Doodad { pub struct Doodad {
pub sprite: String, pub sprite: String,
pub pos: Cartesian, pub pos: Point2<Pfloat>,
} }
impl Doodad { impl Spriteable for Doodad {
pub fn sprite(&self, camera: &Camera) -> Sprite { fn sprite(&self, camera: &Camera) -> Sprite {
let p = self.pos - camera.pos;
return Sprite { return Sprite {
position: (p.x, p.y), position: self.pos,
camera: camera.pos,
name: self.sprite.clone(), name: self.sprite.clone(),
angle: 0.0, angle: Deg { 0: 0.0 },
}; };
} }
} }

View File

@ -1,6 +1,5 @@
use winit::event::{ElementState, VirtualKeyCode}; use winit::event::{ElementState, VirtualKeyCode};
// TODO: no boolean modification (no pub)
pub struct InputStatus { pub struct InputStatus {
pub key_left: bool, pub key_left: bool,
pub key_right: bool, pub key_right: bool,

View File

@ -1,5 +1,5 @@
use anyhow::Result; use anyhow::Result;
use physics::Cartesian; use cgmath::{Deg, Point2};
use winit::{ use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
@ -16,29 +16,33 @@ mod system;
use crate::{ use crate::{
doodad::Doodad, doodad::Doodad,
inputstatus::InputStatus, inputstatus::InputStatus,
physics::Pfloat,
render::GPUState, render::GPUState,
ship::{Ship, ShipKind}, ship::{Ship, ShipKind},
system::System, system::System,
}; };
struct Camera { struct Camera {
pos: Cartesian, pos: Point2<Pfloat>,
} }
impl Camera { trait Spriteable {
fn new() -> Self { fn sprite(&self, camera: &Camera) -> Sprite;
Camera {
pos: Cartesian::new(0.0, 0.0),
}
}
} }
struct Sprite { struct Sprite {
// Image to use // Name of the sprite to draw
name: String, name: String,
// World position
position: (f64, f64), // This object's position, in world coordinates.
angle: f32, position: Point2<Pfloat>,
// This sprite's rotation
// (relative to north, measured ccw)
angle: Deg<Pfloat>,
// The camera we want to draw this sprite from, in world coordinates
camera: Point2<Pfloat>,
} }
struct Game { struct Game {
@ -54,8 +58,10 @@ impl Game {
Game { Game {
last_update: Instant::now(), last_update: Instant::now(),
input: InputStatus::new(), input: InputStatus::new(),
player: Ship::new(ShipKind::Gypsum, Cartesian::new(0.0, 0.0)), player: Ship::new(ShipKind::Gypsum, (0.0, 0.0).into()),
camera: Camera::new(), camera: Camera {
pos: (0.0, 0.0).into(),
},
system: System::new(), system: System::new(),
} }
} }
@ -65,7 +71,7 @@ impl Game {
} }
fn update(&mut self) { fn update(&mut self) {
let t = self.last_update.elapsed().as_secs_f64(); let t: Pfloat = self.last_update.elapsed().as_secs_f32();
println!("{:.02}", 1.0 / t); println!("{:.02}", 1.0 / t);
if self.input.key_thrust { if self.input.key_thrust {
@ -73,11 +79,11 @@ impl Game {
} }
if self.input.key_right { if self.input.key_right {
self.player.body.rot(15.0 * t); self.player.body.rot(Deg { 0: 15.0 } * t);
} }
if self.input.key_left { if self.input.key_left {
self.player.body.rot(-15.0 * t); self.player.body.rot(Deg { 0: -15.0 } * t);
} }
self.player.body.tick(t); self.player.body.tick(t);

View File

@ -1,46 +1,51 @@
use crate::physics::Cartesian; use super::Pfloat;
use cgmath::{Angle, Deg, Point2, Vector2};
pub struct PhysBody { pub struct PhysBody {
pub pos: Cartesian, pub pos: Point2<Pfloat>,
pub vel: Cartesian, pub vel: Vector2<Pfloat>,
pub mass: f64, pub mass: Pfloat,
pub angle: f64, // In degrees pub angle: Deg<Pfloat>,
} }
impl PhysBody { impl PhysBody {
pub fn new(pos: Cartesian) -> Self { pub fn new(pos: Point2<Pfloat>) -> Self {
return PhysBody { return PhysBody {
pos, pos,
vel: Cartesian::new(0.0, 0.0), vel: (0.0, 0.0).into(),
mass: 0.3, mass: 0.3,
angle: 0.0, angle: Deg { 0: 0.0 },
}; };
} }
/// Calculate the state of this body after t seconds. /// Calculate the position of this body after t seconds.
pub fn tick(&mut self, t: f64) { pub fn tick(&mut self, t: Pfloat) {
self.pos += self.vel * t; self.pos += self.vel * t;
} }
/// Apply an instantaneous force to this object /// Apply an instantaneous force to this object
pub fn force(&mut self, v: Cartesian) { pub fn force(&mut self, v: Vector2<Pfloat>) {
self.vel += v / self.mass; self.vel += v / self.mass;
} }
/// Apply force in the direction this object is pointing. /// Apply a force in the direction this object is pointing.
pub fn thrust(&mut self, f: f64) { pub fn thrust(&mut self, f: Pfloat) {
let l = Cartesian::new( let l = Vector2 {
-self.angle.to_radians().sin(), x: -self.angle.sin(),
self.angle.to_radians().cos(), y: self.angle.cos(),
) * f; } * f;
self.force(l); self.force(l);
} }
// Rotate this object by `a` radians. // Rotate this object
pub fn rot(&mut self, a: f64) { pub fn rot(&mut self, a: Deg<Pfloat>) {
self.angle -= a; self.angle -= a;
if self.angle.abs() > 180.0 {
self.angle -= self.angle.signum() * 360.0; // Wrap angles
if self.angle.0.abs() > 180.0 {
self.angle -= Deg {
0: self.angle.0.signum() * 360.0,
};
} }
} }
} }

View File

@ -1,116 +0,0 @@
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
#[derive(Debug, Clone, Copy)]
pub struct Cartesian {
pub x: f64,
pub y: f64,
}
impl Cartesian {
pub fn new(x: f64, y: f64) -> Self {
Cartesian { x, y }
}
/*
pub fn norm(&self) -> f64 {
return (self.x * self.x + self.y * self.y).sqrt();
}
*/
}
impl From<(u32, u32)> for Cartesian {
fn from(value: (u32, u32)) -> Self {
Cartesian {
x: value.0 as f64,
y: value.1 as f64,
}
}
}
impl Add for Cartesian {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl AddAssign for Cartesian {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl Sub for Cartesian {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
impl SubAssign for Cartesian {
fn sub_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl Mul for Cartesian {
type Output = Self;
fn mul(self, other: Self) -> Self {
Self {
x: self.x * other.x,
y: self.y * other.y,
}
}
}
impl MulAssign for Cartesian {
fn mul_assign(&mut self, rhs: Self) {
self.x *= rhs.x;
self.y *= rhs.y;
}
}
impl Mul<f64> for Cartesian {
type Output = Cartesian;
fn mul(self, rhs: f64) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl MulAssign<f64> for Cartesian {
fn mul_assign(&mut self, rhs: f64) {
self.x *= rhs;
self.y *= rhs;
}
}
impl Div<f64> for Cartesian {
type Output = Cartesian;
fn div(self, rhs: f64) -> Self::Output {
Self {
x: self.x / rhs,
y: self.y / rhs,
}
}
}
impl DivAssign<f64> for Cartesian {
fn div_assign(&mut self, rhs: f64) {
self.x /= rhs;
self.y /= rhs;
}
}

View File

@ -1,7 +1,8 @@
mod body; mod body;
mod cartesian;
mod polar; mod polar;
// What kind of float shoud we use for physics?
pub type Pfloat = f32;
pub use body::PhysBody; pub use body::PhysBody;
pub use cartesian::Cartesian;
pub use polar::Polar; pub use polar::Polar;

View File

@ -1,17 +1,18 @@
use super::Cartesian; use super::Pfloat;
use cgmath::{Angle, Deg, EuclideanSpace, Point2};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Polar { pub struct Polar {
pub center: Cartesian, pub center: Point2<Pfloat>,
pub radius: f64, pub radius: Pfloat,
pub angle: f64, pub angle: Deg<Pfloat>,
} }
impl Into<Cartesian> for Polar { impl Polar {
fn into(self) -> Cartesian { pub fn to_cartesian(self) -> Point2<Pfloat> {
return Cartesian::new( return Point2 {
self.radius * self.angle.sin(), x: self.radius * self.angle.sin(),
self.radius * self.angle.cos(), y: self.radius * self.angle.cos(),
) + self.center; } + self.center.to_vec();
} }
} }

View File

@ -1,6 +1,6 @@
use anyhow::Result; use anyhow::Result;
use bytemuck; use bytemuck;
use cgmath::{Deg, Matrix4, Point2, Vector3}; use cgmath::{Deg, EuclideanSpace, Matrix4, Point2, Vector3};
use std::{iter, mem}; use std::{iter, mem};
use wgpu::{self, util::DeviceExt}; use wgpu::{self, util::DeviceExt};
use winit::{self, window::Window}; use winit::{self, window::Window};
@ -104,7 +104,7 @@ struct Transform {
pos: Point2<f32>, pos: Point2<f32>,
aspect: f32, // width / height aspect: f32, // width / height
scale: f32, scale: f32,
rotate: f32, // Around this object's center, in degrees measured ccw from vertical rotate: Deg<f32>, // Around this object's center, in degrees measured ccw from vertical
} }
impl Transform { impl Transform {
@ -115,7 +115,7 @@ impl Transform {
// Our mesh starts at (0, 0), so this will rotate around the object's center. // Our mesh starts at (0, 0), so this will rotate around the object's center.
// Note that we translate AFTER scaling. // Note that we translate AFTER scaling.
let rotate = Matrix4::from_angle_z(Deg { 0: self.rotate }); let rotate = Matrix4::from_angle_z(self.rotate);
let translate = Matrix4::from_translation(Vector3 { let translate = Matrix4::from_translation(Vector3 {
x: self.pos.x, x: self.pos.x,
@ -402,17 +402,14 @@ impl GPUState {
// TODO: warning when too many sprites are drawn. // TODO: warning when too many sprites are drawn.
let mut instances: Vec<Instance> = Vec::new(); let mut instances: Vec<Instance> = Vec::new();
for s in sprites { for s in sprites {
let mut pos: Point2<f32> = (s.position.0 as f32, s.position.1 as f32).into(); // Compute position on screen
let screen_pos: Point2<f32> = (s.position - s.camera.to_vec()) / 400.0;
// TODO: dynamic
pos.x /= 400.0;
pos.y /= 400.0;
let texture = self.texture_array.get_texture(&s.name[..]); let texture = self.texture_array.get_texture(&s.name[..]);
instances.push(Instance { instances.push(Instance {
transform: Transform { transform: Transform {
pos, pos: screen_pos,
aspect: texture.aspect / screen_aspect, aspect: texture.aspect / screen_aspect,
scale: 0.25, scale: 0.25,
rotate: s.angle, rotate: s.angle,

View File

@ -1,7 +1,10 @@
use crate::physics::Cartesian; use cgmath::Point2;
use crate::physics::Pfloat;
use crate::physics::PhysBody; use crate::physics::PhysBody;
use crate::Camera; use crate::Camera;
use crate::Sprite; use crate::Sprite;
use crate::Spriteable;
pub enum ShipKind { pub enum ShipKind {
Gypsum, Gypsum,
@ -21,20 +24,21 @@ pub struct Ship {
} }
impl Ship { impl Ship {
pub fn new(kind: ShipKind, pos: Cartesian) -> Self { pub fn new(kind: ShipKind, pos: Point2<Pfloat>) -> Self {
Ship { Ship {
body: PhysBody::new(pos), body: PhysBody::new(pos),
kind, kind,
} }
} }
}
pub fn sprite(&self, camera: &Camera) -> Sprite { impl Spriteable for Ship {
let p = self.body.pos - camera.pos; fn sprite(&self, camera: &Camera) -> Sprite {
return Sprite { return Sprite {
position: (p.x, p.y), position: self.body.pos,
camera: camera.pos,
name: self.kind.sprite().to_owned(), name: self.kind.sprite().to_owned(),
angle: self.body.angle as f32, angle: self.body.angle,
}; };
} }
} }

View File

@ -1,4 +1,5 @@
use crate::{physics::Cartesian, physics::Polar, Camera, Doodad, Sprite}; use crate::{physics::Polar, Camera, Doodad, Sprite, Spriteable};
use cgmath::Deg;
pub struct System { pub struct System {
bodies: Vec<Doodad>, bodies: Vec<Doodad>,
@ -9,22 +10,22 @@ impl System {
let mut s = System { bodies: Vec::new() }; let mut s = System { bodies: Vec::new() };
s.bodies.push(Doodad { s.bodies.push(Doodad {
pos: Cartesian::new(0.0, 0.0), pos: (0.0, 0.0).into(),
sprite: "a0".to_owned(), sprite: "a0".to_owned(),
}); });
s.bodies.push(Doodad { s.bodies.push(Doodad {
pos: Polar { pos: Polar {
center: Cartesian::new(0.0, 0.0), center: (0.0, 0.0).into(),
radius: 300.0, radius: 300.0,
angle: 31.0, angle: Deg { 0: 31.0 },
} }
.into(), .to_cartesian(),
sprite: "earth".to_owned(), sprite: "earth".to_owned(),
}); });
s.bodies.push(Doodad { s.bodies.push(Doodad {
pos: Cartesian::new(1000.0, 1000.0), pos: (1000.0, 1000.0).into(),
sprite: "small".to_owned(), sprite: "small".to_owned(),
}); });