Problem With Collision

Hello!
I’m a Design student at University of São Paulo and I’ve had some Processing classes and now I have to do a final project. I’m doing a simple game similar to Facebook’s Everwing based on Steven Universe.
It’s basically you controlling Steven with the mouse, shooting and killing enemies that come from above. But I can’t seem to possibly make the collision happen in any way.
By now, the character are all appearing and the shots as well but they don’t have any interaction!
Is there anyone that can help me? I need to deliver this by Sunday and I’m freaking out!

int x = 275;
int y = 500;
int inimigosTamanho = 50;
int inimigosX = 100;
int inimigosY = 100;
int tirox = 5;
int tiroy = 5;
int movX = 0;
int barraLateral = 250;
int tirotamanho = 20;
int[]  posicaoX =  {100, 180, 260, 340};

PImage[] imagens;

boolean acerto = false;
PVector [] tiros;

void setup () {
  size (800, 600);
  imagens = new PImage [5];
  imagens [0] = loadImage ("Steven.png");
  imagens [1] = loadImage ("tiro.png");
  imagens [2] = loadImage ("Rubi.png");
  fill (120, 0, 40);
  frameRate(60);
}

void draw () {
  background (0, 120, 240);
  noStroke(); 
  movX = movX +5;
  int z = mouseX;
  int w = mouseY;
  int s = mouseX+25;
  int r = mouseY - tiroy;
  rect (550, 0, barraLateral, 600);
  inimigos (5);
  colisao ();
  fill (255, 0, 0, 0);
  rect (z, w, 50, 50);
  fill (127);
  image (imagens[0], z, w, 50, 50);
  if (key == CODED) {
    if (keyCode == CONTROL) {
      fill (255, 0, 0, 0);
      rect (s, r, tirotamanho, tirotamanho);
      fill (127);
      image (imagens[1], s, r, tirotamanho, tirotamanho);
      tiroy = tiroy + 60; 
      if (r < 0) {
        tiroy = 0;
      }
    }
  }
  if (movX > height) {
    movX = 0;
    inimigosY = 0;
  }
}
void inimigos (int quant) {   
  int xDef = width -  barraLateral; 
  for (int i = 0; i < quant; i++) {  
    image (imagens[2], (xDef/(quant ) * i)  + (xDef/(quant)-inimigosTamanho)/2, inimigosY + movX, inimigosTamanho, inimigosTamanho);
  }                                                                                                                
}
void colisao () {
  if (s && r == 

Have a look at the Fisica Library.
It includes box2d which was used for Angry Birds btw. :slight_smile:

1 Like

Hi Feelpss!

Your code chops off at the end. Can you isolate where your problem is and post a working example of where your issue is?

Hey!
It’s not chopped! I’ve put the whole code so everyone could understand what the problem was.
I tried to create a collision function (colisao) but I can’t go on further than that.
I can’t post a working example because it doesn’t work…

It looks chopped off. But then I realized that what you have is you writing code right up until the point where you got stuck. Especially since the last statement feels like it reads “If r and s are equal to … UHHHHH I don’t know what they should equal!”

Of course, r and s are integers, so logically AND-ing them together (&&) doesn’t make much sense.

Anyway.

The first step is fixing your code so that we can run it. There are two problems with this. The first is that your code looks chopped off. We can fix that by commenting out the line that doesn’t make sense and then ending the collision function.

The second step is dealing with the fact that we don’t have your three images. To cope with this, I’m going to replace them with colored squares.

Making those changes gives us this code, which anyone can copy, paste, and run:

int x = 275;
int y = 500;
int inimigosTamanho = 50;
int inimigosX = 100;
int inimigosY = 100;
int tirox = 5;
int tiroy = 5;
int movX = 0;
int barraLateral = 250;
int tirotamanho = 20;
int[]  posicaoX =  {100, 180, 260, 340};

PImage[] imagens;

boolean acerto = false;
PVector [] tiros;

void setup () {
  size (800, 600);
  imagens = new PImage [5];
  background(255,0,0);
  imagens [0] = get(0,0,20,20);//loadImage ("Steven.png");
  background(255,255,0);
  imagens [1] = get(0,0,20,20);//loadImage ("tiro.png");
  background(0,255,0);
  imagens [2] = get(0,0,20,20);//loadImage ("Rubi.png");
  fill (120, 0, 40);
  //frameRate(60);
}

void draw () {
  background (0, 120, 240);
  noStroke(); 
  movX = movX +5;
  int z = mouseX;
  int w = mouseY;
  int s = mouseX+25;
  int r = mouseY - tiroy;
  rect (550, 0, barraLateral, 600);
  inimigos (5);
  colisao ();
  fill (255, 0, 0, 0);
  rect (z, w, 50, 50);
  fill (127);
  image (imagens[0], z, w, 50, 50);
  if (key == CODED) {
    if (keyCode == CONTROL) {
      fill (255, 0, 0, 0);
      rect (s, r, tirotamanho, tirotamanho);
      fill (127);
      image (imagens[1], s, r, tirotamanho, tirotamanho);
      tiroy = tiroy + 60; 
      if (r < 0) {
        tiroy = 0;
      }
    }
  }
  if (movX > height) {
    movX = 0;
    inimigosY = 0;
  }
}
void inimigos (int quant) {   
  int xDef = width -  barraLateral; 
  for (int i = 0; i < quant; i++) {  
    image (imagens[2], (xDef/(quant ) * i)  + (xDef/(quant)-inimigosTamanho)/2, inimigosY + movX, inimigosTamanho, inimigosTamanho);
  }                                                                                                                
}
void colisao () {
  //if (s && r ==
}
1 Like

Now we can start addressing your problem.

You want to check if things are colliding. Collisions are determined by the POSITIONS and SIZES of the two things that you’re trying to determine if they are colliding. If they things can be modeled as rectangles (which is likely because they are images, and thus are rectangles), then each of the things has a position (x,y) and a size (w,h).

so, with two things, there are EIGHT numbers to consider. The position and size of the first thing, (x1,y1,w1,h1) and the position and size of the second thing (x2,y2,w2,h2).

There are better guides out there for this already. Here’s one:

Anyway, what I think is really going to help you is if we tidy your code up and think about using classes and objects.

1 Like

There are basically three types of objects in your game.

The first is the player, which follows the mouse.
The second is the enemies, which fall down the screen.
The third is the bullets that the player shoots.

Thus, you will need three classes. We’ll also include the basics for your setup() and draw() functions. So this is that:

class Player{
  Player(){
  }
}

class Foe{
  Foe(){
  }
}

class Bullet{
  Bullet(){
  }
}

void setup(){
  size(800,600);
}

void draw(){
  background(0, 120, 240);
  noStroke();
  fill(127);
  rect(550,0,250,height);
}

Notice that running this seems like a step backwards: None of the things are being drawn any more. But what we have done is add a little structure to your code, and that’s going to help immensely in a short while.

1 Like

Now we can start adding some details about these objects. Each needs to know which image to use, where it is, how to move, how to get drawn, and then we need a single player, an array of foes, and an ArrayList of bullets.

class Player{
  int which_image;
  float position_x;
  float position_y;
  Player(float start_position_x, float start_position_y){
    which_image = 0;
    position_x = start_position_x;
    position_y = start_position_y;
  }
  void draw(){
    move();
    image( images[which_image], position_x, position_y );
  }
  void move(){
    position_x = mouseX;
    position_y = mouseY;
  }
}

class Foe{
  int which_image;
  float position_x;
  float position_y;
  Foe(float start_position_x, float start_position_y){
    which_image = 2;
    position_x = start_position_x;
    position_y = start_position_y;
  }
  void draw(){
    move();
    image( images[which_image], position_x, position_y );
  }
  void move(){
    position_x += 0;
    position_y += 3;
    if( position_y > height ){
      position_y = -images[which_image].height;
    }
  }
}

class Bullet{
  int which_image;
  float position_x;
  float position_y;
  Bullet(float start_position_x, float start_position_y){
    which_image = 1;
    position_x = start_position_x;
    position_y = start_position_y;
  }
  boolean draw(){
    move();
    image( images[which_image], position_x, position_y );
    return( position_y < -images[which_image].height);
  }
  void move(){
    position_x += 0;
    position_y -= 3;
  }
}

PImage[] images;

Player player;
Foe[] foes;
ArrayList<Bullet> bullets;

void setup(){
  size(800,600);
  // Load the images. Or spoof them.
  images = new PImage[5];
  background(255,0,0);
  images [0] = get(0,0,20,20);//loadImage ("Steven.png");
  background(255,255,0);
  images [1] = get(0,0,20,20);//loadImage ("tiro.png");
  background(0,255,0);
  images [2] = get(0,0,20,20);//loadImage ("Rubi.png");
  // Create the Player.
  player = new Player(width/2,height/2);
  // Create the Foes.
  foes = new Foe[5];
  for( int i = 0; i < foes.length; i++){
    foes[i] = new Foe( 50 + 100 * i, 0 );
  }
  // Create the bullets.
  bullets = new ArrayList();
}

void draw(){
  background(0, 120, 240);
  noStroke();
  fill(127);
  rect(550,0,250,height);
  // Draw the player.
  player.draw();
  // Draw the Foes.
  for( int i = 0; i < foes.length; foes[i++].draw());
  // Draw the Bullets.
  for( int i = bullets.size()-1; i >=0; i--) if(bullets.get(i).draw()) bullets.remove(i);
}

void mousePressed(){
  bullets.add( new Bullet(mouseX, mouseY) );
}

Anyway. Collisions. Since the thing that we really care about colliding with is enemies, let’s loop over every enemy. if we collide that enemy with the player, the player dies.

Then let’s loop over all the bullets. If that enemy collides with that bullet, both that enemy and that bullet die.

… What does it mean for an object to die? Well, we can add an alive boolean to each of our objects. And then only draw them if they are alive. And of course only alive things can cause collisions.

class Player {
  int which_image;
  float position_x;
  float position_y;
  float size_w;
  float size_h;
  boolean alive;
  Player(float start_position_x, float start_position_y) {
    which_image = 0;
    position_x = start_position_x;
    position_y = start_position_y;
    size_w = images[which_image].width;
    size_h = images[which_image].height;
    alive = true;
  }
  void draw() {
    if (alive) {
      move();
      image( images[which_image], position_x, position_y );
    }
  }
  void move() {
    position_x = mouseX;
    position_y = mouseY;
  }
  void die() {
    alive = false;
  }
}

class Foe {
  int which_image;
  float position_x;
  float position_y;
  float size_w;
  float size_h;
  boolean alive;
  Foe(float start_position_x, float start_position_y) {
    which_image = 2;
    position_x = start_position_x;
    position_y = start_position_y;
    size_w = images[which_image].width;
    size_h = images[which_image].height;
    alive = true;
  }
  void draw() {
    if (alive) {
      move();
      image( images[which_image], position_x, position_y );
    }
  }
  void move() {
    position_x += 0;
    position_y += 3;
    if ( position_y > height ) {
      position_y = -size_h;
    }
  }
  void die() {
    alive = false;
  }
  boolean collides(float ox, float oy, float ow, float oh) {
    return((ox + ow >= position_x && ox <= position_x + size_w && oy + oh >= position_y && oy <= position_y + size_h));
  }
}

class Bullet {
  int which_image;
  float position_x;
  float position_y;
  float size_w;
  float size_h;
  boolean alive;
  Bullet(float start_position_x, float start_position_y) {
    which_image = 1;
    position_x = start_position_x;
    position_y = start_position_y;
    size_w = images[which_image].width;
    size_h = images[which_image].height;
    alive = true;
  }
  boolean draw() {
    if (alive) {
      move();
      image(images[which_image], position_x, position_y );
    }
    return(!alive || position_y < -size_h);
  }
  void move() {
    position_x += 0;
    position_y -= 3;
  }
  void die() {
    alive = false;
  }
}

PImage[] images;

Player player;
Foe[] foes;
ArrayList<Bullet> bullets;

void setup() {
  size(800, 600);
  // Load the images. Or spoof them.
  images = new PImage[5];
  background(255, 0, 0);
  images[0] = get(0, 0, 20, 20);//loadImage ("Steven.png");
  background(255, 255, 0);
  images[1] = get(0, 0, 20, 20);//loadImage ("tiro.png");
  background(0, 255, 0);
  images[2] = get(0, 0, 20, 20);//loadImage ("Rubi.png");
  // Create the Player.
  player = new Player(width/2, height/2);
  // Create the Foes.
  foes = new Foe[5];
  for ( int i = 0; i < foes.length; i++) {
    foes[i] = new Foe( 50 + 100 * i, 0 );
  }
  // Create the bullets.
  bullets = new ArrayList();
}

void draw() {
  background(0, 120, 240);
  noStroke();
  fill(127);
  rect(550, 0, 250, height);
  // Draw the player.
  player.draw();
  // Draw the Foes.
  for (int i = 0; i < foes.length; foes[i++].draw());
  // Draw the Bullets.
  for (int i = bullets.size()-1; i >=0; i--) if (bullets.get(i).draw()) bullets.remove(i);

  // Collisions!
  for (int i = 0; i < foes.length; i++) {
    // Is this foe alive and does this foe collide with the player?
    if (foes[i].alive && foes[i].collides(player.position_x, player.position_y, player.size_w, player.size_h)) {
      // Kill the player. This is the sort of comment you can leave out. I mean, player.die() is pretty clear, right?
      player.die();
    }
    for (int j = bullets.size()-1; j >= 0; j--) {
      // Are an alive foe and an alive bullet colliding?
      if( foes[i].alive && bullets.get(j).alive && foes[i].collides(bullets.get(j).position_x, bullets.get(j).position_y, bullets.get(j).size_w, bullets.get(j).size_h)) {
        // Kill this bullet and that foe.
        bullets.get(j).die();
        foes[i].die();
      }
    }
  }
}

void mousePressed() {
  // Add a new bullet if the player is alive.
  if(player.alive){
    bullets.add( new Bullet(mouseX, mouseY) );
  }
}

And that works. It works great. But it’s still a mess.

The problem with it is that each of these objects are - basically - the same thing. They’re a rectangle that’s on the screen somewhere. So we can actually compact our three classes into one.

This is something I actually don’t recommend you do if you are planning on having these objects’ behaviors diverge. So, seriously, you might just want to stick with the code from the previous post.

class Obj {
  int t; // type
  float x, y, w, h;
  boolean a; // alive
  Obj(float ix, float iy, int it) {
    t = it;
    x = ix;
    y = iy;
    w = images[t].width;
    h = images[t].height;
    a = true;
  }
  boolean draw() {
    if (a) {
      move();
      image( images[t], x, y );
    }
    return(!a || (t==2&&y<-h));
  }  
  void move() {
    switch(t) {
    case 0: // Player
      x=mouseX;
      y=mouseY;
      break; 
    case 2: // Foe
      y+=3;
      if ( y > height ) {
        y = -h;
      }
      break;
    case 1: // Bullet
      y-=3;
      break;
    }
  }
  void die() {
    a = false;
  }
  boolean collides(float ox, float oy, float ow, float oh) {
    return((ox + ow >= x && ox <= x + w && oy + oh >= y && oy <= y + h));
  }
}


PImage[] images;

Obj player;
Obj[] foes;
ArrayList<Obj> bullets;

void setup() {
  size(800, 600);
  // Load the images. Or spoof them.
  images = new PImage[5];
  background(255, 0, 0);
  images[0] = get(0, 0, 20, 20);//loadImage ("Steven.png");
  background(255, 255, 0);
  images[1] = get(0, 0, 20, 20);//loadImage ("tiro.png");
  background(0, 255, 0);
  images[2] = get(0, 0, 20, 20);//loadImage ("Rubi.png");
  // Create the Player.
  player = new Obj(width/2, height/2, 0);
  // Create the Foes.
  foes = new Obj[5];
  for ( int i = 0; i < foes.length; i++) {
    foes[i] = new Obj( 50 + 100 * i, 0, 2 );
  }
  // Create the bullets.
  bullets = new ArrayList();
}

void draw() {
  background(0, 120, 240);
  noStroke();
  fill(127);
  rect(550, 0, 250, height);
  player.draw();
  for (int i = 0; i < foes.length; foes[i++].draw());
  for (int i = bullets.size()-1; i >=0; i--) if (bullets.get(i).draw()) bullets.remove(i);
  for (int i = 0; i < foes.length; i++) {
    if (foes[i].a && foes[i].collides(player.x, player.y, player.w, player.h)) player.die();
    for (int j = bullets.size()-1; j >= 0; j--) {
      if ( foes[i].a && bullets.get(j).a && foes[i].collides(bullets.get(j).x, bullets.get(j).y, bullets.get(j).w, bullets.get(j).h)) {
        bullets.get(j).die();
        foes[i].die();
      }
    }
  }
}

void mousePressed() {
  if (player.a) {
    bullets.add( new Obj(mouseX, mouseY, 1) );
  }
}

Well, it’s a little shorter…