2

So I am trying to generate a 5x5 grid with 2d array, but when I try to call render method that is responsible for size it does not work. Furthermore, I using rectangle boxes as my images in grid. They render really small.

package ksmd.tiles.Screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;

import ksmd.tiles.Tiles;
import ksmd.tiles.UI.Tile;

public class PlayScreen implements Screen {
    private Tiles game;
    //Texture texture;
    private Tile[][] tile;
    private float boardOffset;
    private OrthographicCamera orthographicCamera;

    public PlayScreen(Tiles game) {
        this.game = game;
        //texture = new Texture("badlogic.jpg");
        tile = new Tile[5][5];
        int tileSize = Tiles.WIDTH / tile[0].length;
        boardOffset = (Tiles.HEIGHT - (tileSize * tile.length)) / 2;
        for (int row = 0; row < tile.length; row++) {
            for (int col = 0; col < tile[0].length; col++) {
                tile[row][col] = new Tile(col * tileSize / 2, row * tileSize + boardOffset + tileSize / 2, tileSize, tileSize);
            }
        }
       // orthographicCamera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    }

    @Override
    public void show() {

    }

    @Override
    public void render(float delta) {
        //game.batch.setProjectionMatrix(orthographicCamera.combined);
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        game.batch.begin();
        for (int row = 0; row < tile.length; row++) {
            for (int col = 0; col < tile[0].length; col++) {

                tile[row][col].render(delta);
            }
        }

        game.batch.end();
    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {

    }
}


package ksmd.tiles.UI;

import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

import ksmd.tiles.Tiles;

public class Tile extends Box implements Screen {
private Tiles game;
private TextureRegion lit;
private TextureRegion dark;
private Sprite sprite;

private boolean selected;

public Tile(float x, float y, float width, float height) {

        this.x = x;
        this.y = y;
        this.height = height -8;
        this.width = width - 8;
        lit = Tiles.res.getAtlas("pack").findRegion("lit");
        dark = Tiles.res.getAtlas("pack").findRegion("dark");
    }


    @Override
    public void show() {
    }

    @Override
    public void render(float delta) {
        game.batch.begin();
        game.batch.draw(lit, x- width/ 2, y- height/ 2, width, height);
        game.batch.end();
    }

    public TextureRegion getTextureRegion(){
        return lit;
    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {

    }
}

Basically I am new and not sure how to use render method to make the atlases bigger in grid. Sorry for bad english.

Guavaman
  • 25
  • 4

1 Answers1

3

If I understand you correctly you will render a Grid of Tiles.
I think it's a camera problem like Squiddie says.
You said you are new to libgdx, so I will give you some hints about how you can better render your game world and hopefully than solve your camera problem.


Firstly you should use a Viewport. If you have understood a viewport it's very helpful, before it's very confusing.

Basically, you create a viewport to define how much you will see of your world and how it affects the content of your world when you have different Screen sizes.

It gives different types of viewport: StretchViewport, FitViewport, FillViewport, ScreenViewport and ExtendViewport more about the viewports: https://github.com/libgdx/libgdx/wiki/Viewports

Creating a Viewport is very basic:

Viewport viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);

The WORLD_WIDHT and WORLD_HEIGHT says how much "units" we can see of our world, the camera is a OrthographicCamera.

In the update() method we must inform the viewport the screen has been resized.

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

Now the Viewport take care of the Content size so that you always see so much of the world you define in the Viewport constructor. A more detailed description how Viewport works: Libgdx's World Units


Now to the Screen. Basically you can only have one Screen active at the same time, so it's wrong to implement Screen in Tile class. LibGdx calls the render method of the active Screen in your case the render() method in PlayScreen. But Tile is not a Screen it's only a Box which can be rendered. So Tile doesn't need to implement Screen.


The Sprite class holds not only the Texture or TextureRegion it also holds where and how the sprite will be rendered. So when you have a Sprite you don't need to have variables for x, y, width, height and rotation. You can simplify your Tile if you using your sprite:

private Sprite texture;
public Tile(float x, float y, int widht, int height, Texture tex) {
    texture = new Sprite(tex);
    texture.setBounds(x, y, widht, height);
}

You can also easy draw the sprite:

public void render(Batch batch, float delta){
    texture.draw(batch);
}

To draw the sprites correctly on the Screen you must tell the SpriteBatch to use the matrix of your camera. To do that, before you call batch.begin() you must call:

batch.setProjectionMatrix(viewport.getCamera().combined);

Now before you begin to draw your sprites, you need to call batch.begin();
Important now is that you only call batch.begin(); once in render method. In your code example you call batch.begin about 26 times because you also call batch.begin in Tile class which occurs probably in a Exception. At the end of your render method you must call one time batch.end();


I hope will all that information you can solve your problem, which is a Camera problem like Squiddie in the comments already said.

Here is also a little running example of rendering a Grid, maybe it can help you to understand each of the components and how you can do it:

public class PlayScreen implements Screen {

    private Tile[][] tiles;
    private Viewport viewport;
    private OrthographicCamera camera;

    private SpriteBatch batch;
    private Texture tex;

    private final float WORLD_WIDTH = 50, WORLD_HEIGHT = 50; //to see 50 x 50 units of the world
    private final int TILE_SIZE = 10; //on tile is 10 units big

    @Override
    public void show() {
        camera = new OrthographicCamera(WORLD_WIDTH, WORLD_HEIGHT);
        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0); // center the camera
        viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera); // create a viewport which sees 50 x 50 units of the game world

        batch = new SpriteBatch();

        tex = new Texture(Gdx.files.internal("badlogic.jpg"));

        tiles = new Tile[5][5];

        //Create the tiles
        for(int row = 0; row < tiles.length; row++){
            for(int col = 0; col < tiles[0].length; col++){
                tiles[row][col] = new Tile(col * TILE_SIZE, row * TILE_SIZE,TILE_SIZE, TILE_SIZE, tex);
            }
        }
    }

    //render the Tiles
    @Override
    public void render(float delta) {
        batch.setProjectionMatrix(viewport.getCamera().combined);

        batch.begin(); //call batch.begin() (this is the only call of batch.begin() !!! )
        for(int row = 0; row < tiles.length; row++){
            for(int col = 0; col < tiles[0].length; col++){
                tiles[row][col].render(batch, delta); // call the render method of each tile
            }
        }
        batch.end();//call batch.end() (this is the only call of batch.end() !!! )
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height); // update the viewport when the screen has been resized
    }

    @Override
    public void dispose() {
        //dispose disposable objects
        batch.dispose();
        tex.dispose();
    }

    @Override
    public void pause() { }
    @Override
    public void resume() { }
    @Override
    public void hide() { }
}

public class Tile {

    private Sprite texture;

    public Tile(float x, float y, int widht, int height, Texture tex) {
        texture = new Sprite(tex);
        texture.setBounds(x, y, widht, height); // set bounds of Sprite
    }

    public void render(Batch batch, float delta){
        //draw the sprite, but not call batch.begin() !!! because batch.begin() is already called!
        texture.draw(batch);
    }
}
Morchul
  • 1,987
  • 1
  • 7
  • 21
  • Woah thanks so much dude, really appreciate you taking the time to help me understand this. I will give this a shot and will update you! – Guavaman Nov 05 '18 at 14:16
  • do you know how I would change the image upon click? @Morchul thanks so much! – Guavaman Nov 12 '18 at 02:17
  • @Guavaman the Image of Button or the Background image? You can use the InputProcessor: https://github.com/libgdx/libgdx/wiki/Event-handling to catch the click events. – Morchul Nov 12 '18 at 07:49