# What coordinate system to use to handle 2D UI?

Following on from the aspect ratios question, I'm interested to hear what other people are using when working on 2D UI systems (most likely their own home-grown solutions). Specifically, how do you handle coordinate systems. To my mind there are three options:

1. Hard-coded co-ordinates (e.g.: 0 -> 720, 0 -> 576)
2. Normalised co-ordinates (0.0 -> 1.0, 0.0 -> 1.0), mapped into real coordinates before rendering
3. Virtual co-ordinates (e.g.: 0 -> 1600, 0 -> 1000), mapped into real coordinates before rendering

Hard-coded is obviously only useful if you're on a fixed platform and know what your screen space coordinates are in advance, or if you're prepared to author screen layouts for every possible set of screen dimensions.

Normalised co-ordinates are nice, but suffer from ambiguity when the aspect ratio of the screen isn't fixed (e.g. 0.75 maps to a different physical co-ordinate when running in widescreen than it does in 4:3). Also, for the authors, it's really counterintuitive to declare a UI element to be (0.2 x 0.2), only to find it's not actually square when rendered.

Virtual co-ordinates are unambiguous, but suffer from the same problems as normalised co-ordinates at the remapping stage: a tiny decimal discrepancy can result in off-by-one errors meaning that UI elements which should tile now have a seam between them.

Similarly, when you do have a fixed resolution screen, both normalised and virtual coordinates mean that it's very difficult to guarantee a 1:1 mapping between your artist's finely crafted pixels in the UI image, and pixels on screen, meaning you run the risk of nasty scaling artefacts (assuming you're rendering as textured quads on screen).

We've gone with the virtual co-ordinate approach, specifically to avoid ambiguity about aspect ratios. So when rendering to a 16:10 screen, the UI space is (0,0) -> (1600,1000), but when rendering to 4:3, the usable UI space is actually (133,0) -> (1467,0).

Are there any better solutions that I'm just not aware of? Are there any good strategies for minimising the problems these 3 approachs have?

I think I agree that normalised co-ordinates don't really map well to UI stuff.

What I typically do for 2D layouts, is basically your "virtual" co-ordinate space, but I pick a space which maps 1:1 with my prefered target resolution (1280x720, for example). It's not fixed, but it's intuitive to deal with and I know that in 90% of cases it'll look just right. Obviously it's important not to get complacent, and to actually check different resolutions often.

For crispness when remapping resolutions, I'd borrow some tips from font-rendering, and provide hinting information. So make sure that things which need to be continuous are tagged in some way, while also performing rounding to exact pixels where crisp alignment is necessary.

Perhaps also consider making things more relative. So rather than everything being "position object 1 at absolute X,Y", you could specify "position bottom left of object 2 at some offset from bottom right of object 1". It's easier then to rescale and/or move things about, without losing important relationships.

CEGUI's coordinate system seems really well thought out. It's unified coordinate system blends absolute positioning with relative positioning. You can specify locations like:

• in the middle of the screen
UDim(0.5,0)
• five pixels to the left of the right edge
UDim(1.0,-5)
• two widgets in the middle but separated by 10 pixels
HA_RIGHT,UDim(0.5,-5) HA_LEFT,UDim(0.5,5)

If in doubt, why not go with the CSS box model, or a simplification of it?

You can specify positions in percentages or pixels. You might position containers with percentages but position the items within them by pixels, for example.

I like using virtual coordinates, but based around a common target resolution (preferably one of the highest resolutions that you expect the game to be run at.

These days, a good choice may be 1920x1080.

All artwork and screen mock-ups can be created at that resolution, and it makes it easy to measure positions/distances in pixels.

If running at a different aspect ratio to the virtual coordinates, you can choose how to fit it to the screen (letterboxing, cropping the sides, or a bit of both)

When coding, I find 'thinking in pixels' much easier than thinking in normalised coordinates! - I want the text to be '50 (virtual) pixels in height' rather than '0.0463 units high'

It totally depends on what type of GUI you have, but often games have things anchored along the edges of the screen and in corners, and then they might have a box in the middle of the screen for a modal dialog or something.

If that's the case for you, then might I suggest using a scheme where you specify an anchor and an offset (x,y)? This would be similar to Java's BorderLayout (but maybe with the four corners, four middles of edges, and one center of screen). So for example, you could specify an offset of (0,0) from the top-left corner; then the element would be anchored exactly in the corner of the screen. And then no matter what resolution, aspect ratio, etc., you would have the health indicator in the corner of the screen. But then if you anchor an element to the top right corner, the element would naturally be anchored relative to its top right point (instead of top left), so again it would be automatically anchored to the corner of the screen no matter the resolution.

I definitely recommend against normalized 0.0-1.0 coordinates; these could vary based on floating-point accuracy. GUIs should be mapped to pixels, unless you have a 3D GUI.

• Well, using relative positioning and anchors pretty much a given for any kind of UI system. I'm specifically more interested in the measurements between different components. And for this sort of thing, the 3D / 2D GUI distinction is sort of hazy: especially when you're using textured screen space quads to take images of arbitrary size, and scale/position them in your UI space. – MrCranky Aug 4 '10 at 16:05

A lot depends on the kind of game and the situation. For quick-and-dirty prototypes, I prefer to plan out the UI on graph paper, write down a list of numeric coordinates for a fixed window size, and hardcode everything -- it's easier and faster for me. But for a "real" project where you'd want resizable windows or alternate screen resolutions, that would obviously not be ideal, and some kind of solution that allows for scaling in both directions would be better.