test: geometry and slope collision coverage
This commit is contained in:
1 parent
a0222105d7
commit
1952538952
4 files changed
+161
No files matched your search
@@ -0,0 +1,28 @@
|
||||
from game.sim.level import parseAscii
|
||||
from game.sim.world import World
|
||||
from game.sim.inputCommand import InputCommand
|
||||
|
||||
|
||||
def makeLevel(lines, name="test"):
|
||||
return parseAscii(name, lines)
|
||||
|
||||
|
||||
def makeWorld(lines, name="test"):
|
||||
return World(parseAscii(name, lines))
|
||||
|
||||
|
||||
def command(**kwargs):
|
||||
return InputCommand(**kwargs)
|
||||
|
||||
|
||||
def stepWorld(world, times=1, **kwargs):
|
||||
cmd = InputCommand(**kwargs)
|
||||
for _ in range(times):
|
||||
world.step(cmd)
|
||||
return world
|
||||
|
||||
|
||||
def settle(world, times=30):
|
||||
for _ in range(times):
|
||||
world.step(InputCommand())
|
||||
return world
|
||||
@@ -0,0 +1,71 @@
|
||||
import pytest
|
||||
|
||||
from game.sim.geometry import Vec2, Aabb, clamp, sign, approach
|
||||
|
||||
|
||||
def test_aabbIntersectsOverlapping():
|
||||
a = Aabb(0, 0, 10, 10)
|
||||
b = Aabb(5, 5, 10, 10)
|
||||
assert a.intersects(b)
|
||||
assert b.intersects(a)
|
||||
|
||||
|
||||
def test_aabbDoesNotIntersectSeparated():
|
||||
a = Aabb(0, 0, 10, 10)
|
||||
b = Aabb(20, 0, 10, 10)
|
||||
assert not a.intersects(b)
|
||||
|
||||
|
||||
def test_aabbTouchingEdgeIsNotOverlap():
|
||||
a = Aabb(0, 0, 10, 10)
|
||||
b = Aabb(10, 0, 10, 10)
|
||||
assert not a.intersects(b)
|
||||
assert a.touches(b)
|
||||
|
||||
|
||||
def test_aabbOverlapArea():
|
||||
a = Aabb(0, 0, 10, 10)
|
||||
b = Aabb(5, 5, 10, 10)
|
||||
assert a.overlapArea(b) == pytest.approx(25.0)
|
||||
assert a.overlapArea(Aabb(100, 100, 5, 5)) == 0.0
|
||||
|
||||
|
||||
def test_aabbContainsAndEdges():
|
||||
box = Aabb(4, 6, 8, 10)
|
||||
assert box.left == 4 and box.right == 12
|
||||
assert box.top == 6 and box.bottom == 16
|
||||
assert box.centerX == pytest.approx(8.0)
|
||||
assert box.containsPoint(8, 10)
|
||||
assert not box.containsPoint(100, 10)
|
||||
|
||||
|
||||
def test_aabbInflated():
|
||||
box = Aabb(10, 10, 4, 4)
|
||||
grown = box.inflated(2, 3)
|
||||
assert grown.left == 8 and grown.right == 16
|
||||
assert grown.top == 7 and grown.bottom == 17
|
||||
|
||||
|
||||
def test_vecArithmetic():
|
||||
a = Vec2(3, 4)
|
||||
assert a.length() == pytest.approx(5.0)
|
||||
assert a.add(Vec2(1, 1)).asTuple() == (4.0, 5.0)
|
||||
assert a.sub(Vec2(3, 4)).asTuple() == (0.0, 0.0)
|
||||
assert a.scale(2).asTuple() == (6.0, 8.0)
|
||||
normalized = a.normalized()
|
||||
assert normalized.length() == pytest.approx(1.0)
|
||||
|
||||
|
||||
def test_vecDistanceAndZeroNormalize():
|
||||
assert Vec2(0, 0).distanceTo(Vec2(3, 4)) == pytest.approx(5.0)
|
||||
assert Vec2(0, 0).normalized().asTuple() == (0.0, 0.0)
|
||||
|
||||
|
||||
def test_helpers():
|
||||
assert clamp(5, 0, 3) == 3
|
||||
assert clamp(-1, 0, 3) == 0
|
||||
assert clamp(2, 0, 3) == 2
|
||||
assert sign(-4) == -1 and sign(4) == 1 and sign(0) == 0
|
||||
assert approach(0, 10, 3) == 3
|
||||
assert approach(10, 0, 3) == 7
|
||||
assert approach(1, 2, 5) == 2
|
||||
@@ -0,0 +1,58 @@
|
||||
import pytest
|
||||
|
||||
from game.sim import physics
|
||||
from game.sim.entity import Actor
|
||||
|
||||
|
||||
class FakeSlopeTerrain:
|
||||
def __init__(self, slopes):
|
||||
self.slopes = slopes
|
||||
|
||||
def slopeAt(self, col, row):
|
||||
return self.slopes.get((col, row))
|
||||
|
||||
|
||||
def test_slopeSurfaceAscendRight():
|
||||
assert physics.slopeSurfaceY(0, 0, 0, "ascendRight") == pytest.approx(16.0)
|
||||
assert physics.slopeSurfaceY(0, 0, 16, "ascendRight") == pytest.approx(0.0)
|
||||
assert physics.slopeSurfaceY(0, 0, 8, "ascendRight") == pytest.approx(8.0)
|
||||
|
||||
|
||||
def test_slopeSurfaceAscendLeft():
|
||||
assert physics.slopeSurfaceY(0, 0, 0, "ascendLeft") == pytest.approx(0.0)
|
||||
assert physics.slopeSurfaceY(0, 0, 16, "ascendLeft") == pytest.approx(16.0)
|
||||
|
||||
|
||||
def test_resolveSlopeSnapsPenetratingActor():
|
||||
terrain = FakeSlopeTerrain({(0, 0): "ascendRight"})
|
||||
actor = Actor(2, -6, 12, 16)
|
||||
actor.vy = 1.0
|
||||
snapped = physics.resolveSlope(actor, terrain, wasOnGround=False)
|
||||
assert snapped
|
||||
assert actor.onGround
|
||||
assert actor.bottom == pytest.approx(physics.slopeSurfaceY(0, 0, actor.centerX, "ascendRight"))
|
||||
assert actor.vy == 0.0
|
||||
|
||||
|
||||
def test_walkingUpSlopeGainsHeight():
|
||||
terrain = FakeSlopeTerrain({(0, 0): "ascendRight"})
|
||||
actor = Actor(0, 0, 12, 16)
|
||||
actor.vy = 1.0
|
||||
physics.resolveSlope(actor, terrain, wasOnGround=False)
|
||||
lowBottom = actor.bottom
|
||||
actor.x = 6
|
||||
actor.vy = 1.0
|
||||
physics.resolveSlope(actor, terrain, wasOnGround=True)
|
||||
assert actor.bottom < lowBottom
|
||||
|
||||
|
||||
def test_resolveSlopeClingsWhenDescending():
|
||||
terrain = FakeSlopeTerrain({(0, 0): "ascendLeft"})
|
||||
actor = Actor(2, 0, 12, 16)
|
||||
surface = physics.slopeSurfaceY(0, 0, actor.centerX, "ascendLeft")
|
||||
actor.y = surface - actor.h - 3.0
|
||||
actor.vy = 0.5
|
||||
snapped = physics.resolveSlope(actor, terrain, wasOnGround=True)
|
||||
assert snapped
|
||||
assert actor.onGround
|
||||
assert actor.bottom == pytest.approx(surface)
|
||||
Reference in new issue
Block a user