updatePixels() for multiple objects.

edited January 2015 in Questions about Code

Hello all.

I have a bouncing ball displaying over an image of the hit 90's R&B group, Boyz II Men (eh, I needed an image of anything).

To my ball class, there are several functions assigned. The ball collection array allows for many objects to be loaded as desired. Here, I chose 4 balls... one for each Boyz II Men singers (sure, why not?)

However, when I add in the brightness function to the update display, I only see one object, even though there is more than one object printing coordinates in the console.

//int n = 1000;
PImage img;


//DECALRE
Ball [] ballCollection = new Ball [4];



void setup ()  {
  size(600,600);
  frameRate(30);
  img = loadImage("/assets/Boyz2Men.jpg");
  img.loadPixels();
  loadPixels();
  smooth();

  //INITIALIZE
  for (int i = 0; i < ballCollection.length; i++)  {
  ballCollection[i] =new Ball(random(0,width), random(0,200));
  }


}

void draw()  {
  background(0);
  image(img, 0, 0);
  //CALL FUNCTIONALITY
  for (int i = 0; i < ballCollection.length; i ++)  {
  ballCollection[i].run();
  print(i, "\n");
  //updatePixels();
  }


}



class Ball {
  //GLOBAL VARIABLES
  float x = 0;
  float y = 0;
  float speedX = 4;
  float speedY = 0.5;

  //CONSTRUCTOR - INITIALIZE VARIABLES
  Ball(float _x, float _y) {
    x = _x;
    y = _y;
  }

  //FUNCTIONS - 
  void run() {
    display();
    move();
    bounce();
    gravity();
  }

  void move() {
    x += speedX; 
    y += speedY;
  }

  void bounce() {
    if (x > width) {
      speedX = speedX * -1;
    }
    if (x < 0) {
      speedX = speedX * -1;
    }
    if (y > height) {
      speedY = speedY * -1;
    }
    if (y < 0) {
      speedY = speedY * -1;
    }
  }

  void gravity() {
    speedY += 0.2;
  }


  void display() {
    print("X is ", x, " ", "Y is ", y, "\n");
    for (int x2 = 0; x2 < img.width; x2++) {
      for (int y2 = 0; y2 < img.height; y2++ ) {
        // Calculate the 1D location from a 2D grid
        int loc = x2 + y2*img.width;
        // Get the R,G,B values from image
        float r, g, b;
        r = red (img.pixels[loc]);
        //g = green (img.pixels[loc]);
        //b = blue (img.pixels[loc]);
        // Calculate an amount to change brightness based on proximity to the mouse
        float maxdist = 50;//dist(0,0,width,height);
        float d = dist(x, y, x2, y2);
        //print(d, "\n");
        float adjustbrightness = 255*(maxdist-d)/maxdist;
        r += adjustbrightness;
        //g += adjustbrightness;
        //b += adjustbrightness;
        // Constrain RGB to make sure they are within 0-255 color range
        r = constrain(r, 0, 255);
        //g = constrain(g, 0, 255);
        //b = constrain(b, 0, 255);
        // Make a new color and set pixel in the window
        //color c = color(r, g, b);
        color c = color(r);
        pixels[y2*width + x2] = c;

      }
    }
    updatePixels();
    ellipse(x, y, 20, 20);
  }
}

What is the reason as to why only one ball shows up? If I comment out the last for loop, I can see the picture clearly. Do I need to make another function called void bright()?

Thanks for any suggestions, I am stumped.

-Aaron

Answers

  • It could be because you are only doing it for x2 and y2. Line 89 and 90. When you mean you comment out the updatePixels() ? According to what I read here: https://www.processing.org/reference/updatePixels_.html, you only use it if you actual image is changing. So I don't think using updatePixels() is even necessary, but when you remove it, you can see it. Now I don't know what you mean by bright, as in making the image brighter? I would do the baby step, and that would be put a white rectangle over the whole thing. Make it transparent. You choose, less transparent, brighter. More transparent, closer to the original. Hope that helps!

  • edited January 2015

    ah, void bright would be a function contained within the class, as in...

      void bright() {
        print("X is ", x, " ", "Y is ", y, "\n");
        for (int x2 = 0; x2 < img.width; x2++) {
          for (int y2 = 0; y2 < img.height; y2++ ) {
            // Calculate the 1D location from a 2D grid
            int loc = x2 + y2*img.width;
            // Get the R,G,B values from image
            float r, g, b;
            r = red (img.pixels[loc]);
            //g = green (img.pixels[loc]);
            //b = blue (img.pixels[loc]);
            // Calculate an amount to change brightness based on proximity to the mouse
            float maxdist = 50;//dist(0,0,width,height);
            float d = dist(x, y, x2, y2);
            //print(d, "\n");
            float adjustbrightness = 255*(maxdist-d)/maxdist;
            r += adjustbrightness;
            //g += adjustbrightness;
            //b += adjustbrightness;
            // Constrain RGB to make sure they are within 0-255 color range
            r = constrain(r, 0, 255);
            //g = constrain(g, 0, 255);
            //b = constrain(b, 0, 255);
            // Make a new color and set pixel in the window
            //color c = color(r, g, b);
            color c = color(r);
            pixels[y2*width + x2] = c;
    
          }
        }
    

    Then I would just call it under void run().

    x2 and y2 are just variables, it could be anything, really. X and Y are already used.

    I'll futz around with the transparency you mentioned, but man, I'd like to make headway on this. :)

    I get what is wrong, but I dont know how to solve it. It's only updating one pixel modification at a time. There has to be a way...

    thanks!

  • edited January 2015 Answer ✓

    Your problem is that you are overriding each ball's intensity shading on every iteration. The last Ball display() is the only one you really see.

    I think the best solution is to create a PGraphics with all black pixels, then on each display you subtract an alpha value according to the distance, without overriding the previous values. You have to subtract because 255 is opaque and 0 is transparant, so you start from a value of 255 and subtract 255 at the nearest spot. Then you use this PGraphics to mask the image, simply calling image in draw should work.

    Remarks:

    • Don't call createGraphics on each draw(), this will fill in your memory rather quickly. Instead, set all pixels to black again of the existing PGraphics.
    • The colour black (0,0,0) with an alpha value of 0 gets misinterpreted by Processing (?). If you encounter the issue of a black spot in the middle of a circle, use an almost-black colour like (0,0,1) instead.
    • With this method the colour of the original image is preserved (which it isn't in your sketch).
  • edited January 2015 Answer ✓

    In order to get 100% transparent black, use: color(0, 0);.
    For resetting the whole canvas w/ it, go w/: clear(); or background(0, 0);.

  • Yeah, I kind of figured that was the issue, but I didn't know about PGraphics. That helps a lot!

    Sort of like double buffering... or maybe just an additional buffer. Thanks!

  • Oh okay, you figured it out, sorry I messed you up there mate.

  • No probelmo man. Thanks for the help, I do appreciate being able to think about the solution in many different ways. :)

    I got it to write to an external buffer, but I'm actually having an issue figuring out how to do a subtraction from the array and getting all modifications to appear. Ugh, it always seems like the thing I am trying to do never has a close comparison or example. Heh, go figure. :P

  • edited February 2016

    ok... I forgot about this one for a long time. work continues. :)

Sign In or Register to comment.