简体   繁体   中英

Scene 2D Separation from viewport coordinates and game coordinates

To practice my Java skills, I have been developing a basic Snake Game. With java, I am using LibGDX and Scene2d to handle all my objects.

Right now, the boundaries of the snake game are set to the viewport dimensions. Collisions are checked whenever the snake reaches the outside of the viewport. I am using a screen viewport which is incorporated into the Stage as seen below.

private AudioSnake gameCore;
private Stage gameStage;
private Image background;
private Image snakeTip;
private Image food;
private ArrayList<Image> snakeTail = new ArrayList <Image>(); // all the snake tail bits
private ScreenViewport viewport;

public GameScreen(AudioSnake audioSnake) {
    gameCore = audioSnake;
    viewport = new ScreenViewport();
    gameStage = new Stage(viewport);
    Gdx.input.setInputProcessor(gameStage); 
    uiSkin = new Skin(Gdx.files.internal("Ui/uiskin.json"));
    scoreLabel = new Label(String.format("%.0f",score),uiSkin);
    generateUi();
    generateFood();
}

Collision check code:

    public void collisionCheck(){ // method that checks rather the snake head is touching outside the border, or inside it's own body
    if(snakeTip.getX() >= gameStage.getWidth() || snakeTip.getY() >= gameStage.getHeight() || snakeTip.getX() <= 0 || snakeTip.getY() <= 0){
        System.out.println("death activated");
        activateDeath();
    }
    else{
        for(int i = 0; i < snakeTail.size(); i++){
            if(snakeTip.getX() == snakeTail.get(i).getX() && snakeTip.getY() == snakeTail.get(i).getY()){
                System.out.println("death activated");
                activateDeath();
            }
        }
    }
}

The big problem with this is that the game mechanics are greatly affected by the size of the screen. What I WANT to have is a virtual area that the snake moves around in (almost like it's own coordinate system) that is separate from the viewport. As for the viewport, I'd rather it remain a screen viewport if possible. What would be the best way to do this?

ScreenViewport is not good here because your game would be for example good looking on smaprtphone's screen when it would be a little polygon at the center of tablet's one. You should rather consider using FitViewport which will add a bars to your screen but will make it possible to keep the same arena size for every device.

To define what resolution your virtual screen should have just pass it in the viewport's constructor

    private FitViewport viewport;

    public GameScreen(AudioSnake audioSnake) {
        gameCore = audioSnake;
        viewport = new ScreenViewport(SCREEN_WIDTH_IN_PX, SCREEN_HEIGHT_IN_PX);
        gameStage = new Stage(viewport);

then you also need to overwrite the resize() method to make your viewport updatable

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
    }

Also in your render() method you need to apply viewport right before rendering the stage

    viewport.apply();
    stage.act(delta);
    stage.draw();

After all of this instead of gameStage.getWidth() you can use just your custom SCREEN_WIDTH_IN_PX

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