Search code examples
javacollision-detectioncollision2d-games

Java Mario game collision between enemy and blocks


I'm begginer in java game programming and I have a small actually big problem (for me) with game. I'm trying making collision between enemy and blocks it doesnt work and i dont know why. It should worked but it just slow game on one fps per second and dont do anything.

I have main class called Game with this main Init() function

public void init(){
    WIDTH = getWidth();
    HEIGHT = getHeight();
    tex = new Texture();

    BufferImageLoader loader = new BufferImageLoader();
    level = loader.loadImage("/level.png"); // loading level
    cloud = loader.loadImage("/cloud.png"); // loading clouds

    handler = new Handler();
    cam = new Camera(0,0);
    LoadImageLevel(level);

    this.addKeyListener(new KeyInput(handler));
}

and than LoadImageLevel function where I read level.png pixel by pixel and by the differents color I'm setting position of every objects.

private void LoadImageLevel (BufferedImage image){
    int w = image.getWidth();
    int h = image.getHeight();
    //System.out.println(w + " , " + h);

    for(int xx = 0; xx < h; xx++){
        for(int yy = 0; yy < w ; yy++){
            int pixel = image.getRGB(xx, yy);
            int red = (pixel >> 16) & 0xff;
            int green = (pixel >> 8) & 0xff;
            int blue = (pixel) & 0xff;

            if(red == 255 && green == 255 && blue == 255) 
                handler.addObject(new Block(xx*32,yy*32,1,ObjectId.Block));
            if(red == 0 && green == 0 && blue == 255) 
                handler.addObject(new Player(xx*32,yy*32,1,handler,ObjectId.Player));
            if(red == 0 && green == 255 && blue == 0) 
                handler.addObject(new Enemy(xx*32,yy*32,handler,ObjectId.Enemy));
        }
    }

}

In class Player is two important functions tick and collision where in tick is collison called.

