Resolutions and image positioning

BlitzMax Forums/BlitzMax Programming/Resolutions and image positioning

Arska(Posted 2015) [#1]
I have UI that is 2560x1600 resolution and it's drawn from screen x0 y0 position to graphicsWidth and height. In bottom right corner is frame for map. I am trying to get minimap drawn inside of those frames regardless of what resolution player chooses. How this can be achieved?

And secondly i think it's not very wise to make UI this way or am i wrong?


Derron(Posted 2015) [#2]
Split the ui into multiple parts.

The map is drawn "behind" the ui:


- draw game
- draw map
- draw hud/ui

Or if your hud/ui consists of individual objects, the map can be drawn by the "mapUI"-component which handles drawing the overlay (the portion of your 2560x1600 image).


Why "split into multiple parts": I assume your "UI" does not cover the whole screen, else you wont see your game at all. Means you include much whitespace/unused area in your image - but all of these pixels has to get send to the GPU...

Solution: Split this images into areas (spellbar, decorations, minimap overlay ...) and draw them individually.
How to handle various resolutions?
- scale
- show/hide decorative elements regarding the aspect ratio (eg a stone figurine left and right of your spell bar)
- have things consiting of "fixed dimension", "stretchable" or "tileable" portions

If your element is "tileable" you will have to decide whether you could stop at each "width" or if the tile-width decides some kind of "width steps".


bye
Ron


Arska(Posted 2015) [#3]
What is the best way to calculate scale and position? And what is best image size for UI elements? Let's say for example that is want health bar bottom middle of the screen which goes 0 to 100 %, but i can't just draw it how it looks good with 800x600 resolution, because when i switch to fullscreen it's in wrong place and size.


Derron(Posted 2015) [#4]
instead of having your healthbar at "x=10, y=100" you calculate:

x = 10 when width = 800
xRelative = 1/80 %

So for a width of 1280 the resulting x is:
xRelative * 1280 = 16


So you could position all your elements by using relative numbers:
xRelative = 0.0 - 1.0 (or <0 respective <1.0 if you want an offscreen position)
yRelative = 0.0 - 1.0 (same as above)

healthbar width is then instead of 100 (at 800x600) 1/8 = 0.125%.


You could of course go more complex by having "maxWidth" being an absolute value - to avoid 500 pixel wide healthbars on bigger resultions etc.
Same then for "minWidth" to avoid unreadable garbage.

You will end up with something like this:

[healthbar-object][........dynamicportion.......][otherobject][...nextdynamicportion...][thirdobject]

Each of this objects could have a minWidth/maxWidth/... so other objects could align properly.


Another option (done years ago): design your game for a specific aspect ratio - and on other resultion try to scale them up (using virtual resolution - available in blitzmax). Either on "left + right" or on "top + bottom" you then have to add black bars - or additional decoration.


If all your elements are in one of the 4 corners, you could also place them easily this way (oX = objectOffsetX, oY = objectOffsetY)

topLeft: 0 + oX, 0 + oY
topRight: GraphicsWidth() - objectWidth + oX, 0 + oY
bottomLeft: 0 + oX, GraphicsHeight() - objectHeight + oY
bottomRight: GraphicsWidth() - objectWidth + oX, GraphicsHeight() - objectHeight + oY


But I would prefer "relative" positioning - it is the same as above with "oX,oY" being calculated values (xRelative * GraphicsWidth = xToUse).


For "UI" things might be attached to other objects - so a healthbar might be "attached with rightBottomAlignment + 10px,5px offset" to the "unit portrait"-object.
Moving that portrait will then move the healthbar too.


bye
Ron


BlitzSupport(Posted 2015) [#5]
Another possible option:

VirtualGfx


Arska(Posted 2015) [#6]
So with VirtualGfx i could design game with certain resolution? And if resolution changes it would automaticly be in right place? I don't understand virtual resolution very good. :/

Any up to date examples how virtualGFX works?


Derron(Posted 2015) [#7]
It handles coordinates for you. BUT ... it scales everything to the designed resolution.

A "relative" UI tries to keep their content "sharp". In a 3D game you do not want things to get blurry because of scaling. You want things to stay crisp and reveal more detail.

So with virtualGfx you get some kind of a canvas which you use to draw your things on (eg. 640x480) if you now play with 1024x768, things will get scaled - similar as if you set it to 640x480 and let your GPU/screen scale it up to fullscreen.

If a higher resolution means "show more" than you should not use virtualGfx.


bye
Ron


Arska(Posted 2015) [#8]
Alright. Relative positioning is way to go for me. And one thing about calculation.. I understand that i need "relative" value which i use to multiply every coordinate. I didn't fully understand how i get this value. Let's say i use 800x600 as designing resolution and all smaller than this is smaller than 1 and bigger are over 1. I am in right track?

So how i get that value from ScreenWidth and Height? (Sorry i am very bad in mathematics)

Edit:
Just something like this?
RelX# = GraphicsWidth() / 800.0
RelY# = GraphicsHeight() / 600.0

And multiply my values like: Valuex * RelX?


Derron(Posted 2015) [#9]
What you calculated is some kind of "scaling factor".

So if you have designed for 800x600 and you res would be 1600x1200 your calculation will lead to
RelX = 2.0
RelY = 2.0

Means, all of your values will be xyz * 2.0. This works for absolute position values.
The result is something similar to VirtualGfx (except that mouse coordinates are not scaled automatically).


This is of course the same as positioning things by "percents". It does not matter if I calculate 10% of Width or use some kind of reference width (80px at a graphics width of 800).

Some prefer percentages, others might better visualize things in their head using absolute numbers.

"relative" values ease some calculations.
Imagine you want to move your object from left to right.
In your case you have to move from "0 to designatedWidth" (eg. 0 until 800). At 67% of the route the movement should try to get faster and faster .... (acceleration). so what was 67% of 800 ... ah ok there was my calculator ... hmm I just write "0.67*800".

If you use relative values instead you just have to use values between 0.0 and 1.0 and your acceleration starts at "0.67". Of course the calculation of the absolute value will happen somewhere in another function (eg. on render) but it might keep your logic lines a bit more short / more readable.


I do not want to convince you of using "relative" - both have benefits.


bye
Ron


Arska(Posted 2015) [#10]
I also tried this, but i got some black area around drawing and everything gets very very small. http://www.blitzmax.com/codearcs/codearcs.php?code=2879


Derron(Posted 2015) [#11]
you get black borders : on top + bottom OR left + right - depending on YOUR resolution and the DESIGNED resolution.

designed resolution is the one you use for layouting everything.
real resolution is the one you use to create the graphical context (like with "graphics 800,600".


Just do it similar to the "demo" provided in the archive entry.

Does it happen with the "demo code" too? In that case there might be a bug with your computer and the virtual resolution code of blitzmax ...


bye
Ron


Arska(Posted 2015) [#12]
Ah... i found problem in my own code. Everything looks now good. Expect mouse cursor seems to be in wrong place. Cursor can't reach every position before real cursor comes out from the window.

Edit:
Nevermind didn't notice virtual mouse position


Arska(Posted 2015) [#13]
Yes! Finally i got it working, but even in example code of VirtualResolution i can't get it stretched and i have 2 black bars.

Edit: And it's not working with higher resolutions. How do i use SetOrigin with VirtualResolution?

Everything works fine in windowed mode and 1024x768 fullscreen if setorigin is VirtualWidth / 2 X VirtualHeight / 2, but my native 1366x768 is not working. (Everything is in wrong position and black bars over images and text) My native resolution works just fine in example (With black bars), but not in my project, so i think problem is setorigin.


Arska(Posted 2015) [#14]
1366x768 resolution:



Arska(Posted 2015) [#15]
Well... This is very random. Sometimes 1024x768 works and sometimes it won't...


Arska(Posted 2015) [#16]
Looks like it's working now.. I was using those old functions...


Arska(Posted 2015) [#17]
One more thing! Looks like that virtual resolution stretches my images width. Any way to prevent this? Aspect ratio i think?


Derron(Posted 2015) [#18]
virtualGFX does not "stretch" in only one direction. It scales. So if you "stretch" then there is surely something in your code not the way it should be (relying on "GraphicsWidth()" instead of the value virtualGFX gives back)


bye
Ron