Bouncing elements

Hi There,

I have modified lines of code where different elements will bounce with each other. For now i want to use the width and the height of the different images with the line of code ""images[i].width" and "images[i].height". In this example, I do not know where to define these variables.

It would be great if you can help me.

PShape[] images = new PShape[5];

final int numBalls = 5;
final float spring = 1;
Ball[] balls = new Ball[numBalls];

void setup()
{
size(640, 800, P3D);
smooth();

for (int i = 0; i < balls.length; i++) {
balls[i] = new Ball();
}
for ( int i = 0; i<5; i++ ) {
images[i] = loadShape( i + ".svg");
}
}

void draw()
{
background(255);

for (int i = 0; i < balls.length; i++) {
for (int j = i; j < balls.length; j++) {
if (balls[i].isCollidingWith(balls[j])) {
balls[i].bounceWith(balls[j]);
}
}
}

for (int i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].display(images[i], images[i].width, images[i].height);
}
}

class Ball
{
float x, y;
float vx, vy;
float diameterW;
float diameterH;
color c;

Ball() {
x = random(width);
y = random(height);
c = int(random(250));
diameterW = 200;
diameterH = 100;
}

void move() {
vy += 0.2;
x += vx;
y += vy;

if (x > width-diameterW/2) {
x = width-diameterW/2;
vx -= 10;
} else if (x - diameterW/2 < 0) {
x = diameterW/2;
vx += 10;
}
if (y + diameterH/2 > height) {
y = height - diameterH/2;
vy -= 10;
} else if (y - diameterH/2 < 0) {
y = diameterH/2;
vy += 10;
}
}

boolean isCollidingWith(Ball ball)
{
return dist(x, y, ball.x, ball.y) < (diameterH + ball.diameterH) / 2;
}

void bounceWith(Ball ball)
{
float dx = ball.x - x;
float dy = ball.y - y;
float minDistW = (ball.diameterW + diameterW) / 2;
float minDistH = (ball.diameterH + diameterH) / 2;
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDistW;
float targetY = y + sin(angle) * minDistH;
float ax = (targetX - ball.x) * spring;
float ay = (targetY - ball.y) * spring;
vx -= ax;
vy -= ay;
ball.vx += ax;
ball.vy += ay;
}

void display(PShape dud, float w, float h) {
shapeMode(CENTER);
rectMode(CENTER);
noStroke();
fill(200, 0, 0);
rect(x, y, diameterW, diameterH);
shape(dud, x, y, w, h);
stroke(255);
strokeWeight(2);
}
}

(de-vandalised)

Answers

  • edited December 2017 Answer ✓

    Personally I would have an Array of PShapes - which you have - and then just pass an INDEX into that array to my objects (and not a copy of the PShap and its properties).

    This index could be passed in via the constructor. Like this:

    PShape[] images = new PShape[5];
    
    final int numBalls = 5;
    final float spring = 1;
    Ball[] balls = new Ball[numBalls];
    
    void setup()
    {
      size(640, 800, P3D);
      smooth();
      for ( int i = 0; i<5; i++ ) {
        images[i] = loadShape( i + ".svg");
      }
      for (int i = 0; i < balls.length; i++) {
        balls[i] = new Ball(i);
      }
    }
    
    void draw()
    {
      background(255);
    
      for (int i = 0; i < balls.length; i++) {
        for (int j = i; j < balls.length; j++) {
          if (balls[i].isCollidingWith(balls[j])) {
            balls[i].bounceWith(balls[j]);
          }
        }
      }
    
      for (int i = 0; i < balls.length; i++) {
        balls[i].move();
        balls[i].display();//images[i], images[i].width, images[i].height);
      }
    }
    
    class Ball
    {
      float x, y;
      float vx, vy;
      float diameterW;
      float diameterH;
      color c;
      int index;
    
      Ball(int ii) {
        x = random(width);
        y = random(height);
        c = int(random(250));
        index = ii;
        diameterW = images[i].width;
        diameterH = images[i].height;
    
      }
    
      void move() {
        vy += 0.2;
        x += vx;
        y += vy;
    
        if (x > width-diameterW/2) {
          x = width-diameterW/2;
          vx -= 10;
        } else if (x - diameterW/2 < 0) {
          x = diameterW/2;
          vx += 10;
        }
        if (y + diameterH/2 > height) {
          y = height - diameterH/2;
          vy -= 10;
        } else if (y - diameterH/2 < 0) {
          y = diameterH/2;
          vy += 10;
        }
      }
    
      boolean isCollidingWith(Ball ball)
      {
        return dist(x, y, ball.x, ball.y) < (diameterH + ball.diameterH) / 2;
      }
    
      void bounceWith(Ball ball)
      {
        float dx = ball.x - x;
        float dy = ball.y - y;
        float minDistW = (ball.diameterW + diameterW) / 2;
        float minDistH = (ball.diameterH + diameterH) / 2;
        float angle = atan2(dy, dx);
        float targetX = x + cos(angle) * minDistW;
        float targetY = y + sin(angle) * minDistH;
        float ax = (targetX - ball.x) * spring;
        float ay = (targetY - ball.y) * spring;
        vx -= ax;
        vy -= ay;
        ball.vx += ax;
        ball.vy += ay;
      }
    
      void display(){
        shapeMode(CENTER);
        rectMode(CENTER);
        noStroke();
        fill(200, 0, 0);
        rect(x, y, diameterW, diameterH);
        shape(images[index], x, y, diameterW, diameterH);
        stroke(255);
        strokeWeight(2);
      }
    }
    

    UNTESTED CODE! I do not have your SVGs, so I can't try running this myself. YMMV.

  • Thank you for your help!

    For now I am trying to make the 'isCollidingWith' part seperate for the width and the height. Can you help me that?

    Thanks

This discussion has been closed.