2
\$\begingroup\$

I have created a tiled map using a BufferedImage (img) from a PNG. From that, I would like to detect the player's (peter) collisions with individual tiles on the map. However, my code will not run and the console gives me: Exception in thread "main" java.lang.StackOverflowError

I am doing this accross to seperate classes: Peter and Map

In my Peter class, I have created collision boxes (left, right, up, down) for my player. I would like to make it so that collision of different sides of the player will be able to be detected.

public Rectangle getBoundsL() {
    return new Rectangle(x, y+4, 4, HEIGHT-8);
}
public Rectangle getBoundsR() {
    return new Rectangle(x+WIDTH-4, y+4, 4, HEIGHT-8);
}
public Rectangle getBoundsU(){
    return new Rectangle(x+4, y, WIDTH-8, 4);
}
public Rectangle getBoundsD(){
    return new Rectangle(x+4, y+HEIGHT-4, WIDTH-8, 4);
}

In my my Map class, I go through a nested for loop that examines the colour of the BufferedImage's pixels in order to draw the Rectangles that represents the boundaries of my walls.

My checkCollision methods are supposed to return a boolean value when one of the player's collisions boxes intersect with the boxes of any of the wall tiles (in this case, the player's left box).

Peter peter = new Peter();

public boolean checkCollisionL(){
    for(int y = 0; y < mapHeight; y++){
        for(int x = 0; x < mapWidth; x++){
            if((img.getRGB(x,y) == 0xff000000) && 
            peter.getBoundsL().intersects(new Rectangle(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))){
                return true;
            }
        }
    }
    return false;
}

However my game is unable to run, and the console instead gives me the following error:

    Exception in thread "main" java.lang.StackOverflowError
    at peterslostworld.Peter.<init>(Peter.java:12)
    at peterslostworld.Map.<init>(Map.java:25)
    at peterslostworld.Peter.<init>(Peter.java:12)
    at peterslostworld.Map.<init>(Map.java:25)
    at peterslostworld.Peter.<init>(Peter.java:12)
    at peterslostworld.Map.<init>(Map.java:25) 
etc, etc....

It would appear (to me at least) that the it takes issue with referencing the Peter class in the Map class. However, I do not know how to fix this issue.

EDIT: As requested, here are the (incomplete) classes involved in the game:

 package peterslostworld;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PetersLostWorld extends JPanel {

    Peter pete = new Peter(this);
    Map map = new Map();

    public PetersLostWorld() {
        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyReleased(KeyEvent e) {
                pete.keyReleased(e);
            }

            @Override
            public void keyPressed(KeyEvent e) {
                pete.keyPressed(e);
            }
        });
        setFocusable(true);
    }



    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        map.paint(g2);
        pete.paint(g2);

    }

    public static void main(String[] args) throws InterruptedException {
        JFrame frame = new JFrame("Peter's Lost World");
        PetersLostWorld game = new PetersLostWorld();
        frame.add(game);
        frame.setSize(800, 600);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        while (true) {
            game.repaint();
            Thread.sleep(10);
        }
    }
}

package peterslostworld;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

public class Peter {
    private static final int WIDTH = 32;
    private static final int HEIGHT = 32;

    Map map = new Map();

    boolean right = false;
    boolean left = false;
    boolean up = false;
    boolean down = false;

    int x = 40;
    int y = 40;
    int pSpeed = 5;

    private PetersLostWorld game;

    public Peter(PetersLostWorld game) {
        this.game = game;
    }

    Peter() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_A){
            left = true;
        }
        if (e.getKeyCode() == KeyEvent.VK_D){
            right = true;
        }
        if (e.getKeyCode() == KeyEvent.VK_W){
            up = true;
        }
        if (e.getKeyCode() == KeyEvent.VK_S){
            down = true;
        }    
    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_A){
            left = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_D){
            right = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_W){
            up = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_S){
            down = false;
        }    
    }

    public void paint(Graphics2D g2) {

        g2.setColor(Color.red);

        g2.fillRect(x, y, WIDTH, HEIGHT);
        if(left){
            x-=pSpeed;
        }
        if(right){
            x+=pSpeed;
        }
        if(up){
            y-=pSpeed;
        }
        if(down){
            y+=pSpeed;
        }

        g2.setColor(Color.blue);
        g2.draw(getBoundsL());
        g2.draw(getBoundsR());
        g2.draw(getBoundsU());
        g2.draw(getBoundsD());
    }

    public Rectangle getBoundsL() {
        return new Rectangle(x, y+4, 4, HEIGHT-8);
    }
    public Rectangle getBoundsR() {
        return new Rectangle(x+WIDTH-4, y+4, 4, HEIGHT-8);
    }
    public Rectangle getBoundsU(){
        return new Rectangle(x+4, y, WIDTH-8, 4);
    }
    public Rectangle getBoundsD(){
        return new Rectangle(x+4, y+HEIGHT-4, WIDTH-8, 4);
    }
}

package peterslostworld;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Map {
    String path = "C:\\Users\\Owner\\Documents\\Eclispe\\Game03\\src\\game03\\maze.png";
    public int mapHeight = 0;
    public int mapWidth = 0;
    BufferedImage img;

    public Rectangle[] mapTiles = new Rectangle[mapWidth*mapHeight];

    public boolean collideLeft = false;
    public boolean collideRight = false;
    public boolean collideUp = false;
    public boolean collideDown = false;

    public static int TILESIZE = 32;

    Peter peter = new Peter();

    public Map(){
        try{
            BufferedImage image = ImageIO.read(new File(path));
            img = image;
            mapHeight = image.getHeight();
            mapWidth = image.getWidth();

        } 
        catch (IOException e){
        }
    }

    public boolean checkCollisionL(){
        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if((img.getRGB(x,y) == 0xff000000) && 
                peter.getBoundsL().intersects(new Rectangle(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean checkCollisionR(){
        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if((img.getRGB(x,y) == 0xff000000) && 
                peter.getBoundsR().intersects(new Rectangle(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean checkCollisionU(){
        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if((img.getRGB(x,y) == 0xff000000) && 
                peter.getBoundsU().intersects(new Rectangle(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean checkCollisionD(){
        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if((img.getRGB(x,y) == 0xff000000) && 
                peter.getBoundsD().intersects(new Rectangle(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))){
                    return true;
                }
            }
        }
        return false;
    }

    public void paint(Graphics2D g2){
        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if(img.getRGB(x,y) == 0xff000000){
                    g2.fillRect(x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE);
                }
            }
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ What is line 12 of the Peter class and line 25 of the Map class? There is not currently enough information to diagnose the problem. Please provide the full classes, or at least more of them. We specifically need to see where Peter references the Map class, and the Map class references Peter. If I had to guess, Peter is talking to the Map who is talking to Peter who is talking to the Map who is talking to Peter who is talking to the Map who is talking to Peter who is talking to the Map who is talking to Peter who is talking to the Map who is talking to Peter who is... \$\endgroup\$ – Evorlor Jun 10 '15 at 18:38
1
\$\begingroup\$

In your Map class, you are instanciating a Peter object on creation on line 25:

Peter peter = new Peter();

In your Peter class, you are instanciating a Map object on creation on line 12:

Map map = new Map();

So, when you create on of the two objects, it will start creating an infinite amount of maps and Peters (probably not what you want).

This is a basic problem of cross-reference that can be solved by deleting one of the two lines specified at the top of my answer.

EDIT

Having looked your code more carefully, I can see that you do not need to instanciate a Map object in your Peter class nor do you need a handle to any map object, so you can delete this line at line 12:

Map map = new Map();
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.