2 * Copyright (c) 2010 The Desert team
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
26 package org
.sourceforge
.desert
;
28 import java
.awt
.Dimension
;
29 import java
.util
.HashSet
;
30 import java
.util
.Iterator
;
32 import org
.junit
.Test
;
33 import static org
.junit
.Assert
.*;
36 * The tests involving position or speed check inequalities rather than equalities.
37 * <br>This way, engines don't have to be scientifically correct; if it looks good then it's good enough.
38 * @author codistmonk (creation 2010-04-17)
40 public abstract class AbstractParticleEngineTestBase
{
43 public final void testSetBoundsAndAddParticlesThenRemoveAllThenUpdate() {
44 final ParticleEngine particleEngine
= this.createParticleEngine();
46 particleEngine
.setBoardSize(new Dimension());
48 assertNotNull(particleEngine
.getBoardSize());
49 assertEquals(0, particleEngine
.getParticleCount());
51 particleEngine
.addParticle(IMMOBILE_TYPE
, 0F
, 0F
, 0F
, 0F
);
53 assertEquals(1, particleEngine
.getParticleCount());
55 particleEngine
.addParticle(MOBILE_TYPE_1
, 0F
, 0F
, 0F
, 0F
);
57 assertEquals(2, particleEngine
.getParticleCount());
59 particleEngine
.removeAllParticles();
61 assertEquals(0, particleEngine
.getParticleCount());
62 assertNotNull(particleEngine
.getBoardSize());
64 update(particleEngine
, SIMULATION_STEP
, SIMULATION_STEP
);
68 public final void testImmobileParticleNotMovedByGravity() {
71 final float deltaTime
= 5F
;
72 final ParticleEngine particleEngine
= this.createParticleEngine();
74 particleEngine
.setGravity(ParticleEngine
.DEFAULT_GRAVITY
);
75 particleEngine
.setBoardSize(null);
76 particleEngine
.addParticle(IMMOBILE_TYPE
, x
, y
, 0F
, 0F
);
77 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
79 final Particle particle
= particleEngine
.iterator().next();
81 assertEquals(IMMOBILE_TYPE
, particle
.getType());
82 assertEquals(x
, particle
.getX(), DELTA
);
83 assertEquals(y
, particle
.getY(), DELTA
);
84 assertEquals(0F
, particle
.getSpeedX(), DELTA
);
85 assertEquals(0F
, particle
.getSpeedY(), DELTA
);
89 public final void testGravityInitializedToDefault() {
90 final ParticleEngine particleEngine
= this.createParticleEngine();
92 assertEquals(particleEngine
.DEFAULT_GRAVITY
, particleEngine
.getGravity(), DELTA
);
96 public final void testCountThenSetBoundsThenCountThenRemoveBoundsThenCount() {
97 final ParticleEngine particleEngine
= this.createParticleEngine();
99 assertEquals(0, particleEngine
.getParticleCount());
101 particleEngine
.setBoardSize(new Dimension());
103 assertEquals(0, particleEngine
.getParticleCount());
105 particleEngine
.setBoardSize(null);
107 assertEquals(0, particleEngine
.getParticleCount());
111 public final void testUpdateWithoutBounds() {
114 final float speedX
= 3F
;
115 final float speedY
= 5F
;
116 final float deltaTime
= 7F
;
117 final ParticleEngine particleEngine
= this.createParticleEngine();
119 particleEngine
.setBoardSize(null);
121 assertNull("board size should have been null but was " + particleEngine
.getBoardSize(), particleEngine
.getBoardSize());
123 particleEngine
.setGravity(-0.1F
);
124 particleEngine
.addParticle(MOBILE_TYPE_1
, x
, y
, speedX
, speedY
);
125 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
127 final Particle particle
= particleEngine
.iterator().next();
129 assertTrue(x
+ " >= " + particle
.getX(), x
< particle
.getX());
130 assertTrue(y
+ " >= " + particle
.getY(), y
< particle
.getY());
131 // This assertion may not hold when drag is implemented
132 assertEquals(speedX
, particle
.getSpeedX(), DELTA
);
133 assertTrue(speedY
+ " <= " + particle
.getSpeedY(), speedY
> particle
.getSpeedY());
137 public final void testUpdateWithBottomBound() {
138 final Integer width
= 20;
139 final Integer height
= 10;
142 final float speedX
= 1F
;
143 final float speedY
= 5F
; // Go downward in screen coordinates
144 final float deltaTime
= 2F
;
145 final ParticleEngine particleEngine
= this.createParticleEngine();
147 particleEngine
.setGravity(0F
);
148 particleEngine
.setBoardSize(new Dimension(width
, height
));
149 particleEngine
.addParticle(MOBILE_TYPE_1
, x
, y
, speedX
, speedY
);
150 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
152 final Particle particle
= particleEngine
.iterator().next();
154 assertTrue(particle
.getY() + " >= " + height
, particle
.getY() < height
);
158 public final void testUpdateWithTopBound() {
159 final Integer width
= 20;
160 final Integer height
= 10;
163 final float speedX
= 1F
;
164 final float speedY
= -5F
; // Go upward in screen coordinates
165 final float deltaTime
= 2F
;
166 final ParticleEngine particleEngine
= this.createParticleEngine();
168 particleEngine
.setGravity(0F
);
169 particleEngine
.setBoardSize(new Dimension(width
, height
));
170 particleEngine
.addParticle(MOBILE_TYPE_1
, x
, y
, speedX
, speedY
);
171 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
173 final Particle particle
= particleEngine
.iterator().next();
175 assertTrue(particle
.getY() + " < 0", particle
.getY() >= 0);
179 public final void testUpdateWithLeftBound() {
180 final Integer width
= 20;
181 final Integer height
= 10;
184 final float speedX
= -10F
;
185 final float speedY
= 1F
;
186 final float deltaTime
= 2F
;
187 final ParticleEngine particleEngine
= this.createParticleEngine();
189 particleEngine
.setGravity(0F
);
190 particleEngine
.setBoardSize(new Dimension(width
, height
));
191 particleEngine
.addParticle(MOBILE_TYPE_1
, x
, y
, speedX
, speedY
);
192 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
194 final Particle particle
= particleEngine
.iterator().next();
196 assertTrue(particle
.getX() + " < 0", particle
.getX() >= 0);
200 public final void testUpdateWithRightBound() {
201 final Integer width
= 20;
202 final Integer height
= 10;
205 final float speedX
= 10F
;
206 final float speedY
= 1F
;
207 final float deltaTime
= 2F
;
208 final ParticleEngine particleEngine
= this.createParticleEngine();
210 particleEngine
.setGravity(0F
);
211 particleEngine
.setBoardSize(new Dimension(width
, height
));
212 particleEngine
.addParticle(MOBILE_TYPE_1
, x
, y
, speedX
, speedY
);
213 update(particleEngine
, deltaTime
, SIMULATION_STEP
);
215 final Particle particle
= particleEngine
.iterator().next();
217 assertTrue(particle
.getX() + " >= " + width
, particle
.getX() < width
);
221 public final void testSetThenGetGravity() {
222 final ParticleEngine particleEngine
= this.createParticleEngine();
223 final float gravity
= -42F
;
225 particleEngine
.setGravity(gravity
);
227 assertEquals(gravity
, particleEngine
.getGravity(), DELTA
);
231 public final void testSetThenGetEmptyBoardSize() {
232 final ParticleEngine particleEngine
= this.createParticleEngine();
233 final Dimension size
= new Dimension(0, 0);
235 particleEngine
.setBoardSize(size
);
237 assertEquals(size
, particleEngine
.getBoardSize());
241 public final void testSetThenGetNonemptyBoardSize() {
242 final ParticleEngine particleEngine
= this.createParticleEngine();
243 final Dimension size
= new Dimension(640, 480);
245 particleEngine
.setBoardSize(size
);
247 assertEquals(size
, particleEngine
.getBoardSize());
251 public final void testAddParticlesAndCountWithoutBounds() {
252 final ParticleEngine particleEngine
= this.createParticleEngine();
254 particleEngine
.setBoardSize(null);
256 assertEquals(0, particleEngine
.getParticleCount());
258 particleEngine
.addParticle(Particle
.Type
.values()[0], 0F
, 0F
, 0F
, 0F
);
260 assertEquals(1, particleEngine
.getParticleCount());
262 particleEngine
.addParticle(Particle
.Type
.values()[0], 0F
, 0F
, 0F
, 0F
);
264 assertEquals(2, particleEngine
.getParticleCount());
268 public final void testAddParticlesAndCountWithBounds() {
269 final ParticleEngine particleEngine
= this.createParticleEngine();
271 particleEngine
.setBoardSize(new Dimension());
273 assertEquals(0, particleEngine
.getParticleCount());
275 particleEngine
.addParticle(Particle
.Type
.values()[0], 0F
, 0F
, 0F
, 0F
);
277 assertEquals(1, particleEngine
.getParticleCount());
279 particleEngine
.addParticle(Particle
.Type
.values()[0], 0F
, 0F
, 0F
, 0F
);
281 assertEquals(2, particleEngine
.getParticleCount());
285 public final void testUpdate() {
286 final ParticleEngine particleEngine
= this.createParticleEngine();
287 final ParticleDefaultImplementation particle1
= new ParticleDefaultImplementation(
288 MOBILE_TYPE_1
, 2F
, 3F
, 5F
, 7F
);
289 final ParticleDefaultImplementation particle2
= new ParticleDefaultImplementation(
290 MOBILE_TYPE_2
, 11F
, 13F
, 17F
, 19F
);
292 particleEngine
.setGravity(0F
);
294 addParticle(particleEngine
, particle1
);
295 addParticle(particleEngine
, particle2
);
297 update(particleEngine
, 1F
, SIMULATION_STEP
);
299 final Iterator
<Particle
> particleIterator
= particleEngine
.iterator();
301 assertTrue(particleIterator
.next().getY() > particle1
.getY());
302 assertTrue(particleIterator
.next().getY() > particle2
.getY());
306 public final void testIteratorWithoutBounds() {
307 final ParticleEngine particleEngine
= this.createParticleEngine();
308 final ParticleDefaultImplementation particle1
= new ParticleDefaultImplementation(
309 MOBILE_TYPE_1
, 2F
, 3F
, 5F
, 7F
);
310 final ParticleDefaultImplementation particle2
= new ParticleDefaultImplementation(
311 MOBILE_TYPE_2
, 11F
, 13F
, 17F
, 19F
);
313 particleEngine
.setBoardSize(null);
314 addParticle(particleEngine
, particle1
);
315 addParticle(particleEngine
, particle2
);
317 final Iterator
<Particle
> particleIterator
= particleEngine
.iterator();
318 final Set
<Particle
> expectedParticles
= new HashSet
<Particle
>();
320 expectedParticles
.add(particle1
);
321 expectedParticles
.add(particle2
);
323 for (int i
= expectedParticles
.size(); i
> 0; --i
) {
324 assertTrue("expected at least " + (i
+ 1) + " particles", particleIterator
.hasNext());
326 final Particle particle
= particleIterator
.next();
328 assertTrue("unexpected particle " + particle
, expectedParticles
.contains(particle
));
330 expectedParticles
.remove(particle
);
332 assertTrue("missing particles " + expectedParticles
, expectedParticles
.isEmpty());
333 assertFalse(particleIterator
.hasNext());
337 public final void testIteratorWithBounds() {
338 final ParticleEngine particleEngine
= this.createParticleEngine();
339 final ParticleDefaultImplementation particle1
= new ParticleDefaultImplementation(
340 MOBILE_TYPE_1
, 2F
, 3F
, 5F
, 7F
);
341 final ParticleDefaultImplementation particle2
= new ParticleDefaultImplementation(
342 MOBILE_TYPE_2
, 11F
, 13F
, 17F
, 19F
);
344 particleEngine
.setBoardSize(new Dimension());
345 addParticle(particleEngine
, particle1
);
346 addParticle(particleEngine
, particle2
);
348 final Iterator
<Particle
> particleIterator
= particleEngine
.iterator();
349 final Set
<Particle
> expectedParticles
= new HashSet
<Particle
>();
351 expectedParticles
.add(particle1
);
352 expectedParticles
.add(particle2
);
354 for (int i
= expectedParticles
.size(); i
> 0; --i
) {
355 assertTrue("expected at least " + (i
+ 1) + " particles", particleIterator
.hasNext());
357 final Particle particle
= particleIterator
.next();
359 assertTrue("unexpected particle " + particle
, expectedParticles
.contains(particle
));
361 expectedParticles
.remove(particle
);
363 assertTrue("missing particles " + expectedParticles
, expectedParticles
.isEmpty());
364 assertFalse(particleIterator
.hasNext());
371 * <br>A non-null value
373 protected abstract ParticleEngine
createParticleEngine();
375 protected static final float DELTA
= 1e-12F
;
377 protected static final float SIMULATION_STEP
= 1.0F
/ 60.0F
;
379 protected static final Particle
.Type IMMOBILE_TYPE
= Particle
.Type
.IMMOBILE
;
381 protected static final Particle
.Type MOBILE_TYPE_1
= Particle
.Type
.SAND
;
383 protected static final Particle
.Type MOBILE_TYPE_2
= Particle
.Type
.WATER
;
387 * @param particleEngine
388 * <br>Should not be null
390 * <br>Should not be null
392 protected static final void addParticle(final ParticleEngine particleEngine
, final Particle particle
) {
393 particleEngine
.addParticle(particle
.getType(), particle
.getX(), particle
.getY(), particle
.getSpeedX(), particle
.getSpeedY());
398 * @param particleEngine
399 * <br>Should not be null
401 * <br>Range: <code>[0F .. Float.POSITIVE_INFINITY[</code>
403 * <br>Range: <code>]0F .. Float.POSITIVE_INFINITY[</code>
405 protected static final void update(final ParticleEngine particleEngine
, final float duration
, final float deltaTime
) {
408 while (time
< duration
) {
409 particleEngine
.update(deltaTime
);