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 scala
.collection
.mutable
._
29 import org
.junit
.Assert
._
36 def addBodyStepExpectBodyMoved
{
39 body
.velocity
= Vec2D(1, 0)
42 assertEquals(Vec2D(2, 0), body
.position
)
48 def addAndRemoveBodyExpectBodyNotMoved
{
51 body
.velocity
= Vec2D(1, 0)
55 assertEquals(Vec2D(0, 0), body
.position
)
61 def addBodyApplyForceCheckVelocity
{
65 body
.applyForce(Vec2D(5, 0))
68 assertEquals(Vec2D(2, 0), body
.velocity
)
74 def addBodyApplyForceStepTwiceCheckVelocity
{
78 body
.applyForce(Vec2D(5, 0))
82 assertEquals(Vec2D(2, 0), body
.velocity
)
88 def addBodyApplyForceStepCheckPosition
{
92 body
.applyForce(Vec2D(5, 0))
95 assertEquals(Vec2D(4, 0), body
.position
)
101 def addBodyApplyImpulseCheckVelocity
{
102 val world
= new World
105 body
.velocity
= Vec2D(3, 0)
106 body
.applyImpulse(Vec2D(5, 0))
109 assertEquals(Vec2D(4, 0), body
.velocity
)
115 def addBodyApplyImpulseCheckVelocity2
{
116 val world
= new World
119 body
.velocity
= Vec2D(3, 0)
120 body
.applyImpulse(Vec2D(5, 0))
123 assertEquals(Vec2D(4, 0), body
.velocity
)
129 def addBodyApplyImpulseCheckImpulse
{
130 val world
= new World
132 body
.applyImpulse(Vec2D(10, 10))
135 assertEquals(Vec2D(0, 0), body
.appliedImpulse
)
141 def applyImpulseToStaticBody
{
143 body
.mass
= Double
.PositiveInfinity
144 body
.applyImpulse(Vec2D(2, 0))
146 val world
= new World
150 assertEquals(Vec2D(0, 0), body
.velocity
)
156 def addBodyDisallowXMovementStepCheckPosition
{
157 val world
= new World
159 body
.allowXMovement(false)
160 body
.applyForce(Vec2D(1, 1))
163 assertEquals(Vec2D(0, 4), body
.position
)
169 def addBodyDisallowYMovementStepCheckPosition
{
170 val world
= new World
172 body
.allowYMovement(false)
173 body
.applyForce(Vec2D(1, 1))
176 assertEquals(Vec2D(4, 0), body
.position
)
182 def verifyInitialBroadPhase
{
183 val world
= new World
184 assertTrue(world
.broadPhase
.isInstanceOf
[SimpleBroadPhase
])
190 def verifyInitialNarrowPhase
{
191 val world
= new World
192 assertTrue(world
.narrowPhase
.isInstanceOf
[SimpleNarrowPhase
])
197 @Test { val expected
= classOf
[NullPointerException
] }
198 def setBroadPhaseNullExpectException
{
199 val world
= new World
200 world
.broadPhase
= null
205 @Test { val expected
= classOf
[NullPointerException
] }
206 def setNarrowPhaseNullExpectException
{
207 val world
= new World
208 world
.narrowPhase
= null
214 def addBodyVerifyItIsPassedToBroadPhase
{
215 val world
= new World
217 val broadPhase
= new BroadPhase
{
218 var passedBodies
: List
[Body
] = null
219 def detectPossibleCollisions(bodies
: List
[Body
]) = { passedBodies
= bodies
; Nil
}
221 world
.broadPhase
= broadPhase
227 assertEquals(body
::Nil
, broadPhase
.passedBodies
)
233 def addBroadPhaseReturningBodyPairsVerifyTheyArePassedToNarrowPhase
{
234 val world
= new World
241 world
.broadPhase
= new BroadPhase
{
242 def detectPossibleCollisions(bodies
: List
[Body
]) = (b1
, b2
)::(b3
, b4
)::Nil
245 val narrowPhase
= new NarrowPhase
{
246 var passedPairs
: List
[(Body
, Body
)] = Nil
247 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
248 passedPairs
= passedPairs
:::List((b1
, b2
))
252 world
.narrowPhase
= narrowPhase
256 assertEquals((b1
, b2
)::(b3
, b4
)::Nil
, narrowPhase
.passedPairs
)
261 def verifyDeltaIsPassedToNarrowPhase
{
262 val world
= new World
267 val narrowPhase
= new NarrowPhase
{
269 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = { d
= delta
; None
}
271 world
.narrowPhase
= narrowPhase
276 assertEquals(d
, narrowPhase
.d
)
282 def verifyCollisionEffects
{
283 val world
= new World
286 b1
.position
= Vec2D(0, 1)
288 b1
.velocity
= Vec2D(-10, -10)
290 b2
.position
= Vec2D(0, -1)
292 b2
.velocity
= Vec2D(5, 5)
294 world
.narrowPhase
= new NarrowPhase
{
295 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
296 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, -1), Vec2D(0, 1), Vec2D(0, 0))))
304 assertEquals(Vec2D(0, 80), b1
.appliedImpulse
)
305 assertEquals(Vec2D(0, -80), b2
.appliedImpulse
)
311 def verifyCollisionEffectsWithBody1Static
{
312 val world
= new World
315 b1
.mass
= Double
.PositiveInfinity
318 b2
.velocity
= Vec2D(1, 1)
320 world
.narrowPhase
= new NarrowPhase
{
321 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
322 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, -1), Vec2D(0, 1), Vec2D(0, 0))))
330 assertEquals(Vec2D(0, 0), b1
.appliedImpulse
)
331 assertEquals(Vec2D(0, -10), b2
.appliedImpulse
)
337 def verifyCollisionEffectsWithBody2Static
{
338 val world
= new World
342 b1
.velocity
= Vec2D(1, 1)
344 b2
.mass
= Double
.PositiveInfinity
346 world
.narrowPhase
= new NarrowPhase
{
347 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
348 Some(Collision(1.0, Contact(b1
, b2
, Vec2D(0, 1), Vec2D(0, -1), Vec2D(0, 0))))
356 assertEquals(Vec2D(0, -10), b1
.appliedImpulse
)
357 assertEquals(Vec2D(0, 0), b2
.appliedImpulse
)
363 def verifyForceIsAppliedBeforeCollisionDetection
{
364 val world
= new World
366 val broadPhase
= new BroadPhase
{
368 def detectPossibleCollisions(bodies
: List
[Body
]) = {
369 v
= bodies(0).velocity
373 world
.broadPhase
= broadPhase
377 body
.applyForce(Vec2D(10, 0))
382 assertEquals(Vec2D(4, 0), broadPhase
.v
)
388 def verifyImpulseIsAppliedBeforeCollisionDetection
{
389 val world
= new World
391 val broadPhase
= new BroadPhase
{
393 def detectPossibleCollisions(bodies
: List
[Body
]) = {
394 v
= bodies(0).velocity
398 world
.broadPhase
= broadPhase
402 body
.applyImpulse(Vec2D(10, 0))
407 assertEquals(Vec2D(2, 0), broadPhase
.v
)
413 def addBodiesThatWouldIntersectAfterMovementVerifyTheyDont
{
414 val world
= new World
418 b1
.position
= Vec2D(0, 0)
419 b1
.velocity
= Vec2D(1, 0)
422 b2
.position
= Vec2D(5, 0)
423 b2
.velocity
= Vec2D(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.5, Contact(b1
, b2
, Vec2D(1, 0), Vec2D(-1, 0), Vec2D(3, 0))))
439 world
.narrowPhase
= narrowPhase
443 val expectedPosition
= Vec2D(1, 0)
445 assertEquals(expectedPosition
.x
, b1
.position
.x
, 0.01)
446 assertEquals(expectedPosition
.y
, b1
.position
.y
, 0.01)
452 def testForIntersectionAtHighPositionValues
{
453 // This is a real-world example that led to a bug. That's where all the odd numbers come from.
455 val world
= new World
459 b1
.position
= Vec2D(83.9699958296336, 488.77572653374307)
460 b1
.velocity
= Vec2D(-445.3620529718986, -50.442888201040574)
462 b2
.shape
= Circle(30)
463 b2
.position
= Vec2D(50.0, 469.8163204364546)
464 b2
.velocity
= Vec2D(0.0, 0.0)
468 val broadPhase
= new BroadPhase
{
469 def detectPossibleCollisions(bodies
: List
[Body
]) = {
473 world
.broadPhase
= broadPhase
475 val narrowPhase
= new NarrowPhase
{
476 def inspectCollision(delta
: Double
, b1
: Body
, b2
: Body
) = {
477 Some(Collision(0.4766389925763854, Contact(b1
, b2
,
478 Vec2D(-0.8732041733361332, -0.4873545646327327),
479 Vec2D(0.8732041733361332, 0.4873545646327327), Vec2D(3, 0))))
482 world
.narrowPhase
= narrowPhase
486 assertTrue((b2
.position
- b1
.position
).squaredLength
>= 35.0 * 35.0)
491 @Test { val expected
= classOf
[IllegalArgumentException
] }
492 def stepPassNegativeDelta
{
493 val world
= new World
500 def verifyBodyIterableIsAccessible
{
501 val world
= new World
502 assertTrue(world
.bodies
.isInstanceOf
[Iterable
[Body
]])
508 def verifyBodyIterableCantChangeWorld
{
509 val world
= new World
511 world
.bodies
.asInstanceOf
[HashSet
[Body
]].addEntry(body
)
512 assertFalse(world
.bodies
.exists(_
== body
))