简体   繁体   中英

Camera going out of bounds of map. How do I fix it?

Everyone. I am having a problem with my java game that I am making. I have made it so that it centers on the player, however, what I want it to do is when the camera's xPos and yPos exceed the Map's width and height, it snaps to the last row of tiles on the map.

Here is my camera class:

public class GameCamera {
private CoreEngine coreEngine; 
private int xOffset; 
private int yOffset;

public GameCamera(CoreEngine coreEngine, int xOffset, int yOffset) { 
    this.coreEngine = coreEngine;
    this.xOffset = xOffset; 
    this.yOffset = yOffset; 
}

public void centerOnEntity(Entity e) { 
    xOffset = e.getX() - coreEngine.getWidth() / 2 + e.getWidth() / 2;
    yOffset = e.getY() - coreEngine.getHeight() / 2 + e.getHeight() / 2;
}

public void setCameraBounds() {
    //Code here to snap/clamp the screen when xPos or yPos exceed Map's width and height. 
}

public void move(float xAmt, float yAmt) {
    xOffset += xAmt;
    yOffset += yAmt;
}

public int getxOffset() {
    return xOffset;
}
public void setxOffset(int xOffset) {
    this.xOffset = xOffset;
}
public int getyOffset() {
    return yOffset;
}
public void setyOffset(int yOffset) {
    this.yOffset = yOffset;
} 

}

Here is my world class:

