Need Help constraining bouncing images to boundary of canvas

edited December 4 in Library Questions

Hello Everyone, I am Mel! I have very little experience with processing, but I have an art project that I've created. My goal is to have 4 shapes bouncing around the screen, and when you click one, a sound will play. So far, I have figured out how to create the shapes, make them move around. However, my first problem is that only the flower image I have stays mostly within the screen. All other shapes are far off and barely show up in one rotation. I understand that this is similar to "bouncing ball" exercises, yet I'm still lost on how to keep the four of my shapes with the boundary.

This below is what I have so far. Sorry that you wont be able to play the code, but hopefully I was detailed enough for you to get the picture.Thank you for reading this and any help is much appreciated!!!

import ddf.minim.*;

Minim minim;
AudioPlayer winter;
AudioPlayer summer;
AudioPlayer spring;
AudioPlayer autumn;


PImage flower;
PImage fire;
PImage sun;
PImage snowman;
float xpos, ypos;    // Starting position of shape    

float xspeed = 5;  // Speed of the shape
float yspeed = 10;  // Speed of the shape

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom
import processing.sound.*;



void setup() {
  size(800, 800);
  noStroke();
  frameRate(50);
  flower = loadImage("Flower.png");
  flower.resize(200, 200);
  sun = loadImage("Sun.png");
  sun.resize(200, 200);
  fire = loadImage("campfire.png");
  fire.resize(200, 200);
  snowman = loadImage("snowman.png");
  snowman.resize(200, 200);
  xpos = width/1.8;
  ypos = height/2;


  // will play sound
  minim = new Minim(this);
  winter = minim.loadFile("Winter Mix.wav");
  summer = minim.loadFile("Summer Mix.wav");
  spring = minim.loadFile("Spring Mix.wav");
  autumn = minim.loadFile("Autumn Mix.wav");
}

void draw() {
  background(#CBE9F0);

  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );

  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1
  if (xpos > width || xpos < 5) {
    xdirection *= -1;
  }
  if (ypos > height || ypos < 10) {
    ydirection *= -1;
  }

  // Draw the shape
  image(flower, xpos, ypos);
  image(sun, -xpos, ypos);
  image(fire, xpos, -ypos);
  image(snowman, -xpos, -ypos);
}
void keyPressed() 
{
  if (winter.isPlaying() )
  {
    winter.pause();
  } else if (winter.position() == winter.length() )
  {
    winter.rewind();
    winter.play();
  }
  summer.rewind();
  summer.play();
}
void mousePressed()
{
  spring.rewind();
}
Tagged:

