2 Copyright (c) 2009 Hanno Braun <hanno@habraun.net>
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
19 package net
.habraun
.sd
26 import org
.junit
.Assert
._
33 def addBodyStepExpectBodyMoved
{
36 body
.velocity
= Vec2D(1, 0)
39 assertEquals(Vec2D(2, 0), body
.position
)
45 def addAndRemoveBodyExpectBodyNotMoved
{
48 body
.velocity
= Vec2D(1, 0)
52 assertEquals(Vec2D(0, 0), body
.position
)
58 def addBodyApplyForceCheckVelocity
{
62 body
.applyForce(Vec2D(5, 0))
65 assertEquals(Vec2D(2, 0), body
.velocity
)
71 def addBodyApplyForceStepTwiceCheckVelocity
{
75 body
.applyForce(Vec2D(5, 0))
79 assertEquals(Vec2D(2, 0), body
.velocity
)
85 def addBodyApplyForceStepCheckPosition
{
89 body
.applyForce(Vec2D(5, 0))
92 assertEquals(Vec2D(4, 0), body
.position
)
98 def addBodyApplyImpulseCheckVelocity
{
102 body
.velocity
= Vec2D(3, 0)
103 body
.applyImpulse(Vec2D(5, 0))
106 assertEquals(Vec2D(4, 0), body
.velocity
)
112 def addBodyApplyImpulseCheckVelocity2
{
113 val world
= new World
116 body
.velocity
= Vec2D(3, 0)
117 body
.applyImpulse(Vec2D(5, 0))
120 assertEquals(Vec2D(4, 0), body
.velocity
)
126 def addBodyApplyImpulseCheckImpulse
{
127 val world
= new World
129 body
.applyImpulse(Vec2D(10, 10))
132 assertEquals(Vec2D(0, 0), body
.appliedImpulse
)
138 def addBodyDisallowXMovementStepCheckPosition
{
139 val world
= new World
141 body
.allowXMovement(false)
142 body
.applyForce(Vec2D(1, 1))
145 assertEquals(Vec2D(0, 4), body
.position
)
151 def addBodyDisallowYMovementStepCheckPosition
{
152 val world
= new World
154 body
.allowYMovement(false)
155 body
.applyForce(Vec2D(1, 1))
158 assertEquals(Vec2D(4, 0), body
.position
)
164 def verifyInitialBroadPhase
{
165 val world
= new World
166 assertTrue(world
.broadPhase
.isInstanceOf
[SimpleBroadPhase
])
172 def verifyInitialNarrowPhase
{
173 val world
= new World
174 assertTrue(world
.narrowPhase
.isInstanceOf
[SimpleNarrowPhase
])
179 @Test { val expected
= classOf
[NullPointerException
] }
180 def setBroadPhaseNullExpectException
{
181 val world
= new World
182 world
.broadPhase
= null
187 @Test { val expected
= classOf
[NullPointerException
] }
188 def setNarrowPhaseNullExpectException
{
189 val world
= new World
190 world
.narrowPhase
= null
196 def addBodyVerifyItIsPassedToBroadPhase
{
197 val world
= new World
199 val broadPhase
= new BroadPhase
{
200 var passedBodies
: List
[Body
] = null
201 def detectPossibleCollisions(bodies
: List
[Body
]) = { passedBodies
= bodies
; Nil
}
203 world
.broadPhase
= broadPhase
209 assertEquals(body
::Nil
, broadPhase
.passedBodies
)
215 def addBroadPhaseReturningBodyPairsVerifyTheyArePassedToNarrowPhase
{
216 val world
= new World
223 world
.broadPhase
= new BroadPhase
{
224 def detectPossibleCollisions(bodies
: List
[Body
]) = (b1
, b2
)::(b3
, b4
)::Nil
227 val narrowPhase
= new NarrowPhase
{
228 var passedPairs
: List
[(Body
, Body
)] = Nil
229 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = { passedPairs
= passedPairs
:::List((b1
, b2
)); None
}
231 world
.narrowPhase
= narrowPhase
235 assertEquals((b1
, b2
)::(b3
, b4
)::Nil
, narrowPhase
.passedPairs
)
241 def verifyCollisionEffects
{
242 val world
= new World
245 b1
.position
= Vec2D(0, 1)
247 b1
.velocity
= Vec2D(-10, -10)
249 b2
.position
= Vec2D(0, -1)
251 b2
.velocity
= Vec2D(5, 5)
253 world
.narrowPhase
= new NarrowPhase
{
254 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
255 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, -1), Vec2D(0, 1), Vec2D(0, 0))))
263 assertEquals(Vec2D(0, 80), b1
.appliedImpulse
)
264 assertEquals(Vec2D(0, -80), b2
.appliedImpulse
)
270 def verifyCollisionEffectsWithBody1Static
{
271 val world
= new World
274 b1
.mass
= Double
.PositiveInfinity
277 b2
.velocity
= Vec2D(1, 1)
279 world
.narrowPhase
= new NarrowPhase
{
280 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
281 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, -1), Vec2D(0, 1), Vec2D(0, 0))))
289 assertEquals(Vec2D(0, 0), b1
.appliedImpulse
)
290 assertEquals(Vec2D(0, -10), b2
.appliedImpulse
)
296 def verifyCollisionEffectsWithBody2Static
{
297 val world
= new World
301 b1
.velocity
= Vec2D(1, 1)
303 b2
.mass
= Double
.PositiveInfinity
305 world
.narrowPhase
= new NarrowPhase
{
306 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
307 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, 1), Vec2D(0, -1), Vec2D(0, 0))))
315 assertEquals(Vec2D(0, -10), b1
.appliedImpulse
)
316 assertEquals(Vec2D(0, 0), b2
.appliedImpulse
)
322 def verifyForceIsAppliedBeforeCollisionDetection
{
323 val world
= new World
325 val broadPhase
= new BroadPhase
{
327 def detectPossibleCollisions(bodies
: List
[Body
]) = {
328 v
= bodies(0).velocity
332 world
.broadPhase
= broadPhase
336 body
.applyForce(Vec2D(10, 0))
341 assertEquals(Vec2D(4, 0), broadPhase
.v
)
347 def verifyImpulseIsAppliedBeforeCollisionDetection
{
348 val world
= new World
350 val broadPhase
= new BroadPhase
{
352 def detectPossibleCollisions(bodies
: List
[Body
]) = {
353 v
= bodies(0).velocity
357 world
.broadPhase
= broadPhase
361 body
.applyImpulse(Vec2D(10, 0))
366 assertEquals(Vec2D(2, 0), broadPhase
.v
)
372 def addBodiesThatWouldIntersectAfterMovementVerifyTheyDont
{
373 val world
= new World
377 b1
.position
= Vec2D(0, 0)
378 b1
.velocity
= Vec2D(1, 0)
381 b2
.position
= Vec2D(5, 0)
382 b2
.velocity
= Vec2D(0, 0)
386 val broadPhase
= new BroadPhase
{
387 def detectPossibleCollisions(bodies
: List
[Body
]) = {
391 world
.broadPhase
= broadPhase
393 val narrowPhase
= new NarrowPhase
{
394 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
395 Some(Collision(0.5, Contact(b1
, b2
, Vec2D(1, 0), Vec2D(-1, 0), Vec2D(3, 0))))
398 world
.narrowPhase
= narrowPhase
402 val expectedPosition
= Vec2D(1, 0)
404 assertEquals(expectedPosition
.x
, b1
.position
.x
, 0.01)
405 assertEquals(expectedPosition
.y
, b1
.position
.y
, 0.01)
411 def testForIntersectionAtHighPositionValues
{
412 // This is a real-world example that led to a bug. That's where all the odd numbers come from.
414 val world
= new World
418 b1
.position
= Vec2D(83.9699958296336, 488.77572653374307)
419 b1
.velocity
= Vec2D(-445.3620529718986, -50.442888201040574)
421 b2
.shape
= Circle(30)
422 b2
.position
= Vec2D(50.0, 469.8163204364546)
423 b2
.velocity
= Vec2D(0.0, 0.0)
427 val broadPhase
= new BroadPhase
{
428 def detectPossibleCollisions(bodies
: List
[Body
]) = {
432 world
.broadPhase
= broadPhase
434 val narrowPhase
= new NarrowPhase
{
435 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
436 Some(Collision(0.4766389925763854, Contact(b1
, b2
,
437 Vec2D(-0.8732041733361332, -0.4873545646327327),
438 Vec2D(0.8732041733361332, 0.4873545646327327), Vec2D(3, 0))))
441 world
.narrowPhase
= narrowPhase
445 assertTrue((b2
.position
- b1
.position
).squaredLength
>= 35.0 * 35.0)
450 @Test { val expected
= classOf
[IllegalArgumentException
] }
451 def stepPassNegativeDelta
{
452 val world
= new World