public class World {
@SuppressWarnings("unused")
private CoreEngine coreEngine;
private int[][] tileMap; 
private int width; 
private int height;
@SuppressWarnings("unused")
private int xSpawn;
@SuppressWarnings("unused")
private int ySpawn;

private EntityManager entityManager;

public World(CoreEngine coreEngine, String filePath) {
    this.coreEngine = coreEngine;
    entityManager = new EntityManager(this, coreEngine);
    loadWorld(filePath);
}

public void update() {
    entityManager.update();
}

public void render(Graphics g) {
    int xStart = Math.max(0, coreEngine.getGameCamera().getxOffset() / Tile.TILEWIDTH);
    int xEnd = Math.min(width, (coreEngine.getGameCamera().getxOffset() + coreEngine.getWidth()) / Tile.TILEWIDTH + 1);
    int yStart = Math.max(0, coreEngine.getGameCamera().getyOffset() / Tile.TILEHEIGHT);
    int yEnd = Math.min(height, (coreEngine.getGameCamera().getyOffset() + coreEngine.getHeight()) / Tile.TILEHEIGHT + 1);

    for(int yPos = yStart; yPos < yEnd; yPos++) {
        for(int xPos = xStart; xPos < xEnd; xPos++) {
            getTile(xPos, yPos).render(g,  xPos * Tile.TILEWIDTH - coreEngine.getGameCamera().getxOffset(), yPos * Tile.TILEHEIGHT - coreEngine.getGameCamera().getyOffset());
        }
    }

    entityManager.render(g);
}

public Tile getTile(int xPos, int yPos) { 
    Tile tile = Tile.tilesArray[tileMap[xPos][yPos]];
    if (tile == null) return Tile.dirtTile; 
    return tile;
}

private void loadWorld(String filePath) { 
    String file = FileLoader.loadFile(filePath);
    String[] tokens = file.split("\\s+");
    width  = FileLoader.parseInt(tokens[0]);
    height = FileLoader.parseInt(tokens[1]);
    xSpawn = FileLoader.parseInt(tokens[2]);
    ySpawn = FileLoader.parseInt(tokens[3]);

    tileMap = new int[width][height];
    for(int yPos = 0; yPos < height; yPos++) {
        for(int xPos = 0; xPos < width; xPos++) {
            tileMap[xPos][yPos] = FileLoader.parseInt(tokens[(xPos + yPos * width) + 4]);
        }
    }
}

Here is my Player class:

public class Player extends Creature {
public static String playerKey = "Player";
private String playerName = "Player One";
public static Inventory inventory;
private Rectangle playerBox;

private Direction currentDirection;
private Bar healthBar;
private Bar energyBar;

private World worldOne;

public Player(CoreEngine coreEngine, World worldOne, int xPos, int yPos) {
    super(coreEngine, worldOne, xPos, yPos, Creature.DEFAULT_CREATURE_WIDTH, Creature.DEFAULT_CREATURE_HEIGHT);
    GameObject.addObject(coreEngine, playerKey, xPos, yPos, width, height);
    this.worldOne = worldOne;
    inventory = new Inventory(this);
    currentDirection = Direction.DOWN;
    init();
}

private void init() {
    healthBar = new Bar((CoreEngine.getWidth() / 2) - 175, (CoreEngine.getHeight() / 2) + 150, 350, 15, Color.lightGray, Color.red,Color.white, this);
    energyBar = new Bar((CoreEngine.getWidth() / 2) - 175, (CoreEngine.getHeight() / 2) + 130, 350, 15, Color.lightGray, Color.yellow, Color.white, this);
    healthBar.fillHealth();
    energyBar.fillEnergy();
}

private void setCollision(int xPos, int yPos, int width, int height) { 
     playerBox = new Rectangle(xPos, yPos, width, height); 
}

//Player Logic Goes Here
public void update() { 
    getInput();
    move(xChange, yChange);
    coreEngine.getGameCamera().centerOnEntity(this);

    healthBar.update();
    energyBar.update();
    inventory.update();
}

public void getInput() { 
    xChange = 0;
    yChange = 0;

    if(coreEngine.getKeyManager().up) {
        currentDirection = Direction.UP;
        yChange = -speed;
    }
    if(coreEngine.getKeyManager().down) {
        currentDirection = Direction.DOWN;
        yChange = speed;
    }
    if(coreEngine.getKeyManager().left) {
        currentDirection = Direction.LEFT;
        xChange = -speed;
    }
    if(coreEngine.getKeyManager().right) {
        currentDirection = Direction.RIGHT;
        xChange = speed;
    }
}

public void render(Graphics g) {
    //g.setColor(new Color(133, 20, 133));
    //g.setFont(new Font("Freaky Paper Cutouts", Font.BOLD, 14));
    //g.drawString(playerName, (xPos - coreEngine.getGameCamera().getxOffset()) - 15, (yPos - coreEngine.getGameCamera().getyOffset()) - 25);
    //g.drawString("(" + xPos + ", " + yPos + ") ", (xPos - coreEngine.getGameCamera().getxOffset()) - 15, (yPos - coreEngine.getGameCamera().getyOffset()) - 10);

    //Basic Purple Player Image
    g.drawImage(CELibrary.playerOne,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);

    //For Use w/ Player Animation:
    switch(currentDirection) {
    case UP:
        //g.drawImage(ResourceLoader.playerUp,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);
        break;
    case DOWN:
        //g.drawImage(ResourceLoader.playerDown,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);
        break;
    case LEFT:
        //g.drawImage(ResourceLoader.playerLeft,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);
        break;
    case RIGHT:
        //g.drawImage(ResourceLoader.playerRight,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);
        break;
    default: //Default Direction = Idle
        //g.drawImage(ResourceLoader.playerIdle,  xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), width, height, null);
        break;
    }

    inventory.render(g);

    g.setColor(Color.red); //Currently showing playerBox for debug purposes only - g.setColor(new Color(133, 20, 133));
    setCollision(xPos - coreEngine.getGameCamera().getxOffset(), yPos - coreEngine.getGameCamera().getyOffset(), Creature.DEFAULT_CREATURE_WIDTH, Creature.DEFAULT_CREATURE_HEIGHT);
    g.drawRect(playerBox.x, playerBox.y, playerBox.width, playerBox.height);

    g.setFont(new Font("Freaky Paper Cutouts", Font.BOLD, 25));
    g.setColor(Color.white);
    g.drawString("Score:", 10, 25);
    g.drawString("" + worldOne.getEntityManager().getWaveManager().score, 580, 25);

    g.setFont(new Font("Freaky Paper Cutouts", Font.BOLD, 14));
    g.setColor(new Color(133, 20, 133));
    g.drawString(playerName, (CoreEngine.getWidth() / 2) - 173, (CoreEngine.getHeight() / 2) + 123);
    g.drawString("(" + xPos + ", " + yPos + ") ", (CoreEngine.getWidth() / 2) + 110, (CoreEngine.getHeight() / 2) + 123);

    energyBar.renderEnergy(g);

    if (getEnergy() == 0) g.drawString("0", (CoreEngine.getWidth() / 2) + 148, (CoreEngine.getHeight() / 2) + 143);
    g.setColor(Color.black);
    g.drawString("Energy: ", (CoreEngine.getWidth() / 2) - 173, (CoreEngine.getHeight() / 2) + 142);
    g.drawString("" + getEnergy(), (CoreEngine.getWidth() / 2) + 148, (CoreEngine.getHeight() / 2) + 143);

    healthBar.renderHealth(g);

    if (getHealth() == 0) g.drawString("0", (CoreEngine.getWidth() / 2) + 148, (CoreEngine.getHeight() / 2) + 162);
    g.setColor(Color.white);
    g.drawString("Health: ", (CoreEngine.getWidth() / 2) - 173, (CoreEngine.getHeight() / 2) + 163);
    g.drawString("" + getHealth(), (CoreEngine.getWidth() / 2) + 148, (CoreEngine.getHeight() / 2) + 162);
}

Here is my GameState class:

public class PlayState extends GameState {

private World worldOne;

public PlayState(CoreEngine coreEngine) {
    super(coreEngine);
    init();
}

private void init() {
    worldOne = new World(coreEngine, CELibrary.WorldPath + "WorldOne.txt");
    //CEMusic.getMusic(CELibrary.Eight_Bit_Trip).play();
}

public void update() {
    worldOne.update();

    /* //Debugging Health / Energy Bar
    if (worldOne.getEntityManager().getPlayer().getHealth() == 0) worldOne.getEntityManager().getPlayer().hurt(0);
    else worldOne.getEntityManager().getPlayer().hurt(Creature.DEFAULT_DAMAGE_TAKEN);

    if (worldOne.getEntityManager().getPlayer().getEnergy() == 0) worldOne.getEntityManager().getPlayer().useEnergy(0);
    else worldOne.getEntityManager().getPlayer().useEnergy(Creature.DEFAULT_ENERGY_COST);
    */
}

@SuppressWarnings("static-access")
public void render(Graphics g) {
    //Render the Background
    g.setColor(Color.black);
    g.fillRect(0, 0, coreEngine.getWidth(), coreEngine.getHeight());

    //Render the World
    worldOne.render(g);
}

}

Here is an image of what I want removed: http://tinypic.com/r/8z4nkz/8

Any ideas as to how I can implement this functionality that I described above?

Right now, we never see how the game is centering on your player. I assume it's somewhere calling your method camera.centerOnEntity(mainPlayer) , but I don't know.

Assuming that is how you are centering the camera, all you have to do is ensure that your player itself isn't going off the map. That is, don't bound the camera - bound the player (entity) itself every time you are moving it.

So I'm not really sure how you reference the world as a whole, but assuming that you do (you'll have to format it to work with your code):

public void setCameraBounds() {
    if(xOffset >= world.getWidth()/2 + (Half of the player)){
    moveRight = false;
    } else if(xOffset <= 0){
    moveLeft = false;
    }
    if(yOffset >= world.getHeight()/2 + (Half of the player)){
    moveDown = false;
    } else if(yOffset <= 0){
    moveUp = false;
    } 
}

Inside of whatever your method that listens for movement is, before you move in each direction, just check for the corrosponding boolean. This will make it so when you reach an edge of the world, your player can not move any closer to that edge.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM