processing-android
processing-android copied to clipboard
Array Out of bounds error with PShape.setFill
I have two applications that use PShape.setFill. One of them runs completely fine, the other one crashes. Both of them use size(x, y, P2D) in the setup, so that's not the issue.
The crazy thing is that the code that crashes is the exact same. I use the same class, and the same way to create the object.
My code
class Particle
{
ParticleSystem system;
PVector velocity;
float lifetime;
float lifespan;
PShape part;
float partSize;
Particle(ParticleSystem system)
{
this.system = system;
partSize = 1;
part = createShape();
part.beginShape(QUAD);
part.noStroke();
part.fill(0, 0);
part.normal(0, 0, 1);
//These vertices will be modified later to decide the size
//but we initialize them now to set the direction of each vertices
part.vertex(-partSize/2, -partSize/2);//, 0, 0);
part.vertex(+partSize/2, -partSize/2);//, partSize, 0);
part.vertex(+partSize/2, +partSize/2);//, partSize, partSize);
part.vertex(-partSize/2, +partSize/2);//, 0, partSize);
part.endShape();
lifetime = system.lifespan + system.lifespanD;
}
PShape getShape() {
return part;
}
void rebirth(float x, float y) {
float a = system.angle / 360 * random(TWO_PI);
a += system.rotation;
velocity = new PVector(cos(a), sin(a));
velocity.mult(system.startSpeed + random(-system.startSpeedD, system.startSpeedD));
lifespan = system.lifespan + random(-system.lifespanD, system.lifespanD);
lifetime = 0;
part.setFill(system.startColor);
part.resetMatrix();
part.translate(x, y);
//set particle size
partSize = random(system.minStartSize, system.maxStartSize);
for(int i = 0; i < part.getVertexCount(); i++)
{
PVector v = part.getVertex(i);
v.normalize().mult(partSize/2);
part.setVertex(i, v.x, v.y);
}
}
boolean isDead() {
if (lifetime > lifespan) {
return true;
} else {
return false;
}
}
public void update() {
lifetime += 0.03f;
if(isDead())
{
part.setFill(color(0, 0));
return;
}
if(system.useGravity)
velocity.add(system.gravity.copy().mult(0.03f));
velocity.mult(1 - system.drag * 0.03f);
float lifePercent = lifetime / lifespan;
part.setFill(lerpColor(system.startColor, system.endColor, lifePercent));
part.translate(velocity.x, velocity.y);
for(int i = 0; i < part.getVertexCount(); i++)
{
float scale = lerp(partSize, system.endSize, lifePercent);
PVector v = part.getVertex(i);
v.normalize().mult(scale/2);
part.setVertex(i, v.x, v.y);
}
}
}
It crashes when I call Update with the error: java.lang.ArrayIndexOutOfBoundsException: length=2; index=6 at processing.core.PShape.setFill(PShape.java:2393)
The ParticleSystem class:
class ParticleSystem extends GameObject
{
public boolean loop = false;
public float loopTime = 5f;
public float spawnRate = 10f;
public ArrayList<Burst> bursts = new ArrayList<Burst>();
//Spawning
public float lifespan = 1f;
public float lifespanD = 0f;
//Shape
public float angle = 360f;
//Physics
public float startSpeed = 10f;
public float startSpeedD = 2f;
public float drag = 0f;
public boolean useGravity = false;
public PVector gravity = new PVector(0, 9.81f);
//Visuals
public color startColor = color(255);
public color endColor = color(255, 0);
public int minStartSize = 10;
public int maxStartSize = 10;
public int endSize = 0;
private ArrayList<Particle> particles;
private PShape particleShape;
private boolean isPlaying = false;
ParticleSystem(PVector position, float rotation, int n)
{
this.position = position;
this.rotation = rotation;
particles = new ArrayList<Particle>();
particleShape = createShape(PShape.GROUP);
for (int i = 0; i < n; i++) {
Particle p = new Particle(this);
particles.add(p);
particleShape.addChild(p.getShape());
}
}
private float currentLoopTime = 0;
private float toSpawn = 0;
public void Update() {
if (!isPlaying)
return;
currentLoopTime += Time.deltaTime;
if(currentLoopTime >= loopTime)
{
if(loop)
{
currentLoopTime = 0;
for (Burst b : bursts)
{
b.done = false;
}
}
else if(currentLoopTime >= loopTime + lifespan + lifespanD)
FinishedPlaying();
}
if(currentLoopTime < loopTime)
{
toSpawn += spawnRate * Time.deltaTime;
for (Burst b : bursts)
{
if(!b.done && b.time <= currentLoopTime)
{
toSpawn += b.amount;
b.done = true;
}
}
}
for (Particle p : particles) {
if (toSpawn >= 1 && p.isDead())
{
p.rebirth(position.x, position.y);
toSpawn -= 1;
}
if(!p.isDead())
p.update();
}
}
public void Play()
{
if(isPlaying)
return;
isPlaying = true;
}
public void Stop()
{
if(!isPlaying)
return;
isPlaying = false;
}
private void FinishedPlaying()
{
Stop();
hierarchy.remove(this);
}
public void Draw()
{
if(!isPlaying)
return;
shape(particleShape);
}
}
public class Burst
{
public int amount;
public float time;
public boolean done = false;
public Burst(int amount, float time)
{
this.amount = amount;
this.time = time;
}
}
Here is a code snippet of the one that crashes, it's the exact same as the one that does not, except for that it also does some other things like setup the physics.
ParticleSystem ps;
void setup()
{
size(displayWidth, displayHeight, P2D);
accel = new AccelerometerManager(this);
Utils.screenWidth = width;
Utils.screenHeight = height;
physics = new PhysicsManager();
init = new Initialization();
upgradeFactory = new UpgradeFactory();
ps = new ParticleSystem(new PVector(width/2, height/2), 0, 200);
ps.Play();
}
void draw()
{
Time.Frame(millis());
physics.Loop();
clear();
background (0);
for(int i = hierarchy.size() - 1; i >= 0; i--)
{
hierarchy.get(i).Update();
}
for(int i = hierarchy.size() - 1; i >= 0; i--)
{
hierarchy.get(i).InternalUpdate();
}
for(int i = hierarchy.size() - 1; i >= 0; i--)
{
hierarchy.get(i).Draw();
}
ps.Draw();
ps.Update();
}
I have two applications that use PShape.setFill. One of them runs completely fine, the other one crashes. Both of them use size(x, y, P2D) in the setup, so that's not the issue.
The crazy thing is that the code that crashes is the exact same. I use the same class, and the same way to create the object.
My code
class Particle { ParticleSystem system; PVector velocity; float lifetime; float lifespan; PShape part; float partSize; Particle(ParticleSystem system) { this.system = system; partSize = 1; part = createShape(); part.beginShape(QUAD); part.noStroke(); part.fill(0, 0); part.normal(0, 0, 1); //These vertices will be modified later to decide the size //but we initialize them now to set the direction of each vertices part.vertex(-partSize/2, -partSize/2);//, 0, 0); part.vertex(+partSize/2, -partSize/2);//, partSize, 0); part.vertex(+partSize/2, +partSize/2);//, partSize, partSize); part.vertex(-partSize/2, +partSize/2);//, 0, partSize); part.endShape(); lifetime = system.lifespan + system.lifespanD; } PShape getShape() { return part; } void rebirth(float x, float y) { float a = system.angle / 360 * random(TWO_PI); a += system.rotation; velocity = new PVector(cos(a), sin(a)); velocity.mult(system.startSpeed + random(-system.startSpeedD, system.startSpeedD)); lifespan = system.lifespan + random(-system.lifespanD, system.lifespanD); lifetime = 0; part.setFill(system.startColor); part.resetMatrix(); part.translate(x, y); //set particle size partSize = random(system.minStartSize, system.maxStartSize); for(int i = 0; i < part.getVertexCount(); i++) { PVector v = part.getVertex(i); v.normalize().mult(partSize/2); part.setVertex(i, v.x, v.y); } } boolean isDead() { if (lifetime > lifespan) { return true; } else { return false; } } public void update() { lifetime += 0.03f; if(isDead()) { part.setFill(color(0, 0)); return; } if(system.useGravity) velocity.add(system.gravity.copy().mult(0.03f)); velocity.mult(1 - system.drag * 0.03f); float lifePercent = lifetime / lifespan; part.setFill(lerpColor(system.startColor, system.endColor, lifePercent)); part.translate(velocity.x, velocity.y); for(int i = 0; i < part.getVertexCount(); i++) { float scale = lerp(partSize, system.endSize, lifePercent); PVector v = part.getVertex(i); v.normalize().mult(scale/2); part.setVertex(i, v.x, v.y); } } }
It crashes when I call Update with the error: java.lang.ArrayIndexOutOfBoundsException: length=2; index=6 at processing.core.PShape.setFill(PShape.java:2393)
The ParticleSystem class:
class ParticleSystem extends GameObject { public boolean loop = false; public float loopTime = 5f; public float spawnRate = 10f; public ArrayList<Burst> bursts = new ArrayList<Burst>(); //Spawning public float lifespan = 1f; public float lifespanD = 0f; //Shape public float angle = 360f; //Physics public float startSpeed = 10f; public float startSpeedD = 2f; public float drag = 0f; public boolean useGravity = false; public PVector gravity = new PVector(0, 9.81f); //Visuals public color startColor = color(255); public color endColor = color(255, 0); public int minStartSize = 10; public int maxStartSize = 10; public int endSize = 0; private ArrayList<Particle> particles; private PShape particleShape; private boolean isPlaying = false; ParticleSystem(PVector position, float rotation, int n) { this.position = position; this.rotation = rotation; particles = new ArrayList<Particle>(); particleShape = createShape(PShape.GROUP); for (int i = 0; i < n; i++) { Particle p = new Particle(this); particles.add(p); particleShape.addChild(p.getShape()); } } private float currentLoopTime = 0; private float toSpawn = 0; public void Update() { if (!isPlaying) return; currentLoopTime += Time.deltaTime; if(currentLoopTime >= loopTime) { if(loop) { currentLoopTime = 0; for (Burst b : bursts) { b.done = false; } } else if(currentLoopTime >= loopTime + lifespan + lifespanD) FinishedPlaying(); } if(currentLoopTime < loopTime) { toSpawn += spawnRate * Time.deltaTime; for (Burst b : bursts) { if(!b.done && b.time <= currentLoopTime) { toSpawn += b.amount; b.done = true; } } } for (Particle p : particles) { if (toSpawn >= 1 && p.isDead()) { p.rebirth(position.x, position.y); toSpawn -= 1; } if(!p.isDead()) p.update(); } } public void Play() { if(isPlaying) return; isPlaying = true; } public void Stop() { if(!isPlaying) return; isPlaying = false; } private void FinishedPlaying() { Stop(); hierarchy.remove(this); } public void Draw() { if(!isPlaying) return; shape(particleShape); } } public class Burst { public int amount; public float time; public boolean done = false; public Burst(int amount, float time) { this.amount = amount; this.time = time; } }
Here is a code snippet of the one that crashes, it's the exact same as the one that does not, except for that it also does some other things like setup the physics.
ParticleSystem ps; void setup() { size(displayWidth, displayHeight, P2D); accel = new AccelerometerManager(this); Utils.screenWidth = width; Utils.screenHeight = height; physics = new PhysicsManager(); init = new Initialization(); upgradeFactory = new UpgradeFactory(); ps = new ParticleSystem(new PVector(width/2, height/2), 0, 200); ps.Play(); } void draw() { Time.Frame(millis()); physics.Loop(); clear(); background (0); for(int i = hierarchy.size() - 1; i >= 0; i--) { hierarchy.get(i).Update(); } for(int i = hierarchy.size() - 1; i >= 0; i--) { hierarchy.get(i).InternalUpdate(); } for(int i = hierarchy.size() - 1; i >= 0; i--) { hierarchy.get(i).Draw(); } ps.Draw(); ps.Update(); }
Hi @Sebastiran can you please provide the exact logs of the errors you are getting ?
That would be helpful to check exactly where the error is happening in the codebase.
Thanks ! happy coding