We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Adding an object to an array
Page Index Toggle Pages: 1
Adding an object to an array (Read 1719 times)
Adding an object to an array
Dec 13th, 2008, 4:46pm
 
I'm trying to modify the bouncyBubbles example so that when you click the mouse, you get a new bubble that interacts with the others. The (slightly modified) code is:

Code:

int numBalls = 12;
float spring = 0.25;
float gravity = 0.2;
float friction = -0.9;
Ball[] balls = new Ball[numBalls];

void setup()
{
size(640, 200);
noStroke();
smooth();
for (int i = 0; i < numBalls; i++) {
balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls);
}
}

void draw()
{
background(0);
for (int i = 0; i < numBalls; i++) {
balls[i].collide();
balls[i].move();
balls[i].display();
}
}

class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
Ball[] others;

Ball(float xin, float yin, float din, int idin, Ball[] oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}

void collide() {
for (int i = id + 1; i < numBalls; i++) {
float dx = others[i].x - x;
float dy = others[i].y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others[i].diameter*0.5 + diameter*0.5; // were both /2
if (distance <= minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - others[i].x) * spring;
float ay = (targetY - others[i].y) * spring;
vx -= ax;
vy -= ay;
others[i].vx += ax;
others[i].vy += ay;
}
}
}

void move() {
vy += gravity;
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx *= friction;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= friction;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= friction;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}

void display() {
fill(255, 204);
ellipse(x, y, diameter, diameter);
}
}


The obvious thing (to me, anyway) would be to add something like this, which is a variant on the "add Boid" bit in the Flocking example:

Code:

void mousePressed() {
balls.add(new Ball(random(width), random(height), random(20, 40), i, balls));
}


But it doesn't work - I get "Cannot invoke add(BouncyBubbles.Ball) on the array type BouncyBubbles.Ball[]. Any ideas? Sorry for the stupid question!
Re: Adding an object to an array
Reply #1 - Dec 13th, 2008, 5:34pm
 
add() is for ArrayList and other Collections. For plain array as you have, use append().
Re: Adding an object to an array
Reply #2 - Dec 13th, 2008, 7:09pm
 
thanks - I must be being an idiot though, because it still doesn't work? I get the same error Sad
Re: Adding an object to an array
Reply #3 - Dec 14th, 2008, 10:23am
 
Have you read the page of append()? Not seeing your code, I can only guess you did balls.append() instead of append(balls, ...)
Re: Adding an object to an array
Reply #4 - Dec 14th, 2008, 2:04pm
 
You're right - sorry, I hadn't realised that was the correct syntax. It now runs with this code in the mousePressed bit:

Code:

void mousePressed() {
append(balls, new Ball(random(width), random(height), random(20, 40), numBalls, balls));
numBalls += 1;
}


but when I click to add a ball, this line in Balls.collide() errors:

Code:

float dx = others[i].x - x;


(and presumably the one after that deals with y would too, if it got that far). I can only guess that at this point, others[] is the size balls[] used to be, which is causing the out of range error. Do I need to append others[] too?

Again, sorry for my lack of understanding on this.
Re: Adding an object to an array
Reply #5 - Dec 14th, 2008, 4:15pm
 
Ah, that's a problem with append() I haven't suspected. While it is a convenient function -- arrays are simpler to use than ArrayList or similar classes -- it has a few drawbacks: it is a bit slow because on each append() call, it creates a new array with one more element, then copy all data from the old array (which will be garbage collected/deleted automatically) to the new one.

But when you create a new Ball, you pass the reference to the array holding all the balls, so that a ball can check itself the collision against the other balls.
Problem: using append(), you create a new array, so all the Balls created so far point to the old, obsolete array.
The algorithm wasn't designed with a variable amount of balls...

Several solutions are possible, I think I would just replace the array with an ArrayList: when you use .add(), you won't alter the reference to this list.
Of course, you must change all balls[i] (and others[i]) by ((Balls) balls.get(i)), etc.
Re: Adding an object to an array
Reply #6 - Dec 14th, 2008, 6:56pm
 
Thanks for the help... I'm still floundering around though, I think because I basically don't understand objects yet. The code is now:

Code:

int numBalls = 12;
float spring = 0.25;
float gravity = 0.2;
float friction = -0.9;
ArrayList balls;
//Ball[] balls = new Ball[numBalls];

void setup()
{
size(640, 200);
noStroke();
smooth();
balls = new ArrayList();
for (int i = 0; i < numBalls; i++) {
// balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls);
balls.add(new Ball(random(width), random(height), random(20, 40), i, balls));
}
}

void draw()
{
background(0);
for (int i = balls.size() - 1; i>= 0; i--) {
Ball ball = (Ball) balls.get(i);
ball.collide();
ball.move();
ball.display();
// balls[i].collide();
// balls[i].move();
// balls[i].display();
}
}

class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
ArrayList others;

Ball(float xin, float yin, float din, int idin, ArrayList oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}

void collide() {
for (int i = id + 1; i < balls.size() ; i++) {
float dx = others.get(i).x - x;
float dy = others.get(i).y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others.get(i).diameter*0.5 + diameter*0.5;
if (distance <= minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - (Ball) others.get(i).x) * spring;
float ay = (targetY - (Ball) others.get(i).y) * spring;
vx -= ax;
vy -= ay;
others.get(i).vx += ax;
others.get(i).vy += ay;
}
}
}

void move() {
vy += gravity;
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx *= friction;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= friction;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= friction;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}

void display() {
fill(255, 204);
ellipse(x, y, diameter, diameter);
}
}

void mousePressed() {
balls.add(new Ball(random(width), random(height), random(20, 40), numBalls, balls));
}

I tried it with (Ball) others.get(i) everywhere instead of just others.get(i) but got "misplaced construct" when it got to
Code:
	  (Ball) others.get(i).vx += ax; 



The error I'm getting now is "x cannot be resolved or is not a field" for this line:

Code:

float dx = others.get(i).x - x;
Re: Adding an object to an array
Reply #7 - Dec 15th, 2008, 1:40pm
 
Smiley
See . operator with ArrayList.get() which explains why I wrote ((Ball) balls.get(i)): the extra parentheses were here for a purpose... Wink
Using a Ball object like you did in draw() is also a good solution.
Re: Adding an object to an array
Reply #8 - Dec 15th, 2008, 1:47pm
 
Ahhhhhhhhhhh... it's a case of misplaced brackets XD
Thanks heaps - it now works! The code (for anyone who's remotely interested??) is

Code:

int numBalls = 12;
float spring = 0.25;
float gravity = 0.2;
float friction = -0.9;
ArrayList balls;
//Ball[] balls = new Ball[numBalls];

void setup()
{
size(640, 450);
noStroke();
smooth();
balls = new ArrayList();
for (int i = 0; i < numBalls; i++) {
// balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls);
balls.add(new Ball(random(width), random(height), random(20, 40), i, balls));
}
}

void draw()
{
background(0);
for (int i = balls.size() - 1; i>= 0; i--) {
Ball ball = (Ball) balls.get(i);
ball.collide();
ball.move();
ball.display();
// balls[i].collide();
// balls[i].move();
// balls[i].display();
}
}

class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
ArrayList others;

Ball(float xin, float yin, float din, int idin, ArrayList oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}

void collide() {
for (int i = id + 1; i < balls.size() ; i++) {
float dx = ((Ball) others.get(i)).x - x;
float dy = ((Ball) others.get(i)).y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = ((Ball) others.get(i)).diameter*0.5 + diameter*0.5;
if (distance <= minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - ((Ball) others.get(i)).x) * spring;
float ay = (targetY - ((Ball) others.get(i)).y) * spring;
vx -= ax;
vy -= ay;
((Ball) others.get(i)).vx += ax;
((Ball) others.get(i)).vy += ay;
}
}
}

void move() {
vy += gravity;
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx *= friction;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= friction;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= friction;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}

void display() {
fill(255, 204);
ellipse(x, y, diameter, diameter);
}
}

void mousePressed() {
balls.add(new Ball(mouseX, mouseY, random(20, 40), numBalls, balls));
}
Page Index Toggle Pages: 1