Answers

  • Working code is always better. Not only to see the problem but to move to a solution. Here I modified your code:

    PImage flower;
    PImage fire;
    PImage sun;
    PImage snowman;
    float xpos, ypos;    // Starting position of shape    
    
    float xspeed = 5;  // Speed of the shape
    float yspeed = 10;  // Speed of the shape
    
    int xdirection = 1;  // Left or Right
    int ydirection = 1;  // Top to Bottom
    
    
    void setup() {
      size(800, 800);
      noStroke();
      frameRate(50);
      //flower = loadImage("Flower.png");
      //flower.resize(200, 200);
      //sun = loadImage("Sun.png");
      //sun.resize(200, 200);
      //fire = loadImage("campfire.png");
      //fire.resize(200, 200);
      //snowman = loadImage("snowman.png");
      //snowman.resize(200, 200);
      xpos = width/1.8;
      ypos = height/2;
      flower=getMeImage(color(150, 0, 150));
      fire=getMeImage(color(150, 0, 0));
      sun=getMeImage(color(250, 200, 0));
      snowman=getMeImage(color(250));
      ;
    }   
    
    
    void draw() {
      background(#CBE9F0);
    
      // Update the position of the shape
      xpos = xpos + ( xspeed * xdirection );
      ypos = ypos + ( yspeed * ydirection );
    
      // Test to see if the shape exceeds the boundaries of the screen
      // If it does, reverse its direction by multiplying by -1
      if (xpos > width || xpos < 5) {
        xdirection *= -1;
      }
      if (ypos > height || ypos < 10) {
        ydirection *= -1;
      }
    
      // Draw the shape
      image(flower, xpos, ypos);
      image(sun, -xpos, ypos);
      image(fire, xpos, -ypos);
      image(snowman, -xpos, -ypos);
    }
    
    PImage getMeImage(color c) {
      PImage img=createImage(200, 200, RGB);
      img.loadPixels();
      for (int i=0; i<200*200; i++)
        img.pixels[i]=c;
      img.updatePixels();
      return img;
    }
    

    Now, the problem here is that you manage all four images using a single set of coordinates. Doing it the way you are doing it, it will always give you this behavior. If you want to change it, then you will need to provide different coordinates to each object. Do you still want the objects to leave the screen or do you want to constrict them within the sketch area?

    This tutorial will come handy as the solution will be using classes. Not difficult but reviewing the concepts will help: https://processing.org/tutorials/objects/

    Kf

  • Kf, thank you for making it accessible for others.

    Yes, I would like for the objects to stay within the sketch. So are you saying that I need to make :

     xpos = xpos + ( xspeed * xdirection );
      ypos = ypos + ( yspeed * ydirection );
    

    different for every image?

  • Something like this.

    Kf

    MyImage flower;
    MyImage fire;
    MyImage sun;
    MyImage snowman;
    float xpos, ypos;    // Starting position of shape    
    
    float xspeed = 5;  // Speed of the shape
    float yspeed = 10;  // Speed of the shape
    
    int xdirection = 1;  // Left or Right
    int ydirection = 1;  // Top to Bottom
    
    
    void setup() {
      size(800, 800);
      noStroke();
    
      xpos = width/1.8;
      ypos = height/2;
      flower=new MyImage(color(150, 0, 150));
      fire=new MyImage(color(150, 0, 0));
      sun=new MyImage(color(250, 200, 0));
      snowman=new MyImage(color(250));
    }   
    
    
    void draw() {
      background(#CBE9F0);
    
      flower.update();
      flower.draw();
      fire.update();
      fire.draw();
    }
    
    
    
    class MyImage {
    
      PImage img;
      float x, y;
      int w, h;
      float xspeed, yspeed;
    
      MyImage() {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=yspeed=5;
        img=getMeImage(color(0));
      }
    
      MyImage(color c) {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=random(5,13);    
        yspeed=random(3,7);
        img=getMeImage(c);
      }
    
      PImage getMeImage(color c) {
    
        PImage img=createImage(w, h, RGB);
        img.loadPixels();
        for (int i=0; i<200*200; i++)
          img.pixels[i]=c;
        img.updatePixels();
        return img;
      }
    
      void update() {
        if (x > width-w || x < 0) {
          xspeed *= -1;
        }
        if (y > height-h || y < 0) {
          yspeed *= -1;
        }
        x+=xspeed;
        y+=yspeed;
      }
    
      void draw() {
        image(img, x, y);  //ImageMode corners
      }
    }
    
  • Hey, Kf!

    Thank you again for your help. I have been replicating your format for the classes with my own images, but I am not sure why they aren't working. The Errors listed will say "Return Type for method is Missing" or "NullPointer Exception"

    Also, I need the Pimage part and the void update in my code for the the sketch to run?

    class Flower {
    
      PImage flower;
      float x, y;
      int w, h;
      float xspeed, yspeed;
    
      Flower() {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=yspeed=5;
       flower = loadImage("Flower.png");
      }
    
      Sun(color c) {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=random(6,10);    
        yspeed=random(4,9);
        sun = loadImage("Sun.png");
    }
    
    }
    
  • You shouldn't have a Sun() constructor inside a Flower class.

  • edited December 4

    Hi, TFGuy44 and thanks for the reply.

    Before I added the Sun() constructor, i tried to test it out with only the Flower, and the sketch still didn't run.

    and now Ive tried to make more of the same Flowers() with variations and it has not worked.

  • We're at a total loss when it comes to seeing where you're at now. Post your code again.

  • Hello! I kept trying to edit what kfrager posted as an example, with replacements of the images I needed. I am thankful for the link to the lesson on classes. However, I do not know how to replace the rectangles with my images, now that the objects stay within the perimeter of the canvas. I see that adding :

      flower.update();
      flower.draw();
      fire.update();
      fire.draw();
      sun.update();
      sun.draw();
      snowman.update();
      snowman.draw();
    

    makes for 4 shapes to bounce around. But, is there is a way I should put PImage there instead so that my images bounce?

    Thanks!

    MyImage flower;
    MyImage fire;
    MyImage sun;
    MyImage snowman;
    float xpos, ypos;    // Starting position of shape    
    
    float xspeed = 5;  // Speed of the shape
    float yspeed = 10;  // Speed of the shape
    
    int xdirection = 1;  // Left or Right
    int ydirection = 1;  // Top to Bottom
    
    
    void setup() {
      size(800, 800);
      noStroke();
    
      xpos = width/1.8;
      ypos = height/2;
      flower=new MyImage(color(150, 0, 150));
      fire=new MyImage(color(150, 0, 0));
      sun=new MyImage(color(250, 200, 0));
      snowman=new MyImage(color(250));
    }   
    
    
    void draw() {
      background(#CBE9F0);
    
      flower.update();
      flower.draw();
      fire.update();
      fire.draw();
      sun.update();
      sun.draw();
      snowman.update();
      snowman.draw();
    }
    
    
    
    class MyImage {
    
      PImage img;
      float x, y;
      int w, h;
      float xspeed, yspeed;
    
      MyImage() {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=yspeed=5;
        img=getMeImage(color(0));
      }
    
      MyImage(color c) {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=random(5,13);    
        yspeed=random(3,7);
        img=getMeImage(c);
      }
    
    
      PImage getMeImage(color c) {
    
        PImage img=createImage(w, h, RGB);
        img.loadPixels();
        for (int i=0; i<200*200; i++)
          img.pixels[i]=c;
        img.updatePixels();
        return img;
      }
    
      void update() {
        if (x > width-w || x < 0) {
          xspeed *= -1;
        }
        if (y > height-h || y < 0) {
          yspeed *= -1;
        }
        x+=xspeed;
        y+=yspeed;
      }
    
      void draw() {
        image(img, x, y);  //ImageMode corners
      }
    }
    
  • Please add a new constructor to MyImage class:

      MyImage(String filename) {
        w=h=200;   
        x=random(w, width-w);
        y=random(h, height-h);
        xspeed=yspeed=5;
        img=loadImage(filename);
        img.resize(200,200);
      }
    

    Then you need to do two things. In setup:

      flower = new MyImage("Flower.png");
      sun = new MyImage("Sun.png");
      fire = new MyImage("campfire.png");
    

    Now in draw, you need:

    void draw() {
      background(#CBE9F0);
    
      flower.update();
      sun.update();
      fire.update();
    
      flower.draw();
      sun.draw();
      fire.draw();
    }
    

    Kf

  • Thank you so much! I will try it out!

Sign In or Register to comment.