From 6af2ce1d4708d1f7c48f9d4a3118f9d73f18f602 Mon Sep 17 00:00:00 2001 From: codistmonk Date: Sat, 8 May 2010 14:37:36 +0000 Subject: [PATCH] Removed ability for the user to create particles outside the drawing board. Updated the cellular engine; task #24 is done. git-svn-id: https://desert.svn.sourceforge.net/svnroot/desert@93 cbff3641-ea5c-438d-a1bd-c9f42921e016 --- nbproject/configs/JWS_generated.properties | 1 + nbproject/project.properties | 2 +- .../ParticleEngineCellularImplementation.java | 287 ++++++++++++--------- src/org/sourceforge/desert/ui/DrawingBoard.java | 2 +- 4 files changed, 169 insertions(+), 123 deletions(-) diff --git a/nbproject/configs/JWS_generated.properties b/nbproject/configs/JWS_generated.properties index 8e214b4..450d1f4 100644 --- a/nbproject/configs/JWS_generated.properties +++ b/nbproject/configs/JWS_generated.properties @@ -3,3 +3,4 @@ $target.debug=jws-debug $target.run=jws-run compile.on.save.unsupported.javawebstart=false main.class=org.sourceforge.desert.ui.DesertMain +run.jvmargs=-ea -Djava.security.policy=applet.policy diff --git a/nbproject/project.properties b/nbproject/project.properties index 0a1b58f..9e62176 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -64,7 +64,7 @@ jnlp.codebase.type=user jnlp.codebase.user=http://desert.sourceforge.net/ jnlp.descriptor=applet jnlp.enabled=true -jnlp.offline-allowed=false +jnlp.offline-allowed=true jnlp.signed=true main.class=org.sourceforge.desert.DesertMain manifest.file=manifest.mf diff --git a/src/org/sourceforge/desert/ParticleEngineCellularImplementation.java b/src/org/sourceforge/desert/ParticleEngineCellularImplementation.java index 02c501a..6c9b0f0 100644 --- a/src/org/sourceforge/desert/ParticleEngineCellularImplementation.java +++ b/src/org/sourceforge/desert/ParticleEngineCellularImplementation.java @@ -38,36 +38,95 @@ import static org.sourceforge.desert.Utilities.*; */ public class ParticleEngineCellularImplementation extends AbstractParticleEngineCustomImplementation { + private long newParticleId; + private ParticleCellularImplementation[][] cells; + private final ParticleCellularImplementation borderParticle; + /** * This variable is part of a temporary measure to detect particle deletion. *
TODO remove when deletion is handled correctly */ private int lastParticleCount; + public ParticleEngineCellularImplementation() { + this.newParticleId = Long.MIN_VALUE; + this.borderParticle = this.new ParticleCellularImplementation(Particle.Type.IMMOBILE, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 0F, 0F); + + this.setGravity(MAXIMUM_SPEED * signum(this.getGravity())); + } + @Override public final void update(float deltaTime) { this.updateCells(); + this.applyForces(deltaTime); + + this.updatePositions(deltaTime); + } + + @Override + protected final void particleAdded(final ParticleDefaultImplementation particle) { + this.setCell(particle.getX(), particle.getY(), (ParticleCellularImplementation) particle); + } + + @Override + protected final ParticleDefaultImplementation createParticle(final Particle.Type type, final float x, final float y, final float speedX, final float speedY) { + return new ParticleCellularImplementation(type, x, y, speedX, speedY); + } + + @Override + protected final void boardSizeChanged() { + if (this.getBoardSize() != null && this.getBoardSize().width > 0 && this.getBoardSize().height > 0) { + this.cells = new ParticleCellularImplementation[this.getBoardSize().width][this.getBoardSize().height]; + + this.fillCells(); + } else { + this.cells = null; + } + } + + final long generateNewId() { + return this.newParticleId++; + } + + /** + * + * @param deltaTime in seconds + *
Range: [0F .. Float.POSITIVE_INFINITY[ + */ + private final void applyForces(final float deltaTime) { for (final ParticleCellularImplementation particle : this.getParticles()) { if (particle.getType().isMobile()) { + if (particle.getType() == Particle.Type.WATER) { + if (particle.getSpeedX() == 0F && particle.getSpeedY() == 0F) { + final float direction = random() > 0.5 ? 1F : -1F; + + if (this.isCellTraversable(particle.getX() + direction, particle.getY(), particle)) { + particle.setSpeedX(direction * MAXIMUM_SPEED * (0.5F + (float) random())); + } + else if (this.isCellTraversable(particle.getX() - direction, particle.getY(), particle)) { + particle.setSpeedX(-direction * MAXIMUM_SPEED * (0.5F + (float) random())); + } + } + } + particle.setSpeedY(particle.getSpeedY() + this.getGravity() * deltaTime); if (abs(particle.getSpeedY()) > MAXIMUM_SPEED) { particle.setSpeedY(signum(particle.getSpeedY()) * MAXIMUM_SPEED); } - - if (!particle.isAlreadyMoved()) { - particle.setSpeedX(0F); - particle.setSpeedY(0F); - } - - particle.setAlreadyMoved(false); - particle.getReplacementCandidates().clear(); } } + } + /** + * + * @param deltaTime + *
Range: [0F .. Float.POSITIVE_INFINITY[ + */ + private final void updatePositions(final float deltaTime) { for (final ParticleCellularImplementation particle : this.getParticles()) { if (particle.getType().isMobile()) { final float dX = signum(particle.getSpeedX()); @@ -90,46 +149,10 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine this.tryAndMove(particle, particle.getSpeedX() == 0F ? oldX : newX, particle.getSpeedY() == 0F ? oldY : newY); - - if (particle.getType() == Particle.Type.WATER) { - if (particle.getSpeedX() == 0F && particle.getSpeedY() == 0F) { - final float direction = random() > 0.5 ? 1F : -1F; - - if (this.isCellTraversable(oldX + direction, oldY, particle)) { - particle.setSpeedX(direction * MAXIMUM_SPEED * (0.5F + (float) random())); - } - else if (this.isCellTraversable(oldX - direction, oldY, particle)) { - particle.setSpeedX(-direction * MAXIMUM_SPEED * (0.5F + (float) random())); - } - } - } } } } - private static final float MAXIMUM_SPEED = 25F; - - @Override - protected final void particleAdded(final ParticleDefaultImplementation particle) { - this.setCell(particle.getX(), particle.getY(), (ParticleCellularImplementation) particle); - } - - @Override - protected final ParticleDefaultImplementation createParticle(final Particle.Type type, final float x, final float y, final float speedX, final float speedY) { - return new ParticleCellularImplementation(type, x, y, speedX, speedY); - } - - @Override - protected final void boardSizeChanged() { - if (this.getBoardSize() != null && this.getBoardSize().width > 0 && this.getBoardSize().height > 0) { - this.cells = new ParticleCellularImplementation[this.getBoardSize().width][this.getBoardSize().height]; - - this.fillCells(); - } else { - this.cells = null; - } - } - private final void fillCells() { for (final ParticleCellularImplementation particle : this.getParticles()) { this.setCell(particle.getX(), particle.getY(), particle); @@ -147,24 +170,27 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine *
Can be null *
Reference parameter */ - private final void setCell(final float x, final float y, final ParticleCellularImplementation particle) { + final void setCell(final float x, final float y, final ParticleCellularImplementation particle) { + assert particle == null || (int) x == (int) particle.getX() : x + " " + y + " " + particle; + assert particle == null || (int) y == (int) particle.getY() : x + " " + y + " " + particle; + if (this.isInGrid(x, y) && (this.cells[(int) x][(int) y] == null || this.cells[(int) x][(int) y].getType().isMobile())) { this.cells[(int) x][(int) y] = particle; } } /** - * + * This method returns this.borderParticle if the coordinates do not locate a valid cell. * @param x *
Range: [Float.NEGATIVE_INFINITY .. Float.POSITIVE_INFINITY] * @param y *
Range: [Float.NEGATIVE_INFINITY .. Float.POSITIVE_INFINITY] * @return - *
A possibly null value + *
A non-null value *
A reference */ private final ParticleCellularImplementation getParticle(final float x, final float y) { - return this.isInGrid(x, y) ? this.cells[(int) x][(int) y] : null; + return this.isInGrid(x, y) ? this.cells[(int) x][(int) y] : this.borderParticle; } /** @@ -219,69 +245,17 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine * @param newY *
Range: [Float.NEGATIVE_INFINITY .. Float.POSITIVE_INFINITY] */ - private final boolean tryAndMove(final ParticleCellularImplementation particle, final float newX, final float newY) { - final float oldX = particle.getX(); - final float oldY = particle.getY(); - - if ((int) oldX != (int) newX || (int) oldY != (int) newY) { - final ParticleCellularImplementation replaced = this.getParticle(newX, newY); - - if (replaced == null) { - this.setCell(oldX, oldY, null); + private final void tryAndMove(final ParticleCellularImplementation particle, final float newX, final float newY) { + particle.setTargetLocation(newX, newY); - this.move(particle, newX, newY); + final ParticleCellularImplementation target = this.getParticle(newX, newY); - if (!particle.getReplacementCandidates().isEmpty()) { - this.tryAndMove(particle.getReplacementCandidates().get(0), oldX, oldY); - } - } - else if (replaced.getType().isMobile()) { - if (replaced.getType().getMass() < particle.getType().getMass()) { - replaced.setX(oldX); - replaced.setY(oldY); - replaced.getReplacementCandidates().clear(); - this.setCell(oldX, oldY, replaced); - - this.move(particle, newX, newY); - - if (!particle.getReplacementCandidates().isEmpty()) { - this.tryAndMove(particle.getReplacementCandidates().get(0), oldX, oldY); - } - } - else if (!replaced.isAlreadyMoved()) { - replaced.getReplacementCandidates().add(particle); - - return false; - } - } - else { - return false; - } + if (target == null) { + particle.processReplacementCandidate(particle); } else { - this.move(particle, newX, newY); + target.processReplacementCandidate(particle); } - - return true; - } - - /** - * - * @param particle - *
Should not be null - *
Input-output parameter - *
Reference parameter - *
A reference - * @param newX - *
Range: [Float.NEGATIVE_INFINITY .. Float.POSITIVE_INFINITY] - * @param newY - *
Range: [Float.NEGATIVE_INFINITY .. Float.POSITIVE_INFINITY] - */ - private final void move(final ParticleCellularImplementation particle, final float newX, final float newY) { - particle.setX(newX); - particle.setY(newY); - particle.setAlreadyMoved(true); - this.setCell(newX, newY, particle); } /** @@ -314,11 +288,15 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine * * @author codistmonk (creation 2010-05-06) */ - private static final class ParticleCellularImplementation extends ParticleDefaultImplementation { + private final class ParticleCellularImplementation extends ParticleDefaultImplementation { + + private final long id; private final List replacementCandidates; - private boolean alreadyMoved; + private float targetX; + + private float targetY; /** * @@ -337,10 +315,10 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine *
Should not be null *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ */ - public ParticleCellularImplementation(Type type, float x, float y, float speedX, float speedY) { + public ParticleCellularImplementation(final Type type, final float x, final float y, final float speedX, final float speedY) { super(type, x, y, speedX, speedY); + this.id = ParticleEngineCellularImplementation.this.generateNewId(); this.replacementCandidates = new ArrayList(4); - this.alreadyMoved = false; } public ParticleCellularImplementation() { @@ -348,27 +326,94 @@ public class ParticleEngineCellularImplementation extends AbstractParticleEngine } /** - * - * @return - *
A non-null value - *
A reference + * + * @param particle + *
Should not be null + *
Input-output parameter + *
Reference parameter */ - public final List getReplacementCandidates() { - return replacementCandidates; + public final void processReplacementCandidate(final ParticleCellularImplementation particle) { + assert this == particle || (int) particle.targetX == (int) this.getX() : this + " " + particle; + assert this == particle || (int) particle.targetY == (int) this.getY() : this + " " + particle; + + if (!this.getType().isMobile()) { + return; + } + + if (particle.getType().getMass() > this.getType().getMass()) { + this.replacementCandidates.clear(); + this.replacementCandidates.addAll(particle.replacementCandidates); + particle.replacementCandidates.clear(); + this.setTargetLocation(particle.getX(), particle.getY()); + this.move(); + particle.updateNewLocation(particle.targetX, particle.targetY); + } + else if (particle.id < this.id) { + this.replacementCandidates.add(particle); + } + else if (particle.id == this.id) { + this.move(); + } } - public boolean isAlreadyMoved() { - return alreadyMoved; + /** + * + * @param targetX + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ + * @param targetY + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ + */ + public final void setTargetLocation(final float targetX, final float targetY) { + this.targetX = targetX; + this.targetY = targetY; + } + + private final void move() { + if ((int) this.targetX != this.getX() || (int) this.targetY != this.getY()) { + this.updateOldAndNewLocation(this.targetX, this.targetY); + + if (!this.replacementCandidates.isEmpty()) { + final ParticleCellularImplementation replacement = this.replacementCandidates.get(0); + + this.replacementCandidates.clear(); + + replacement.move(); + } + } + else { + this.updateOldAndNewLocation(this.targetX, this.targetY); + } } /** * - * @param alreadyMoved + * @param newX + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ + * @param newY + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ */ - public final void setAlreadyMoved(final boolean alreadyMoved) { - this.alreadyMoved = alreadyMoved; + private final void updateOldAndNewLocation(final float newX, final float newY) { + ParticleEngineCellularImplementation.this.setCell(this.getX(), this.getY(), null); + + this.updateNewLocation(newX, newY); + } + + /** + * + * @param newX + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ + * @param newY + *
Range: ]float.NEGATIVE_INFINITY .. float.POSITIVE_INFINITY[ + */ + private final void updateNewLocation(final float newX, final float newY) { + this.setX(newX); + this.setY(newY); + + ParticleEngineCellularImplementation.this.setCell(this.getX(), this.getY(), this); } } + private static final float MAXIMUM_SPEED = 25F; + } diff --git a/src/org/sourceforge/desert/ui/DrawingBoard.java b/src/org/sourceforge/desert/ui/DrawingBoard.java index c07e609..4612318 100644 --- a/src/org/sourceforge/desert/ui/DrawingBoard.java +++ b/src/org/sourceforge/desert/ui/DrawingBoard.java @@ -292,7 +292,7 @@ public class DrawingBoard extends Canvas implements ActionListener { * @return true if the specified location is outside the board or contain no particle */ final boolean canAddParticle(final int x, final int y) { - return !this.isInsideBoard(x, y) || !this.particleMask[y][x]; + return this.isInsideBoard(x, y) && !this.particleMask[y][x]; } private final void clearBuffer() { -- 2.11.4.GIT