0
\$\begingroup\$

I am quite new to game development (but not programming) so please forgive me if I am not correctly understanding certain concepts.

I am trying to figure out how to use world coordinates rather than pixel coordinates so that my game can work correctly at different resolutions. As I understand it, I need a viewport and I can use camera functions such as project() and unproject() to convert between the two coordinates. At the moment, I am just placing objects every 16 pixels as this is the size of objects and the objects cannot intersect.

For example:

enter image description here

The bottom left block is located at pixel (0, 0), the one to the right at (16, 0), to the right of that is (32, 0), and so on. However, I would like to be able to place them at (0,0), (1, 0), and (2, 0) with the same result so that it looks the same on different resolutions.

Basically, I'm asking how to set this up and have it work properly as world coordinates.

\$\endgroup\$
0
\$\begingroup\$

Here's what I would do in this situation.I'm not using libgdx myself, but I'll give you some pseudo pseudo code. If you haven't already, make a separate class called something like TileMap In that class, create the following variables.

  • public int tileSize
  • public int tilesX
  • public int tilesY
  • public int[,] map

The map variable is a two dimensional integer array, meaning that every tile type will be represented as an int. For example, a stone tile could be '3'

In the constructor of the TileMap you need to take in ( tileSize, tilesX, tilesY), and assign them to the local variables.In the bottom of the constructor you need to instantiate the map variable like shown in the example constructor below

public TileMap( tileSize, tilesX, tilesY ){
    this.tileSize = tileSize;    this.tilesX = tilesX;    this.tilesY = tilesY;
    this.map = new int[tilesX,tilesY]();    // not sure if you need the () at the end, since I'm writing this on my phone.
    }

Now you've got a TileMap setup, currently all the tiles should be 0 to my understanding, if they aren't you might have to make a nested for loop for the tilesX and tilesY variables. It's time to create the methods that will return the world position from given tile coordinates, and the method that will return a tile from the given world coordinates. To convert to world position, simply take the X and Y values and multiply them by the tileSize this will give you 0,0 at the tile 0,0 and 48,48 at the tile 2,2 assuming you have tileSize set to 24 You can create a method that returns this easily.

To get the tile from world coordinates you need to do something like this assuming you work with vectors

public int getTileWorldPos(Vector2 worldPos){
float x = Math.floor(worldPos.x/tileSize);
float y = Math.floor(worldPos.y/tileSize);

return map[x,y];
}

This method will return the tile id at the given world coordinates

If you want to change the tile at a given world pos use this method

public void setTileWorldPos(Vector2 worldPos, int newtile){
float x = Math.floor(worldPos.x/tileSize);
float y = Math.floor(worldPos.y/tileSize);
map[x,y] = newtile;
return;
}

Now that you've got a TileMap class, you need to instantiate it in your main class. To do this, simply write

TileMap map = new TileMap (24, 10, 10);

In that case, I'm creating a 10 by 10 TileMap with a tileSize of 24

If you want to manually set a tile you can just do like this

map[6,3] = 3;

And to use the methods you created in the TileMap class, write

map.getTileWorldPos(new Vector2 (362, 49));

I've written all of this on my phone, so I haven't had any way to test my code, and syntax might not be perfect. But hopefully this will give you an idea on how to do this.

if I'm missing anything feel free to ask questions.

I hope this can help you achieve what you want :)

\$\endgroup\$
  • \$\begingroup\$ Thank you very much for your in-depth explaination. I'm going to do some more research on TileMaps to make sure it is what I want because this will require a lot of rewriting what I already have. My imediate concern is that my world is infinitely generated. Can I change the size of the tile map as the player explores? \$\endgroup\$ – Panda Jun 23 '15 at 6:31
  • \$\begingroup\$ Infinite TileMaps are a bit more of a challenge. Have a look at this google.dk/… \$\endgroup\$ – Daniel Holst Jun 23 '15 at 6:38
  • \$\begingroup\$ Thank you, I think this will work for me, however I have one more question, if you don't mind. From what I understand, tileSize is still the pixel dimensions of a tile. Doesn't this present the same problems as before with things looking weird at different resolutions? \$\endgroup\$ – Panda Jun 23 '15 at 6:55
  • 1
    \$\begingroup\$ If you want the tiles to always have the same size no matter the resolution. You just need to change the tileSize variable to a float. And then calculate the tileSize like this. TileSize = (resolution width) / (how many tiles to fit on screen width) \$\endgroup\$ – Daniel Holst Jun 23 '15 at 7:09
0
\$\begingroup\$

You are allready on the right path, Viewport and Camera are what you are looking for.
If you take a look at the different Viewporttypes, there are some, which support virtual screen sizes. That means, that you can say how big your Viewport is and Libgdx will "scale" it up to the Game-Window (or to the screen, if fullscreen).
So when creating a Viewport, all you have to think about is, how many units i want to see on screen at one time.
If you, for example, have a human-like character (about 2m tall), and you want him to use 1/10 of the screen-height, the your virtual screen height would be 20 (character-height/screen-height = 1/10).
Also think about the aspect ratio. Most PCs nowadays have a 16/9 aspect ratio, while mobile devices might have different aspect ratios.
There are different Viewport-types, with different solutions to this: - FitViewport keeps aspect ratio, by showing black borders on the sides or on top and bottom, if aspect ratio is different.
- StretchViewport stretches the frame to use up the whole screen, no black borders will be shown.

There might be other Viewport types with different solutions for this, but i guess those are the most important types.

The Camera instead is used to show different parts of the world, you can simply move it arround using world units.

And as you allready said, you can convert pixels to worldunits and vice versa, by using viewport.project and viewport.unproject. This is used for touchinputs for example, as they are given in screen coordinates.

\$\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.