0

How do you get a certain object to hit another object?

I am making a game where trash is falling from the sky, you are meant to drag and drop the trash into the correct bins. How do I make it so when you drag it into the regional area of the bin is, it gives you a score and resets again. I have made the score & lives function but how do you get it to hit the bin and give you a score?

Here's the progress I have made so far:

PImage scene, can, brownB, blueB, greenB;

int can_x = -100; //CAN IS HIDDEN FOR NOW
int can_y = 500;

int canX = 100;
int canY = 50;
int canwidth = width/2;
int canheight = height/2;

int score = 0;
int lives = 3;
int can_count = 0;

int quit = 0;

boolean mouseInCan = false;

void setup() // Entry point (start of program), runs once
{
 size(800,600,P2D); // Create a Window, must be same size as scene
 scene = loadImage("backround.png"); // load image and data into scene data structure
 can = loadImage("can.png"); // load image of can into the GPU
 greenB = loadImage("green_bin.png");

 textureMode(NORMAL); // Scale texture Top right (0,0) to (1,1)
 blendMode(BLEND); // States how to mix a new image with the one behind it
 noStroke(); // Do not draw a line around objects

 canX = 0 + (int)random(800); // Choose drop starting position
 canY = 0;  
 
}

//check if the mouse is in the can
void mousePressed() {
  if (mouseX > canX && mouseX < canX + canwidth && mouseY > canY && mouseY < canY + canheight) {
    mouseInCan = true;
  }
}

//if the mouse is in the can, then move it when the mouse is dragged
void mouseDragged() {
  if (mouseInCan) {
    float deltaX = mouseX - pmouseX;
    float deltaY = mouseY - pmouseY;

    canX += deltaX;
    canY += deltaY;
  }
}

//when we let go of the mouse, stop dragging the can
void mouseReleased() {
  mouseInCan = false;
}

void draw()
{
  
 background(scene); // Display background image referenced by scene
 image(can, canX, canY, canwidth, canheight); //Can is drawn at position
 image(greenB, 100, 450, width/8, height/4);
 
 pushMatrix(); // Store current location of origin (0,0)
 translate(can_x,can_y); // Change origin (0,0) for drawing to (drop_x,drop_y)
 beginShape(); // Open graphics pipeline
 texture(can); // Tell GPU to use drop to texture the polygon
 vertex( -20, -20, 0, 0); // Load vertex data (x,y) and (U,V) texture data into GPU
 vertex(20, -20, 1, 0); // Square centred on (0,0) of width 40 and height 40
 vertex(20, 20, 1, 1); // Textured with an image of a drop
 vertex( -20, 20, 0, 1);
 endShape(CLOSE); // Tell GPU you have loaded shape into memory.
 popMatrix(); 
 
 canY += 1.5; // Make "drop" move down the screen (two pixels at a time)
 if (canY>600) // If y value is entering the bottom of screen
 {
 canX = 0+(int)random(800); // Restart the drop again in the cloud.
 canY = 0;
 lives--;

 } 
 
 
 if ((canY>100)&&(canY<450)) // If drop is on same level as player
 {
 if(abs((canX+100)-(canX+450))<25) // And drop is near player
 {
 score++; // Increase drop count by one (caught)

 canX=0+(int)random(800); // Restart a new drop in the cloud
 canY=0;
 
 }
 }
 
 
 textSize(18); // Display score information on the screen
 fill(0,0,0);
 text("Lives: "+lives, 540, 20);
 
 textSize(18);
 fill(0,0,0);
 text("Score: "+score, 640, 20);
 
 if(quit==1) // Wait five seconds before exiting
 {
 delay(5000);
 exit();
 }
 
 if (lives<1) // All lives lost so game over but
 { // return to draw one more time to
 quit = 1; // allow "Game Over to be displayed.
 } 
} 

I have tried doing it where the comment with 'If drop is on same level as player' but no luck, The code is a mess right now but I will clean it up, still new to processing.

julien.giband
  • 2,467
  • 1
  • 12
  • 19
Eiken
  • 3
  • 2

2 Answers2

1

What you are looking for is some kind of collision detection. There are very complex algorithms out there that can do an accurate detection with complex shapes, at the cost of CPU time, but in your case, just checking the intersection of two rectangles will probably be enough, at least for a start.

First you need to have your bin and can's positions and dimensions stored somewhere. We'll use the enclosing rectangle of each as a collision box.

PImage scene, can, brownB, blueB, greenB;

int canX = 100, canY = 50, canwidth = 80, canheight = 80;
int binX = 100, binY = 450, binW = 100, binH = 150;

You can then adjust the dimensions according to your screen size, but it has to be done after you have initialized it in setup:

void setup() // Entry point (start of program), runs once
{
  size(800, 600, P2D); // Create a Window, must be same size as scene
  scene = loadImage("backround.png"); // load image and data into scene data structure
  can = loadImage("can.png"); // load image of can into the GPU
  greenB = loadImage("green_bin.png");
  //...

  canwidth = width / 10;
  canheight = width / 10;
  
  binW = width / 8;
  binH = height / 4;
  binY = height - binH; //Set the bin at the bottom of the screen
}

Now your elements can be drawn according to the stored values, how and where you intend them, and you can do your collision detection inside your draw loop:

void draw()
{
  background(scene); // Display background image referenced by scene
  image(can, canX, canY, canwidth, canheight); //Can is drawn at position
  image(greenB, binX, binY, binW, binH);
  //...
  
  /* If the top of the can is below the top of the bin and the can is 
   * horizontally within the bin, then we count score
   */
  if (canY > binY && canX > binX && canX + canwidth < binX + binW) {
    score++; // Increase drop count by one (caught)

    canX=0+(int)random(800); // Restart a new drop in the cloud
    canY=0;
  }
  //...
}

I've neglected the check for bottom coordinates of the can relative to the bin, as the bin is at the very bottom, and hitting the bottom kills you.

julien.giband
  • 2,467
  • 1
  • 12
  • 19
0

As was said already, you need some kind of collision detection. I would abstain though from trying to implement any algorithms myself and would instead use a professional library for that like: https://github.com/locationtech/jts That way you can also test against the real geometry and the overhead is minimal because these tests are first run againt the bounding boxes and only when that is positive they are refined to the real geometry. In addition you could also use a spatial index to speed up the search.

mipa
  • 10,369
  • 2
  • 16
  • 35