private boolean dirty;\r
\r
/**\r
+ * Creates an uninitialized sprite. The sprite will need a texture, texture region, bounds, and color set before it can be\r
+ * drawn.\r
+ */\r
+ public Sprite () {\r
+ }\r
+\r
+ /**\r
* Creates a sprite with width, height, and texture region equal to the size of the texture.\r
*/\r
public Sprite (Texture texture) {\r
/**\r
* Creates a sprite with width, height, and texture region equal to the specified size. The texture region's upper left corner\r
* will be 0,0.\r
+ * @param srcWidth The width of the texture region. May be negative to flip the sprite when drawn.\r
+ * @param srcHeight The height of the texture region. May be negative to flip the sprite when drawn.\r
*/\r
public Sprite (Texture texture, int srcWidth, int srcHeight) {\r
this(texture, 0, 0, srcWidth, srcHeight);\r
\r
/**\r
* Creates a sprite with width, height, and texture region equal to the specified size.\r
+ * @param srcWidth The width of the texture region. May be negative to flip the sprite when drawn.\r
+ * @param srcHeight The height of the texture region. May be negative to flip the sprite when drawn.\r
*/\r
public Sprite (Texture texture, int srcX, int srcY, int srcWidth, int srcHeight) {\r
if (texture == null) throw new IllegalArgumentException("texture cannot be null.");\r
this.texture = texture;\r
setTextureRegion(srcX, srcY, srcWidth, srcHeight);\r
setColor(1, 1, 1, 1);\r
- setBounds(0, 0, Math.abs(srcWidth), Math.abs(srcHeight));\r
+ setSize(Math.abs(srcWidth), Math.abs(srcHeight));\r
setOrigin(width / 2, height / 2);\r
}\r
\r
/**\r
* Creates a sprite with width, height, and texture region equal to the specified size, relative to specified sprite's texture\r
* region.\r
+ * @param srcWidth The width of the texture region. May be negative to flip the sprite when drawn.\r
+ * @param srcHeight The height of the texture region. May be negative to flip the sprite when drawn.\r
*/\r
public Sprite (Sprite parent, int srcX, int srcY, int srcWidth, int srcHeight) {\r
this(parent.texture, (int)(srcX + parent.vertices[U1] * parent.texture.getWidth()), (int)(srcY + parent.vertices[V2]\r
}\r
\r
/**\r
- * Sets the size and position of the sprite when drawn, before scaling and rotation are applied. If origin, rotation, or scale\r
- * are changed, it is slightly more efficient to set the bounds afterward.\r
+ * Sets the position and size of the sprite when drawn, before scaling and rotation are applied. If origin, rotation, or scale\r
+ * are changed, it is slightly more efficient to set the bounds after those operations.\r
*/\r
public void setBounds (float x, float y, float width, float height) {\r
this.x = x;\r
\r
/**\r
* Sets the size of the sprite when drawn, before scaling and rotation are applied. If origin, rotation, or scale are changed,\r
- * it is slightly more efficient to set the size afterward. If both position and size are to be changed, it is better to use\r
- * {@link #setBounds(float, float, float, float)}.\r
+ * it is slightly more efficient to set the size after those operations. If both position and size are to be changed, it is\r
+ * better to use {@link #setBounds(float, float, float, float)}.\r
*/\r
public void setSize (float width, float height) {\r
this.width = width;\r
\r
/**\r
* Sets the position where the sprite will be drawn. If origin, rotation, or scale are changed, it is slightly more efficient\r
- * to set the position afterward. If both position and size are to be changed, it is better to use\r
+ * to set the position after those operations. If both position and size are to be changed, it is better to use\r
* {@link #setBounds(float, float, float, float)}.\r
*/\r
public void setPosition (float x, float y) {\r
\r
/**\r
* Sets the position relative to the current position where the sprite will be drawn. If origin, rotation, or scale are\r
- * changed, it is slightly more efficient to translate afterward.\r
+ * changed, it is slightly more efficient to translate after those operations.\r
*/\r
public void translate (float xAmount, float yAmount) {\r
x += xAmount;\r
}\r
\r
/**\r
- * Sets the texture coordinates in pixels to apply to the sprite.\r
+ * Sets the texture coordinates in pixels to apply to the sprite. This resets calling {@link #flip(boolean, boolean)}.\r
+ * @param srcWidth The width of the texture region. May be negative to flip the sprite when drawn.\r
+ * @param srcHeight The height of the texture region. May be negative to flip the sprite when drawn.\r
*/\r
public void setTextureRegion (int srcX, int srcY, int srcWidth, int srcHeight) {\r
float invTexWidth = 1.0f / texture.getWidth();\r
}\r
\r
/**\r
- * Flips the texture.\r
+ * Flips the current texture region.\r
*/\r
public void flip (boolean x, boolean y) {\r
float[] vertices = this.vertices;\r
import java.io.BufferedReader;\r
import java.io.IOException;\r
import java.io.Writer;\r
-import java.math.BigInteger;\r
import java.util.BitSet;\r
\r
import com.badlogic.gdx.graphics.GL10;\r
import com.badlogic.gdx.graphics.Texture;\r
import com.badlogic.gdx.utils.MathUtils;\r
\r
-// BOZO - Support point particles?\r
+// BOZO - Javadoc.\r
// BOZO - Add a duplicate emitter button.\r
\r
public class ParticleEmitter {\r
private boolean flipX, flipY;\r
private int updateFlags;\r
\r
- private float emission, emissionDiff, emissionDelta;\r
- private float lifeOffset, lifeOffsetDiff;\r
- private float life, lifeDiff;\r
+ private int emission, emissionDiff, emissionDelta;\r
+ private int lifeOffset, lifeOffsetDiff;\r
+ private int life, lifeDiff;\r
private int spawnWidth, spawnWidthDiff;\r
private int spawnHeight, spawnHeightDiff;\r
public float duration = 1, durationTimer;\r
private boolean additive = true;\r
\r
public ParticleEmitter () {\r
- this((Texture)null);\r
- }\r
-\r
- public ParticleEmitter (Texture texture) {\r
- this.texture = texture;\r
-\r
initialize();\r
-\r
- durationValue.setLow(3, 3);\r
-\r
- emissionValue.setHigh(10, 10);\r
-\r
- lifeValue.setHigh(1, 1);\r
-\r
- scaleValue.setHigh(32, 32);\r
-\r
- rotationValue.setLow(1, 360);\r
- rotationValue.setHigh(180, 180);\r
- rotationValue.setTimeline(new float[] {0, 1});\r
- rotationValue.setScaling(new float[] {0, 1});\r
- rotationValue.setRelative(true);\r
-\r
- angleValue.setHigh(1, 360);\r
- angleValue.setActive(true);\r
-\r
- velocityValue.setHigh(80, 80);\r
- velocityValue.setActive(true);\r
-\r
- transparencyValue.setHigh(1, 1);\r
- transparencyValue.setTimeline(new float[] {0, 0.2f, 0.8f, 1});\r
- transparencyValue.setScaling(new float[] {0, 1, 1, 0});\r
}\r
\r
public ParticleEmitter (BufferedReader reader) throws IOException {\r
\r
public void draw (SpriteBatch spriteBatch, float delta) {\r
delta = Math.min(delta, 0.250f);\r
+ int deltaMillis = (int)(delta * 1000);\r
\r
if (additive) spriteBatch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);\r
\r
while (true) {\r
index = active.nextSetBit(index);\r
if (index == -1) break;\r
- if (updateParticle(index, delta))\r
+ if (updateParticle(index, delta, deltaMillis))\r
particles[index].draw(spriteBatch);\r
else {\r
active.clear(index);\r
if (additive) spriteBatch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);\r
\r
if (delayTimer < delay) {\r
- delayTimer += delta;\r
+ delayTimer += deltaMillis;\r
return;\r
}\r
\r
}\r
\r
if (durationTimer < duration)\r
- durationTimer += delta;\r
+ durationTimer += deltaMillis;\r
else {\r
if (!continuous) return;\r
restart();\r
}\r
\r
- emissionDelta += delta;\r
+ emissionDelta += deltaMillis;\r
float emissionTime = emission + emissionDiff * emissionValue.getScale(durationTimer / (float)duration);\r
if (emissionTime > 0) {\r
- emissionTime = 1 / emissionTime;\r
+ emissionTime = 1000 / emissionTime;\r
if (emissionDelta >= emissionTime) {\r
int emitCount = (int)(emissionDelta / emissionTime);\r
emitCount = Math.min(emitCount, maxParticleCount - activeCount);\r
durationTimer -= duration;\r
duration = durationValue.newLowValue();\r
\r
- emission = emissionValue.newLowValue();\r
- emissionDiff = emissionValue.newHighValue();\r
+ emission = (int)emissionValue.newLowValue();\r
+ emissionDiff = (int)emissionValue.newHighValue();\r
if (!emissionValue.isRelative()) emissionDiff -= emission;\r
\r
- life = lifeValue.newLowValue();\r
- lifeDiff = lifeValue.newHighValue();\r
+ life = (int)lifeValue.newLowValue();\r
+ lifeDiff = (int)lifeValue.newHighValue();\r
if (!lifeValue.isRelative()) lifeDiff -= life;\r
\r
- lifeOffset = lifeOffsetValue.active ? lifeOffsetValue.newLowValue() : 0;\r
- lifeOffsetDiff = lifeOffsetValue.newHighValue();\r
+ lifeOffset = lifeOffsetValue.active ? (int)lifeOffsetValue.newLowValue() : 0;\r
+ lifeOffsetDiff = (int)lifeOffsetValue.newHighValue();\r
if (!lifeOffsetValue.isRelative()) lifeOffsetDiff -= lifeOffset;\r
\r
spawnWidth = (int)spawnWidthValue.newLowValue();\r
if (tintValue.timeline.length > 1) updateFlags |= UPDATE_TINT;\r
}\r
\r
- public void activateParticle (int index) {\r
+ private void activateParticle (int index) {\r
Particle particle = particles[index];\r
if (particle == null) {\r
particles[index] = particle = new Particle(texture);\r
int updateFlags = this.updateFlags;\r
\r
float offsetTime = lifeOffset + lifeOffsetDiff * lifeOffsetValue.getScale(percent);\r
- particle.life = particle.currentLife = life + lifeDiff * lifeValue.getScale(percent);\r
+ particle.life = particle.currentLife = life + (int)(lifeDiff * lifeValue.getScale(percent));\r
\r
if (velocityValue.active) {\r
particle.velocity = velocityValue.newLowValue();\r
particle.angle = angleValue.newLowValue();\r
particle.angleDiff = angleValue.newHighValue();\r
if (!angleValue.isRelative()) particle.angleDiff -= particle.angle;\r
- if ((updateFlags & UPDATE_ANGLE) == 0) particle.angle = particle.angle + particle.angleDiff * angleValue.getScale(0);\r
+ if ((updateFlags & UPDATE_ANGLE) == 0) {\r
+ float angle = particle.angle + particle.angleDiff * angleValue.getScale(0);\r
+ particle.angle = angle;\r
+ particle.angleCos = MathUtils.cosDeg(angle);\r
+ particle.angleSin = MathUtils.sinDeg(angle);\r
+ }\r
\r
particle.scale = scaleValue.newLowValue() / texture.getWidth();\r
particle.scaleDiff = scaleValue.newHighValue() / texture.getWidth();\r
particle.setBounds(x - texture.getWidth() / 2, y - texture.getHeight() / 2, texture.getWidth(), texture.getHeight());\r
}\r
\r
- public boolean updateParticle (int index, float delta) {\r
+ private boolean updateParticle (int index, float delta, int deltaMillis) {\r
Particle particle = particles[index];\r
- float life = particle.currentLife - delta;\r
+ int life = particle.currentLife - deltaMillis;\r
if (life <= 0) return false;\r
particle.currentLife = life;\r
\r
- float percent = 1 - particle.currentLife / particle.life;\r
+ float percent = 1 - particle.currentLife / (float)particle.life;\r
int updateFlags = this.updateFlags;\r
\r
if ((updateFlags & UPDATE_SCALE) != 0)\r
particle.setScale(particle.scale + particle.scaleDiff * scaleValue.getScale(percent));\r
\r
- float angle = particle.angle;\r
- if ((updateFlags & UPDATE_ANGLE) != 0) angle += particle.angleDiff * angleValue.getScale(percent);\r
-\r
- if ((updateFlags & UPDATE_ROTATION) != 0) {\r
- float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(percent);\r
- if (aligned) rotation += angle;\r
- if (rotation != 0) particle.setRotation(rotation);\r
- }\r
-\r
if ((updateFlags & UPDATE_VELOCITY) != 0) {\r
float velocity = (particle.velocity + particle.velocityDiff * velocityValue.getScale(percent)) * delta;\r
- float velocityX = velocity * MathUtils.cosDeg(angle);\r
- float velocityY = velocity * MathUtils.sinDeg(angle);\r
+\r
+ float velocityX, velocityY;\r
+ if ((updateFlags & UPDATE_ANGLE) != 0) {\r
+ float angle = particle.angle += particle.angleDiff * angleValue.getScale(percent);\r
+ velocityX = velocity * MathUtils.cosDeg(angle);\r
+ velocityY = velocity * MathUtils.sinDeg(angle);\r
+ if ((updateFlags & UPDATE_ROTATION) != 0) {\r
+ float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(percent);\r
+ if (aligned) rotation += angle;\r
+ particle.setRotation(rotation);\r
+ }\r
+ } else {\r
+ velocityX = velocity * particle.angleCos;\r
+ velocityY = velocity * particle.angleSin;\r
+ if ((updateFlags & UPDATE_ROTATION) != 0) {\r
+ float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(percent);\r
+ if (aligned) rotation += particle.angle;\r
+ particle.setRotation(rotation);\r
+ }\r
+ }\r
+\r
if ((updateFlags & UPDATE_WIND) != 0)\r
velocityX += (particle.wind + particle.windDiff * windValue.getScale(percent)) * delta;\r
+\r
if ((updateFlags & UPDATE_GRAVITY) != 0)\r
velocityY += (particle.gravity + particle.gravityDiff * gravityValue.getScale(percent)) * delta;\r
+\r
particle.translate(velocityX, velocityY);\r
+ } else {\r
+ if ((updateFlags & UPDATE_ROTATION) != 0)\r
+ particle.setRotation(particle.rotation + particle.rotationDiff * rotationValue.getScale(percent));\r
}\r
\r
float[] color;\r
}\r
\r
public void load (BufferedReader reader) throws IOException {\r
- name = readString(reader, "name");\r
- reader.readLine();\r
- delayValue.load(reader);\r
- reader.readLine();\r
- durationValue.load(reader);\r
- reader.readLine();\r
- setMinParticleCount(readInt(reader, "minParticleCount"));\r
- setMaxParticleCount(readInt(reader, "maxParticleCount"));\r
- reader.readLine();\r
- emissionValue.load(reader);\r
- reader.readLine();\r
- lifeValue.load(reader);\r
- reader.readLine();\r
- lifeOffsetValue.load(reader);\r
- reader.readLine();\r
- xOffsetValue.load(reader);\r
- reader.readLine();\r
- yOffsetValue.load(reader);\r
- reader.readLine();\r
- spawnShapeValue.load(reader);\r
- reader.readLine();\r
- spawnWidthValue.load(reader);\r
- reader.readLine();\r
- spawnHeightValue.load(reader);\r
- reader.readLine();\r
- scaleValue.load(reader);\r
- reader.readLine();\r
- velocityValue.load(reader);\r
- reader.readLine();\r
- angleValue.load(reader);\r
- reader.readLine();\r
- rotationValue.load(reader);\r
- reader.readLine();\r
- windValue.load(reader);\r
- reader.readLine();\r
- gravityValue.load(reader);\r
- reader.readLine();\r
- tintValue.load(reader);\r
- reader.readLine();\r
- transparencyValue.load(reader);\r
- reader.readLine();\r
- attached = readBoolean(reader, "attached");\r
- continuous = readBoolean(reader, "continuous");\r
- aligned = readBoolean(reader, "aligned");\r
- additive = readBoolean(reader, "additive");\r
- behind = readBoolean(reader, "behind");\r
+ try {\r
+ name = readString(reader, "name");\r
+ reader.readLine();\r
+ delayValue.load(reader);\r
+ reader.readLine();\r
+ durationValue.load(reader);\r
+ reader.readLine();\r
+ setMinParticleCount(readInt(reader, "minParticleCount"));\r
+ setMaxParticleCount(readInt(reader, "maxParticleCount"));\r
+ reader.readLine();\r
+ emissionValue.load(reader);\r
+ reader.readLine();\r
+ lifeValue.load(reader);\r
+ reader.readLine();\r
+ lifeOffsetValue.load(reader);\r
+ reader.readLine();\r
+ xOffsetValue.load(reader);\r
+ reader.readLine();\r
+ yOffsetValue.load(reader);\r
+ reader.readLine();\r
+ spawnShapeValue.load(reader);\r
+ reader.readLine();\r
+ spawnWidthValue.load(reader);\r
+ reader.readLine();\r
+ spawnHeightValue.load(reader);\r
+ reader.readLine();\r
+ scaleValue.load(reader);\r
+ reader.readLine();\r
+ velocityValue.load(reader);\r
+ reader.readLine();\r
+ angleValue.load(reader);\r
+ reader.readLine();\r
+ rotationValue.load(reader);\r
+ reader.readLine();\r
+ windValue.load(reader);\r
+ reader.readLine();\r
+ gravityValue.load(reader);\r
+ reader.readLine();\r
+ tintValue.load(reader);\r
+ reader.readLine();\r
+ transparencyValue.load(reader);\r
+ reader.readLine();\r
+ attached = readBoolean(reader, "attached");\r
+ continuous = readBoolean(reader, "continuous");\r
+ aligned = readBoolean(reader, "aligned");\r
+ additive = readBoolean(reader, "additive");\r
+ behind = readBoolean(reader, "behind");\r
+ } catch (RuntimeException ex) {\r
+ if (name == null) throw ex;\r
+ throw new RuntimeException("Error parsing emitter: " + name, ex);\r
+ }\r
}\r
\r
static String readString (BufferedReader reader, String name) throws IOException {\r
}\r
\r
static class Particle extends Sprite {\r
- float life, currentLife;\r
+ int life, currentLife;\r
float scale, scaleDiff;\r
float rotation, rotationDiff;\r
float velocity, velocityDiff;\r
float angle, angleDiff;\r
+ float angleCos, angleSin;\r
float transparency, transparencyDiff;\r
float wind, windDiff;\r
float gravity, gravityDiff;\r