roc/physics.py
2017-05-08 13:10:48 -07:00

126 lines
2.7 KiB
Python
Executable file

from py3dutil import vect, quat
import gametimer
import math
floor = math.floor
class motion(object):
def __init__(self):
pass
def turn(self, dir):
pass
class physics_manager(object):
def __init__(self):
self.cellsize = 100.0
self.cells = {}
self.zones = {}
def getcell(self, pos, create=False):
x = int(floor(pos.x / self.cellsize))
y = int(floor(pos.y / self.cellsize))
z = int(floor(pos.z / self.cellsize))
k = (x, y, z)
if k in self.cells:
return self.cells[k]
if create:
self.cells[k] = collision_cell()
return self.cells[k]
else:
return None
def collide(self, obj, pos, newpos):
pass
def get_neighbors(self, cellkey, dist):
return []
def _postcollide_single(self, obj, cellkey, pairmap):
movement = obj._collide_end - obj._collide_start
cellmove = int(movement.mag() / self.cellsize) + 2
neighbors = self.get_neighbors(cellkey, cellmove)
for neighbor in neighbors:
for other in neighbor:
d = obj.pos.dist(other.pos)
thresh = movement.mag()
if obj.radius:
thresh += obj.radius
if other.radius:
thresh += other.radius
if d > thresh:
continue
pairkey = (obj, other)
if id(other) < id(obj):
pairkey = (other, obj)
pairmap[pairkey] = 1
def _postcollide_pair(self, pair):
obj, other = pair
moved1, moved2 = False, False
if not obj.massless:
moved1 = other.collide(obj)
if not other.massless:
moved2 = obj.collide(other)
print("Collision!")
assert False
return moved1 or moved2
def postcollide(self):
positions_adjusted = True
iter = 0
while positions_adjusted:
positions_adjusted = False
iter += 1
pairmap = {}
for key, cell in list(self.cells.items()):
for obj in cell:
self._postcollide_single(obj, key, pairmap)
for pair in pairmap:
rv = self._postcollide_pair(pair)
if rv:
positions_adjusted = True
def collide_failed(self):
pass
def move(self, obj, pos, newpos):
x = int(floor(pos.x / self.cellsize))
y = int(floor(pos.y / self.cellsize))
z = int(floor(pos.z / self.cellsize))
xn = int(floor(newpos.x / self.cellsize))
yn = int(floor(newpos.y / self.cellsize))
zn = int(floor(newpos.z / self.cellsize))
if x != xn or y != yn or z != zn:
cellold = self.getcell(pos)
cellnew = self.getcell(newpos, create=True)
if cellold:
cellold.remove(obj)
cellnew.add(obj)
class collision_cell(object):
def __init__(self):
self.objects = {}
def add(self, obj):
self.objects[obj] = 1
def remove(self, obj):
if obj in self.objects:
del self.objects[obj]
def __iter__(self):
return iter(self.objects)
class render_zone(object):
def __init__(self):
pass
def init():
global mgr
mgr = physics_manager()
mgr = None