Advertisement

How to treat coordinates in a simple 2D game?

Started by July 26, 2018 07:24 AM
17 comments, last by master_clown 6 years, 6 months ago

I'm making a simple 2D game — a copy of 'Battle City' — using OpenGL Core profile (to train the skill in it), and now I've come across a question, how should I handle an object coordinates and sizes. What kind of measure should I use for them? As I get it, that info is being put to the model matrix. But how can I place my objects to the exact positions I desire them to be in? And how scale them properly? For instance, I want to draw a game field -- collection of little squares. The resolution of the screen may change, so fixed coordinates and sizes are inappropriate (or not?). Maybe then I should set numbers relatively the width and height of the screen?

I hope I expressed myself clearly. It's quite a basic problem, everyone who made a game has faced with it. Though, can't get, what coordinates and sizes in what coordinate system to use when it comes to placing and scaling game objects.

 

First you need to decide what kind of 2d game you want to have.

I usually normalise my coordinates to one of two things:

If it's a single screen game (no scrolling) I usually chose one of the axis of the screen (usualy width) as 1.0 . This is useful when you do GUI work: Menus, buttons,etc.. (ex: Card games )

If it's a scrolling tile based game, I usually normalise to tile size: 1 tile = 1.0 x 1.0 (ex: Strategy games / Platformers)

It doesn't really matter how you normalise your coordinates, but it's useful to normalise them to something meaningful to your game.

(in anything with physics I usually use 1.0 = 1 meter)

 

My Oculus Rift Game: RaiderV

My Android VR games: Time-Rider& Dozer Driver

My browser game: Vitrage - A game of stained glass

My android games : Enemies of the Crown & Killer Bees

Advertisement

SillyCow, the center of the screen is the origin, with respect to which I should build a model matrix?

If your game doesn't scroll, I would recommend making the top left corner (0,0) with sizes increasing towards the bottom right. This is inline with how popular image files are encoded. (I assume you will be loading sprites from PNG or JPG files...)

If you are making a scrolling game (Mario), it doesn't really matter. The center of the screen is as good an origin as anything.

PS: I wouldn't spend too much time thinking about it, just start drawing stuff and see what happens. Eventually you can make any coordinate system work. Just start  try *something* and see if it works for you. (More important to start prototyping and gain some experience). Even if you end up making a mistake, you will have more tools to understand it.

My Oculus Rift Game: RaiderV

My Android VR games: Time-Rider& Dozer Driver

My browser game: Vitrage - A game of stained glass

My android games : Enemies of the Crown & Killer Bees

7 hours ago, master_clown said:

For instance, I want to draw a game field -- collection of little squares. The resolution of the screen may change, so fixed coordinates and sizes are inappropriate (or not?).

The way most engines solve this is by having a abstract unit. So (1X,1Y) is a visual block. Then they allow you to define how many pixels (1X,1Y) is.

So if I wanted Every X to be a 100 pixels then that is what it is. That way the developer can tweak the values of X and Y to fit any screen.

Shouldnt you use just 0..1 for each dimension x and y, this will give you exact size on different resolutions you will need a function to change world position into a 2d screen but knowing that center is at 0.5,0.5 anf knowinh world translation youll be able to handle it its like how far you want to see lts say its 320 units along x and , so its like

vec2 vs = vp.xy - translation.xy;
vec2 sc = (vec2(sw, sh) / 2.0) / scale; // our translation center

gl_Position = vec4((vs/sc), 0.0, 1.0);

Where sw and sh are screen dimension in pixels so one pixel corresponds to 1 unit  and vp is vertex position its quite simple

Advertisement
11 minutes ago, KKTHXBYE said:

Shouldnt you use just 0..1 for each dimension x and y, this will give you exact size on different resolutions

Actually, assuming a single screen game/app it is usually usefull to select one dominant axis as 1.0 and scale the other according to the aspect ratio. Otherwise your image will get stretched. 

My Oculus Rift Game: RaiderV

My Android VR games: Time-Rider& Dozer Driver

My browser game: Vitrage - A game of stained glass

My android games : Enemies of the Crown & Killer Bees

Looks like I did not get the thing, so I'll elaborate a bit.

As I said, the game is a copy of 'Battle city'. For now I'm writing the code of the game field drawing. It happens in such way:

1. The view matrix looks at the origin from the point (0.0, 0.0, 1.0) with 'up' direction as (0.0, 1.0, 0.0). 

2. The game field is made up from tiny blocks which are drawn consecutively. The place of a block is defined by its model matrix:


model = mat4(1.0f);
model = glm::translate(model, Vec3f(i * BLOCK_SIZE,
									j * BLOCK_SIZE,
                       				0.0f));
model = glm::scale(model, Vec3f(BLOCK_SIZE));

for [i,j] block. The coordinates of vertices of a block are (±0.5f, ±0.5f, 0.0f), i.e. it's a unit square. So after scaling it becomes a square with scaling factor BLOCK_SIZE side, correct? And does this mean that the center of a block is initially at the origin?

Well, the main misunderstanding I have is about window resizing and the coordinate system I'm working in. The problem is notable in the attached photos. After window resizing (horizontally expanded) the square has moved (or it's just the viewport is making something) ans is fully visible.  What I want is to fix the game field in some ratio relatively to the screen, so that it expanded as the windows does, but stays in its place. What kind of things I should do is unclear to me.

image.png

image.png

You can render everything to an offscreen texture with fixed sized, and then fill the screen with this texture. That way you dont need to worry about the screen size (since the render target texture has fixed size) but this may cause some quality issues when the texture is stretched to fill the screen.

You can also use some kind of relative coordinate system, as other have suggested, so that when the screen changes size you just call an OnResize() function which (re)computes the screen position based on a relative offset.

2 minutes ago, Aerodactyl55 said:

You can render everything to an offscreen texture with fixed sized, and then fill the screen with this texture. That way you dont need to worry about the screen size (since the render target texture has fixed size) but this may cause some quality issues when the texture is stretched to fill the screen.

You can also use some kind of relative coordinate system, as other have suggested, so that when the screen changes size you just call an OnResize() function which (re)computes the screen position based on a relative offset.

The former is inappropriate for the reason you've written yourself. The latter is, probably, the thing I'm looking for and about which the guys above were talking. I just don't understand how it should look in the code.

This topic is closed to new replies.

Advertisement