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 static org
.sourceforge
.desert
.Utilities
.*;
32 * @author codistmonk (creation 2010-04-13)
34 public class ParticleEngineCustomImplementation
extends AbstractParticleEngineCustomImplementation
{
36 private int lastParticleCount
;
38 private Particle
[][] grid
;
41 public final void update(final float deltaTime
) {
44 for (final Particle particle
: this) {
45 if (particle
.getType().isMobile()) {
46 this.updateSpeed((ParticleDefaultImplementation
) particle
, deltaTime
);
50 for (final Particle particle
: this) {
51 if (particle
.getType().isMobile()) {
52 this.updatePosition((ParticleDefaultImplementation
) particle
, deltaTime
);
58 protected final void boardSizeChanged() {
59 if (this.getBoardSize() != null && this.getBoardSize().width
> 0 && this.getBoardSize().height
> 0) {
60 this.grid
= new ParticleDefaultImplementation
[this.getBoardSize().width
][this.getBoardSize().height
];
62 for (final Particle particle
: this) {
63 if (0 <= particle
.getX() && particle
.getX() < this.grid
.length
&& 0 <= particle
.getY() && particle
.getY() < this.grid
[0].length
) {
64 this.grid
[(int) particle
.getX()][(int) particle
.getY()] = particle
;
74 protected final void particleAdded(final ParticleDefaultImplementation particle
) {
75 if (this.grid
!= null && 0 <= particle
.getX() && particle
.getX() < this.grid
.length
&& 0 <= particle
.getY() && particle
.getY() < this.grid
[0].length
) {
76 this.grid
[(int) particle
.getX()][(int) particle
.getY()] = particle
;
80 private final void updateGrid() {
81 if (this.grid
!= null && this.lastParticleCount
!= this.getParticleCount()) {
82 for (int x
= 0; x
< this.grid
.length
; ++x
) {
83 for (int y
= 0; y
< this.grid
[0].length
; ++y
) {
84 this.grid
[x
][y
] = null;
88 for (final Particle particle
: this) {
89 final int x
= (int) particle
.getX();
90 final int y
= (int) particle
.getY();
92 if (0 <= x
&& x
< this.grid
.length
&& 0 <= y
&& y
< this.grid
[0].length
) {
93 this.grid
[x
][y
] = particle
;
97 this.lastParticleCount
= this.getParticleCount();
103 * @param particle A mobile particle
104 * <br>Should not be null
105 * <br>Input-output parameter
107 * <br>Range: <code>[0F .. Float.POSITIVE_INFINITY[</code>
109 private final void updateSpeed(final ParticleDefaultImplementation particle
, final float deltaTime
) {
111 particle
.setSpeedY(particle
.getSpeedY() + this.getGravity() * deltaTime
);
113 // Collisions with surrounding cells
114 for (int i
= -1; i
<= 1; ++i
) {
115 for (int j
= -1; j
<= 1; ++j
) {
116 if (i
!= 0 || j
!= 0) {
117 this.collision(particle
, (int) (particle
.getX() + i
), (int) (particle
.getY() + j
));
122 constrainSpeed(particle
);
128 * <br>Should not be null
129 * <br>Input-output parameter
131 * <br>Range: Any integer
133 * <br>Range: Any integer
135 private final void collision(final ParticleDefaultImplementation particle
, final int x
, final int y
) {
136 if (this.grid
!= null && 0 <= x
&& x
< this.grid
.length
&& 0 <= y
&& y
< this.grid
[0].length
&& this.grid
[x
][y
] != null) {
137 final Particle other
= this.grid
[x
][y
];
138 float uX
= other
.getX() - particle
.getX();
139 float uY
= other
.getY() - particle
.getY();
140 final float u
= length(uX
, uY
);
142 if (0F
< u
&& u
<= particle
.getType().getRadius() + other
.getType().getRadius()) {
146 final float otherCollisionSpeed
= other
.getSpeedX() * uX
+ other
.getSpeedY() * uY
;
147 final float collisionSpeed
= particle
.getSpeedX() * uX
+ particle
.getSpeedY() * uY
;
149 if (collisionSpeed
> 0 && otherCollisionSpeed
<= 0) {
150 // TODO use particles masses
151 particle
.setSpeedX(particle
.getSpeedX() - 2F
* collisionSpeed
* uX
);
152 particle
.setSpeedY(particle
.getSpeedY() - 2F
* collisionSpeed
* uY
);
160 * @param particle A mobile particle
161 * <br>Should not be null
162 * <br>Input-output parameter
164 * <br>Range: <code>[0F .. Float.POSITIVE_INFINITY[</code>
166 private final void updatePosition(final ParticleDefaultImplementation particle
, final float deltaTime
) {
167 float deltaX
= particle
.getSpeedX() * deltaTime
;
168 float deltaY
= particle
.getSpeedY() * deltaTime
;
169 final int pixelCount
= 1 + ((int) length(deltaX
, deltaY
));
170 deltaX
/= pixelCount
;
171 deltaY
/= pixelCount
;
173 for (int i
= 0; i
< pixelCount
; ++i
) {
174 int x
= (int) particle
.getX();
175 int y
= (int) particle
.getY();
177 if (this.grid
!= null && 0 <= x
&& x
< this.grid
.length
&& 0 <= y
&& y
< this.grid
[0].length
&& this.grid
[x
][y
] == particle
) {
178 this.grid
[x
][y
] = null;
181 particle
.setX(particle
.getX() + deltaX
);
182 particle
.setY(particle
.getY() + deltaY
);
184 if (this.grid
!= null) {
185 x
= (int) particle
.getX();
186 y
= (int) particle
.getY();
188 if (0 <= x
&& x
< this.grid
.length
&& 0 <= y
&& y
< this.grid
[0].length
&& this.grid
[x
][y
] == null) {
189 this.grid
[x
][y
] = particle
;
192 particle
.setX(particle
.getX() - 2F
* deltaX
);
193 particle
.setY(particle
.getY() - 2F
* deltaY
);
199 this.constrainPosition(particle
);