Initial work on proper character movement
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
use bevy::math::{Vec2, primitives::Segment2d};
|
||||
|
||||
use fixed::prelude::*;
|
||||
|
||||
pub type FGi32 = fixed::FixedI32<fixed::types::extra::U16>;
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod int;
|
||||
pub mod segment;
|
||||
pub mod vec;
|
||||
@@ -0,0 +1,92 @@
|
||||
use bevy::math::{Vec2, primitives::Segment2d};
|
||||
|
||||
use fixed::prelude::*;
|
||||
|
||||
use crate::math::vec::FGVec2;
|
||||
|
||||
type FGi32 = fixed::FixedI32<fixed::types::extra::U16>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct FGSegment2d {
|
||||
point1: FGVec2,
|
||||
point2: FGVec2
|
||||
}
|
||||
|
||||
impl FGSegment2d {
|
||||
#[inline]
|
||||
pub fn new(point1: FGVec2, point2: FGVec2) -> Self {
|
||||
Self {
|
||||
point1, point2
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn point1(&self) -> FGVec2 {
|
||||
self.point1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn point2(&self) -> FGVec2 {
|
||||
self.point2
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SegmentIntersection {
|
||||
fn segment_intersection(&self, rhs: &Segment2d) -> Option<FGVec2>;
|
||||
}
|
||||
|
||||
impl SegmentIntersection for Segment2d {
|
||||
fn segment_intersection(&self, rhs: &Segment2d) -> Option<Vec2> {
|
||||
let p0 = self.point1();
|
||||
let p1 = self.point2();
|
||||
let p2 = rhs.point1();
|
||||
let p3 = rhs.point2();
|
||||
|
||||
let s1_x = p1.x - p0.x;
|
||||
let s1_y = p1.y - p0.y;
|
||||
let s2_x = p3.x - p2.x;
|
||||
let s2_y = p3.y - p2.y;
|
||||
|
||||
let denom = -s2_x * s1_y + s1_x * s2_y;
|
||||
if denom.abs() < f32::EPSILON {
|
||||
return None; // Parallel or collinear
|
||||
}
|
||||
|
||||
let s = (-s1_y * (p0.x - p2.x) + s1_x * (p0.y - p2.y)) / denom;
|
||||
let t = ( s2_x * (p0.y - p2.y) - s2_y * (p0.x - p2.x)) / denom;
|
||||
|
||||
if s >= 0.0 && s <= 1.0 && t >= 0.0 && t <= 1.0 {
|
||||
Some(Vec2::new(p0.x + (t * s1_x), p0.y + (t * s1_y)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SegmentIntersection for Segment2d {
|
||||
fn segment_intersection(&self, rhs: &Segment2d) -> Option<Vec2> {
|
||||
let p0 = self.point1();
|
||||
let p1 = self.point2();
|
||||
let p2 = rhs.point1();
|
||||
let p3 = rhs.point2();
|
||||
|
||||
let s1_x = p1.x - p0.x;
|
||||
let s1_y = p1.y - p0.y;
|
||||
let s2_x = p3.x - p2.x;
|
||||
let s2_y = p3.y - p2.y;
|
||||
|
||||
let denom = -s2_x * s1_y + s1_x * s2_y;
|
||||
if denom.abs() < f32::EPSILON {
|
||||
return None; // Parallel or collinear
|
||||
}
|
||||
|
||||
let s = (-s1_y * (p0.x - p2.x) + s1_x * (p0.y - p2.y)) / denom;
|
||||
let t = ( s2_x * (p0.y - p2.y) - s2_y * (p0.x - p2.x)) / denom;
|
||||
|
||||
if s >= 0.0 && s <= 1.0 && t >= 0.0 && t <= 1.0 {
|
||||
Some(Vec2::new(p0.x + (t * s1_x), p0.y + (t * s1_y)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
use bevy::math::Vec2;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
use super::int::FGi32;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct FGVec2 {
|
||||
pub x: FGi32,
|
||||
pub y: FGi32,
|
||||
}
|
||||
|
||||
impl FGVec2 {
|
||||
pub const ZERO: Self = Self::new(FGi32::ZERO, FGi32::ZERO);
|
||||
|
||||
#[inline(always)]
|
||||
pub const fn new(x: FGi32, y: FGi32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_i32(x: i32, y: i32) -> Self {
|
||||
Self {
|
||||
x: FGi32::from_num(x),
|
||||
y: FGi32::from_num(y),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn length_squared(&self) -> FGi32 {
|
||||
self.x * self.x + self.y * self.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn length(&self) -> FGi32 {
|
||||
(self.x * self.x + self.y * self.y).sqrt()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn normalized_or_zero(&self) -> Self {
|
||||
let len = self.length();
|
||||
if len.is_zero() {
|
||||
Self::ZERO
|
||||
} else {
|
||||
self / len
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_vec2(&self) -> Vec2 {
|
||||
Vec2::new(self.x.to_num(), self.y.to_num())
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x * rhs.x, self.y * rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x + rhs.x, self.y + rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x - rhs.x, self.y - rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x / rhs.x, self.y / rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<FGi32> for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: FGi32) -> Self::Output {
|
||||
Self::new(self.x * rhs, self.y * rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<FGi32> for FGVec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn div(self, rhs: FGi32) -> Self::Output {
|
||||
Self::new(self.x / rhs, self.y / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<FGi32> for &FGVec2 {
|
||||
type Output = FGVec2;
|
||||
|
||||
#[inline]
|
||||
fn div(self, rhs: FGi32) -> Self::Output {
|
||||
(*self).div(rhs)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user