reorganized collider code
This commit is contained in:
BIN
collider/__pycache__/system.cpython-311.pyc
Normal file
BIN
collider/__pycache__/system.cpython-311.pyc
Normal file
Binary file not shown.
BIN
collider/__pycache__/types.cpython-311.pyc
Normal file
BIN
collider/__pycache__/types.cpython-311.pyc
Normal file
Binary file not shown.
@@ -1,110 +1,8 @@
|
|||||||
from dataclasses import dataclass
|
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
from typing import Generator
|
|
||||||
|
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from math import pi
|
|
||||||
|
|
||||||
|
from collider.types import *
|
||||||
from transform import Transform
|
from transform import Transform
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Face:
|
|
||||||
begin: pg.Vector2
|
|
||||||
end: pg.Vector2
|
|
||||||
|
|
||||||
@property
|
|
||||||
def normal(self) -> pg.Vector2:
|
|
||||||
return (self.end-self.begin).rotate(-90).normalize()
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ColliderContact:
|
|
||||||
__slots__ = ["points", "normal", "penetration"]
|
|
||||||
points: list[pg.Vector2]
|
|
||||||
normal: pg.Vector2
|
|
||||||
penetration: float
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class PolygonalHull:
|
|
||||||
_vertices: list[pg.Vector2]
|
|
||||||
|
|
||||||
def get_vertex_at_index(self, key: int) -> pg.Vector2:
|
|
||||||
return self._vertices[key]
|
|
||||||
|
|
||||||
def get_face_at_index(self, key: int) -> Face:
|
|
||||||
return Face(self._vertices[key], self._vertices[(key + 1) % len(self._vertices)])
|
|
||||||
|
|
||||||
def vertices(self) -> Generator[pg.Vector2, None, None]:
|
|
||||||
for v in self._vertices:
|
|
||||||
yield v
|
|
||||||
|
|
||||||
def faces(self) -> Generator[Face, None, None]:
|
|
||||||
for i in range(len(self._vertices)):
|
|
||||||
yield self.get_face_at_index(i)
|
|
||||||
|
|
||||||
def project(self, axis: pg.Vector2) -> tuple[float, float]:
|
|
||||||
projections = [v.dot(axis) for v in self._vertices]
|
|
||||||
return (min(projections), max(projections))
|
|
||||||
|
|
||||||
|
|
||||||
class BaseCollider(ABC):
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def moment_of_inertia(self, mass: float) -> float:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ConvexCollider(BaseCollider):
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def hull(self, transform: Transform) -> PolygonalHull:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CircleCollider(BaseCollider):
|
|
||||||
|
|
||||||
radius: float
|
|
||||||
|
|
||||||
def moment_of_inertia(self, mass: float) -> float:
|
|
||||||
return 0.5 * self.radius ** 2 * mass
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LineCollider(ConvexCollider):
|
|
||||||
|
|
||||||
length: float
|
|
||||||
|
|
||||||
def hull(self, transform: Transform) -> PolygonalHull:
|
|
||||||
return PolygonalHull([
|
|
||||||
transform.global_position - pg.Vector2(self.length / 2.0, 0).rotate(transform.global_degrees) * transform.global_scale,
|
|
||||||
transform.global_position + pg.Vector2(self.length / 2.0, 0).rotate(transform.global_degrees) * transform.global_scale
|
|
||||||
])
|
|
||||||
|
|
||||||
def moment_of_inertia(self, mass):
|
|
||||||
return 1.0 / 12.0 * mass * self.length**2
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class RectCollider(ConvexCollider):
|
|
||||||
|
|
||||||
dimensions: tuple[float, float]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def width(self):
|
|
||||||
return self.dimensions[0]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def height(self):
|
|
||||||
return self.dimensions[1]
|
|
||||||
|
|
||||||
def hull(self, transform: Transform) -> PolygonalHull:
|
|
||||||
return PolygonalHull([
|
|
||||||
transform.global_position - pg.Vector2(self.width / 2.0, self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
|
||||||
transform.global_position - pg.Vector2(-self.width / 2.0, self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
|
||||||
transform.global_position - pg.Vector2(-self.width / 2.0, -self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
|
||||||
transform.global_position - pg.Vector2(self.width / 2.0, -self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale
|
|
||||||
])
|
|
||||||
|
|
||||||
def moment_of_inertia(self, mass: float) -> float:
|
|
||||||
return (1.0 / 12.0) * mass * (self.width ** 2 + self.height ** 2)
|
|
||||||
|
|
||||||
def _interval_overlap(a: tuple[float, float], b: tuple[float, float]) -> float | None:
|
def _interval_overlap(a: tuple[float, float], b: tuple[float, float]) -> float | None:
|
||||||
if a[0] <= b[1] and b[0] <= a[1]:
|
if a[0] <= b[1] and b[0] <= a[1]:
|
||||||
return min(a[1], b[1]) - max(a[0], b[0])
|
return min(a[1], b[1]) - max(a[0], b[0])
|
||||||
104
collider/types.py
Normal file
104
collider/types.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Generator
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
import pygame as pg
|
||||||
|
from transform import Transform
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Face:
|
||||||
|
begin: pg.Vector2
|
||||||
|
end: pg.Vector2
|
||||||
|
|
||||||
|
@property
|
||||||
|
def normal(self) -> pg.Vector2:
|
||||||
|
return (self.end-self.begin).rotate(-90).normalize()
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ColliderContact:
|
||||||
|
__slots__ = ["points", "normal", "penetration"]
|
||||||
|
points: list[pg.Vector2]
|
||||||
|
normal: pg.Vector2
|
||||||
|
penetration: float
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class PolygonalHull:
|
||||||
|
_vertices: list[pg.Vector2]
|
||||||
|
|
||||||
|
def get_vertex_at_index(self, key: int) -> pg.Vector2:
|
||||||
|
return self._vertices[key]
|
||||||
|
|
||||||
|
def get_face_at_index(self, key: int) -> Face:
|
||||||
|
return Face(self._vertices[key], self._vertices[(key + 1) % len(self._vertices)])
|
||||||
|
|
||||||
|
def vertices(self) -> Generator[pg.Vector2, None, None]:
|
||||||
|
for v in self._vertices:
|
||||||
|
yield v
|
||||||
|
|
||||||
|
def faces(self) -> Generator[Face, None, None]:
|
||||||
|
for i in range(len(self._vertices)):
|
||||||
|
yield self.get_face_at_index(i)
|
||||||
|
|
||||||
|
def project(self, axis: pg.Vector2) -> tuple[float, float]:
|
||||||
|
projections = [v.dot(axis) for v in self._vertices]
|
||||||
|
return (min(projections), max(projections))
|
||||||
|
|
||||||
|
|
||||||
|
class BaseCollider(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def moment_of_inertia(self, mass: float) -> float:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ConvexCollider(BaseCollider):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def hull(self, transform: Transform) -> PolygonalHull:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CircleCollider(BaseCollider):
|
||||||
|
|
||||||
|
radius: float
|
||||||
|
|
||||||
|
def moment_of_inertia(self, mass: float) -> float:
|
||||||
|
return 0.5 * self.radius ** 2 * mass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LineCollider(ConvexCollider):
|
||||||
|
|
||||||
|
length: float
|
||||||
|
|
||||||
|
def hull(self, transform: Transform) -> PolygonalHull:
|
||||||
|
return PolygonalHull([
|
||||||
|
transform.global_position - pg.Vector2(self.length / 2.0, 0).rotate(transform.global_degrees) * transform.global_scale,
|
||||||
|
transform.global_position + pg.Vector2(self.length / 2.0, 0).rotate(transform.global_degrees) * transform.global_scale
|
||||||
|
])
|
||||||
|
|
||||||
|
def moment_of_inertia(self, mass):
|
||||||
|
return 1.0 / 12.0 * mass * self.length**2
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RectCollider(ConvexCollider):
|
||||||
|
|
||||||
|
dimensions: tuple[float, float]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self.dimensions[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def height(self):
|
||||||
|
return self.dimensions[1]
|
||||||
|
|
||||||
|
def hull(self, transform: Transform) -> PolygonalHull:
|
||||||
|
return PolygonalHull([
|
||||||
|
transform.global_position - pg.Vector2(self.width / 2.0, self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
||||||
|
transform.global_position - pg.Vector2(-self.width / 2.0, self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
||||||
|
transform.global_position - pg.Vector2(-self.width / 2.0, -self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale,
|
||||||
|
transform.global_position - pg.Vector2(self.width / 2.0, -self.height / 2.0).rotate(transform.global_degrees) * transform.global_scale
|
||||||
|
])
|
||||||
|
|
||||||
|
def moment_of_inertia(self, mass: float) -> float:
|
||||||
|
return (1.0 / 12.0) * mass * (self.width ** 2 + self.height ** 2)
|
||||||
2
main.py
2
main.py
@@ -1,7 +1,7 @@
|
|||||||
import pygame as pg
|
import pygame as pg
|
||||||
from math import pi
|
from math import pi
|
||||||
from rigidbody import *
|
from rigidbody import *
|
||||||
from collider import RectCollider
|
from collider.types import RectCollider
|
||||||
|
|
||||||
from tools import debug
|
from tools import debug
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ from itertools import combinations
|
|||||||
import pygame as pg
|
import pygame as pg
|
||||||
|
|
||||||
from tools import debug
|
from tools import debug
|
||||||
from collider import *
|
from collider.system import intersect
|
||||||
|
from collider.types import *
|
||||||
from transform import Transform
|
from transform import Transform
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
Reference in New Issue
Block a user