public class Player extends GameObject{

private float width = 32, // 48
        height = 64; // 96

private float gravity = 0.5f;
private final float MAX_SPEED = 10; 
private int facing = 1;
private int last = 0; // last position left or right
private Handler handler;

Texture tex = Game.getInstance();
private int type;

private Animation playerWalk, playerWalkLeft,jump;

public Player(float x, float y,int type , Handler handler ,ObjectId id) {
    super(x, y, id);
    this.handler = handler;
    this.type = type;

    playerWalk = new Animation(2,tex.player[2],tex.player[3],
            tex.player[4],tex.player[5]);
    playerWalkLeft = new Animation(2,tex.player[7],tex.player[8],
            tex.player[9],tex.player[10]);
    jump = new Animation(2,tex.player[11],tex.player[12]);
}

public void tick(LinkedList<GameObject> object) {
    x += velX;
    y += velY;

    if(velX < 0) facing = -1;
    else if(velX > 0) facing = 1;

    if(falling || jumping){
        velY += gravity;

        if(velY > MAX_SPEED){
            velY = MAX_SPEED;
        }
    }
    Collision(object);
    //System.out.println(velX + " " + velY);

    playerWalk.runAnimation();
    playerWalkLeft.runAnimation();
    jump.runAnimation();
}

private void Collision(LinkedList<GameObject> object){
    for(int i = 0; i < handler.object.size();i++){
        GameObject tempObject = handler.object.get(i);
        if(tempObject.getId() == ObjectId.Block ){

            if(getBoundsTop().intersects(tempObject.getBounds())){
                y = tempObject.getY() + 32;
                velY = 0;
            }


            if(getBounds().intersects(tempObject.getBounds())){
                y = tempObject.getY() - height;
                velY = 0;
                falling = false;
                jumping = false;
            }else 
                falling = true;

            if(getBoundsRight().intersects(tempObject.getBounds())){
                x = tempObject.getX() - width;
            }


            if(getBoundsLeft().intersects(tempObject.getBounds())){
                x = tempObject.getX() + 35;
            }
        }

        /* new */

    }

}


public void render(Graphics g) {

    /*
    g.setColor(Color.blue);
    g.fillRect((int)x,(int)y,(int)width,(int)height);

    Graphics2D g2d = (Graphics2D) g;
    g.setColor(Color.red);
    g2d.draw(getBounds());
    g2d.draw(getBoundsRight());
    g2d.draw(getBoundsLeft());
    g2d.draw(getBoundsTop());
    */

    if(velX != 0){
        if (facing == 1){
        playerWalk.drawAnimation(g,(int) x, (int)y,32,64);
        last = 1;
        }
        else{
            playerWalkLeft.drawAnimation(g,(int) x, (int)y,32,64);
            last =  0;
        }   
    }


    else
        if (last == 1)
        g.drawImage(tex.player[1], (int)x,(int) y,32,64,null);
        else
        g.drawImage(tex.player[6], (int)x,(int) y,32,64,null); // 6 ,32,64

    //System.out.println("Y: " + y); // 513 je max
    if (y >= 513){
        g.setColor(Color.red);
        g.drawString("Game Over", (int) x, 200);
    }
}

public Rectangle getBounds() {
    return new Rectangle((int) ((int)x+(width/2)-((width/2)/2)),(int) ((int)y+(height/2)),(int)width/2,(int)height/2);
}

public Rectangle getBoundsTop() {
    return new Rectangle((int) ((int)x+(width/2)-((width/2)/2)),(int)y,(int)width/2,(int)height/2);
}

public Rectangle getBoundsRight() {
    return new Rectangle((int) ((int)x+width-5),(int)y+5,(int)5,(int)height-10);
}
public Rectangle getBoundsLeft() {
    return new Rectangle((int)x,(int)y+5,(int)5,(int)height-10);
}

Player dont have any problem with block collision.

public class Block extends GameObject {

Texture tex = Game.getInstance();
private int type;


public Block(float x, float y,int type,ObjectId id) {
    super(x, y, id);
    this.type = type;
}

public void tick(LinkedList<GameObject> object) {

}

public void render(Graphics g) {
    if(type == 0)
        g.drawImage(tex.block[0], (int) x, (int) y ,null);
    if(type == 1)
        g.drawImage(tex.block[1], (int) x, (int) y ,null);
}


public Rectangle getBounds() {
    return new Rectangle((int)x,(int)y,32,32);
}
}

But when i tried created Enemy class and make it same like in Player class I mean collision it just make game slower and nothing else.

public class Enemy extends GameObject{

private Handler handler;
public Enemy(float x, float y,Handler handler, ObjectId id) {
    super(x, y, id);
    this.handler = handler;
}

public void tick(LinkedList<GameObject> object) {
    for(int i = 0; i < handler.object.size();i++){
        GameObject tempObject = handler.object.get(i);
        if(tempObject.getId() == ObjectId.Block ){

            if(getBoundsTop().intersects(tempObject.getBounds())){

            }


            if(getBounds().intersects(tempObject.getBounds())){

            }

            if(getBoundsRight().intersects(tempObject.getBounds())){

            }


            if(getBoundsLeft().intersects(tempObject.getBounds())){

            }
        }
    }
}

public void render(Graphics g) {
    g.setColor(Color.red);
    g.fillRect((int)x,(int) y, 32, 32);
}

public Rectangle getBoundsTop() {
    return new Rectangle((int)x,(int)y,32,32);
}

public Rectangle getBoundsLeft() {
    return new Rectangle((int)x,(int)y,32,32);
}

public Rectangle getBoundsRight() {
    return new Rectangle((int)x,(int)y,32,32);
}

public Rectangle getBounds() {
    return new Rectangle((int)x,(int)y,32,32);
}}

I know that bounds should not have return same "new Rectangle" and that theres no any movements of enemy anyway when i set in tick method x--; for just trying if enemy stop when it come to the edge of block but it doesnt work i dont know whats wrong with it i spend more than two days with fixing this. If it can help you there is a link for whole project (Eclipse) You can download it from dropbox

I just wanted to have an enemy which move left and right and have collison with block it means when he "touch" by his left side to the block he "turn around" and move to right side until he "touch" by his right side etc... other collisions between Player and Enemy is not problem for me. But just this. I'm so thankful for every advice :)


Solution

  • The problem is with your getBounds() method.

    You are saying in getBounds() method to return a rectangle with width=32 and height=32. And since your rectangle is 32 by 32 (as mentioned in fillrect(x,y,32,32) ) so getBounds() returns with the intersection in height and width.

    In other words, try not to collide the returned Top left bottom or right bounds with themselves.

    And in enemy(), you are declaring set.color = red while in loading you are using green. Try red==255, green==0, blue==0 instead of if(red == 0 && green == 255 && blue == 0)