Widescreen + GUI = :(

Blitz3D Forums/Blitz3D Programming/Widescreen + GUI = :(

Dock(Posted 2005) [#1]
I have a widescreen monitor on one of my computers which has lead me to be a lot more widescreen-concious with my coding. :) I'm trying to make sure my game works perfectly in 16:9, 4:3 and also fake 16:9 (640x480 stretched into widescreen format, similar to how it is done on PS2 etc).

My problem lies with my GUI!

I'm using Shawn Swift's excellent GUI system, and so far I've been really happy with it. However, it treats the whole screen as though it were 640x480, irrespective of resolution.

Can anyone think of any ways I could work with this to cope with widescreen formats so that my GUI and text isn't stretched and fat on those displays even when the game is not? My circle buttons are oval now!

One way that springs to mind is to force the GUI system to use the centre 640 width only, but I'm not certain how that could be done.

Any ideas? How have other people done their GUI for widescreen displays?


BlackJumper(Posted 2005) [#2]
The fact is that widescreen is differnt from standard, so you need to think in terms of placement of items relative to fixed points on the screen...

I was coding a GUI with nSprite and each item was placed in relation to the top/bottom + left/right corners, so that no matter what resolution you use, the elements will appear in the correct place. {You could also work with midpoints, etc.}

... depending on the type of game it might work or just look strange.

Depending on how the pixel-perfect stuff is being achieved, you could simply scale each item (of the GUI) in the horizontal direction to avoid your stretched look


sswift(Posted 2005) [#3]
The solution is to have two sizes/positions for your HUD objects, one for the normal screen, and one for the widescreen.

The 640x480 is getting stretched horizontally in the widescreen mode, so you just need to imagine that that wide screen is 640 pixels wide, and change the width of your objects appropriately.

I've been trying to find an easy solution for this for you, and I've found that widescreen resolutions are totally screwed up!

The screen is supposed to be 16:9.

640x480 is 4:3. That means if you divide 640x480 by 4 and 3, you get 160 for both. That means that 640x480 is a square pixel resolution on a 4:3 screen.

But all these widescreens I see are 1280x768 and 1920x1200.

So for 16:9, 1280 / 16 = 80 and 80 * 9 = 720. So the screen resolution should be 1280x720! And instead of 1920x1200 it should be 1920x1080!

But I think I've calculated it out. You need to multiply the width of all your HUD elements by 0.75 exactly when in widescreen mode to un-stretch a 4:3 ratio image displaued on a 16:9 screen.

Then you just need to figure out where you want to position them when in that mode.

If you want to center a 4:3 hud in the widescreen, you could do the above to get their scale right, and then multiply their positions by 0.75 and then add N to the X value to offset the now 4:3 ratio positions to the center of the screen. I am not sure what N is. It might be 640*0.25/2 or something.

Anyway, fixing it is all just a matter of you keeping track of whether the user is in a widescreen mode or not and changing the scales and positions appropriately.


Dock(Posted 2005) [#4]
Thanks for the help guys. I've had some success with passing a width variable through my GUI stuff which multiplies by 0.8 for 16:9 HUD (though I'll make this variable for whatever strange widescreens people have - 1280x768? weird!)

The only problem I seem to be having still is the text, which seems much more complicated. I can't seem to find the part that makes the proper 3D single surface object. Any ideas?


sswift(Posted 2005) [#5]
Dock:
You don't need to make it variable for different resolutions.

The HUD renders like a 3d game, so as long as the screen is the right aspect ratio, no matter what the resolution is, and whether the pixels are square or not, it will render properly.


The function that creates the text meshes is at the bottom of the library:

Function INTERNAL_CreateTextMesh(ThisFont.GUI_Font, TextString$, CenterX=False, CenterY=False, Wrap_Width#=65535, Mesh=0, Kerning#=0.05)


You'll probably have to add your multiplier to all the spots where you see an addvertex.

As for that multiplier, are you sure 0.8 is correct, because my calculations indicated that 0.75 is the right value to use.

To scale 16:9 to 4:3 you do the following:
First, scale the 16:9 to fit the 4:3 vertically.

3/9 = 0.3333
16*0.3333 = 5.3333

So that means that a 16:9 screen scaled in both directions to fit a 4:3 screen vertically, will have a width of 5.3333.

Divide 5.333 by 4, and we see that a 16:9 screen is 1.33 times the width of a 4:3 screen. And divide 4 by 5.333 and we get 0.75, which should be what you have to multiply the width of a 16:9 screen by to get it to fit a 4:3 screen horizontally. Of course, that gives me a result of 1440x1200 if scaling a 1920x1200 down to 4:3, which is wrong. But 0.8 is also wrong, giving a result of 1536. The result we want is 1600. But 1920x1200 is not actually a square pixel mode on a widescreen lcd. So perhaps 0.8 is right, but I don't know how to arrive at that result.

To get 1600x1200 from 1920x1200, you need to multiply by 0.833333
To get 1024x768 from 1280x768 you need to multiply by 0.8

Which is what you got. But as I showed in my first post, 1280x768 is not a true 16:9 resolution. 1280x720 is.

Hm...

To get 1280x960 from 1280x720, you need to multiply by 1.33 for the vertical. Multiplying both gives you 1706.6666667x960, which is a wide screen res with square pixels with a height of 960. So going from there, you get... 0.75 to go from 1706 wide to 1280 wide.

So it would appear that 0.75 is the correct value to multiply by, if your goal is to keep your circles round.


Dock(Posted 2005) [#6]
Ah yeah - 0.75 is right, my bad.
(4/3)/(16/9)=0.75

I'll let you know how I get on with fixing the textbox widths. Thanks!


Dock(Posted 2005) [#7]
Excellent, I cracked it! :)

Shawn, you may or may not want to add this addition to your code.

; start widescreen setup
If Lower(fakewidescreen)="yes" Then ScaleEntity cam,1.25,1,1  ; stretch viewport for 'fake widescreen'
Global GUIpixel# = 1 ; setup gui squishing for widescreen
If Lower(fakewidescreen)="yes" Then GUIpixel = 0.75   ; define 0.75 width for GUI widescreen
If Float(screenwidth)/Float(screenheight)>1.4 Then GUIpixel = 0.75  ; define 0.75 width for GUI widescreen
This is where I setup my widescreen width. I have 'fake widescreen' which is basically anamorphic output, as well as proper widescreen. Stupidly, I had no idea that I needed to add 'Float' to each number I divided by, so that gave me some trouble... I've never needed that before.

CW# = ThisFont\Character_Width#[ThisChar]*GUIpixel
The '*GUIpixel' is the only part I added to the sswift code. I also added the same thing to all sections that call GUI_CreateSprite in my own code, which was a pretty easy way to handle it. This does the job really nicely. I changed some of my alignment to work by centre instead of left side, and it works okay now.


sswift(Posted 2005) [#8]
Glad to hear you got it working. :-)


Dock(Posted 2005) [#9]
P.S. there isn't a line return character in your GUI is there, for text boxes? As the centered+fixed width is a bit broken, I could use a line return for multi-line centre text.


sswift(Posted 2005) [#10]
chr$(13) is carraige return.

Centered and fixed width broken? What fixed width? If you want fixed width, you need to make all the letters the same width, or alter the function. It assumes variable width. You might also have to change something to make the spaces the same width as well.


Dock(Posted 2005) [#11]
Thanks for the carriage return!

By fixed width I actually meant when you define a width for wrapping text. The example in the top-left of your demo. It works with left aligned text, but goes screwy with centered text - shifting all over the place depending upon the width you specify.

So, yes... there's no way to do a wrapping text box with centered text.

edit: ah, carriage return doesn't fix my problem either. I suppose if I want something centered I'll have to keep it single line. :/


N(Posted 2005) [#12]
Just in case you want more widescreen resolutions, my laptop runs at 1440x900, and I've also heard of cases where some widescreen laptops will use 1400x990 (what the heck?).

Just thought I'd mention that.


sswift(Posted 2005) [#13]
Dock:
Make a demo of this "shifting" if you would so I can see it for myself. There probably is no easy way to fix it, but I can check at least if I have a demo.

Noodle:
Hm...

1440/16 = 90, 900/9 = 100
1400/16 = 87.5, 990/9 = 110

Neither therefore is a square pixel resolution, but the first one is closer.

I don't know why these manufacturers didn't go with resolutions like 1600x900, 2400x1350, and 3200x1800, which would all be 16:9 exactly.