Resolution scaling for HUD/GUI?

Is there an easy way to scale images for different screen resolution? Or do I have to set it up by hand?



Right now I’m running the game in 1280x720 and things are fine (except for XML preview since it uses 640x480), but later on I’ll add different screen resolutions. So naturally I’m pondering the best way to handle the HUD based on resolution.



For now the “HUD” is an image overlayed over the main screen. There will be many areas (sort of panels) on the screen animated depending on user actions. But as you can imagine, scaling is different for each resolution.



Now, I can take the easy way and make a HUD for each resolution, but that’d be bad. Too many images handling/packing. I would much prefer using a full screen version that can be scaled down to match the running resolution. But as you can imagine, everything goes wacky when I do that.



As you can see in the image below (the alignment is wrong, I know), I have two “panels” on the lower right on the screen. Those will show things to the user depending on certain action. For example, the bottom panel will “flip” upon selecting a star in the view and show the star with a button or two to display the star’s characteristics and other information. But, pixel numbers to properly align elements will be different depending on resolution.



So, what would be your take on this? Is there an “easy” facility to make that happening? I’m guessing here I’ll have to do everything by hand depending on the chosen resolution.



http://www.danyrioux.com/files/hud.png

Yes, afaik the image sizes are not adapted by nifty. If you use the themes correctly however, window bars and such should be scaled somehow (I might be wrong tho)

Hmm,

I don’t know if I’ve really understood the question but if you use attributes like width="20%"height=“100%”, it will automaticly scale with the resolution I think.



There are different way for rescaling images inside nifty. Check this link



The “resize:” option is powerfull.

In your example, you can have :

  • Your blue frame around the window with a thickness not depending on resolution
  • The right panel depending on the resolution.



    Here is a little example of how you will have to implement it :

    [xml]

    |layer id=“frameLayer” childLayout=“center” height=“100%” width=“100%” |

    |panel height=“100%” width=“100%” align=“center” valign=“center” childLayout=“center” visibleToMouse=“true”|

    |image id=“frameImage” height=“100%” width=“100%” filename=“frame.png” imageMode=“resize:20,160,20,20,20,160,20,60,20,160,20,20” /|

    |/panel|

    |/layer|



    |layer id=“rightPanelLayer” childLayout=“center” height=“100%” width=“100%” |

    |panel height=“100%” width=“20%” align=“right” valign=“center” childLayout=“center” visibleToMouse=“true”|

    |image id=“rightPanelImage” height=“100%” width=“100%” filename=“rightPanel.png” imageMode=“normal” /|

    |/panel|

    |/layer|

    [/xml]

    I will let you read the link for understanding how “resize:20,160,20,20,20,160,20,60,20,160,20,20” works :slight_smile:

Thanks for your opinion didialchichi.



The only problem here is the padding. Of course there’s an alternate solution, but again, it’s not favorable to memory management. ie: I could make those panels using same size as the border but with everything else but the panel itself in the alpha channel, thus having 100% transparency and unseen. But I don’t like this.



At some places I have to make padding, 1px, 3px, etc and there’s no way I can use a percentage to indicate that to scale properly (1% of 1280 is 13px) and AFAIK, we can’t use fractions of percentages (0.5% or whatever. I never tried though).



I’m sorry if my original post might have sounded confusing a bit. I’m doing a lot of wondering “aloud” in here. :wink: My musing was about if there was an internal way that Nifty handled resolutions. So by, let’s say, if I set things up at a certain resolution, it would, by itself, adapt to other resolution. Even though I had a pretty good idea that it didn’t, It’s never a bad idea to confer with other people. There are so many people in here to know so much about how things work that not asking it would be a sin.



So, as I imagined I will have to implement the whole HUD based on the current resolution.

Well, that’s what I thought. I didn’t understand the question :slight_smile:



I think it’s to deep inside Nifty for me to fully understand your problem.

When I was watching the tracker earlier, I found something about switching resolution and the RenderDevice behavior.

I don’t know if it might help : here

Don’t sweat it. It’s sometimes hard to follow my train of thoughts. Even I sometimes have a hard time. :wink:



As for the link I have read it some time ago, but that’s easily solvable by closing the screen and redrawing it all by hand. Although I admit it would be preferable if it could be done using a simple method. But that’s the price we have to pay to play with bleeding edge technology. Our brains bleed but we like it. :wink:

I have a solution, still its not perfect!

You have to call the method before you load the nifty scene and you are not allowed to use % positions (because my code assumes, that all children have x and y coordinates)

Widescreen and Non-Widescreen is included



[java]public void resize(Element element){

for(int i = 0; i < element.getElements().size();i++){

Element child = element.getElements().get(i);

//System.out.println(child + " " + child.getElementType());



if(-1 < child.getElementType().toString().indexOf(“de.lessvoid.nifty.loaderv2.types.ImageType”)){



int widescreen = (int)((float)Xero.APPLICATION.getCamera().getWidth()/Xero.APPLICATION.getCamera().getHeight()*100);

if(widescreen != 133){

int width = 1440;

int height = 900;



double scalew =(double)width/Xero.APPLICATION.getCamera().getWidth();

double scaleh =(double)height/Xero.APPLICATION.getCamera().getHeight();



child.setConstraintWidth(new SizeValue((int)Math.round((double)getValue(child.getConstraintWidth().toString())/scalew) + “px”));

child.setConstraintHeight(new SizeValue((int)Math.round((double)getValue(child.getConstraintHeight().toString())/scaleh) + “px”));



child.setConstraintX(new SizeValue((int)Math.round((double)getValue(child.getConstraintX().toString())/scalew) + “px”));

child.setConstraintY(new SizeValue((int)Math.round((double)getValue(child.getConstraintY().toString())/scaleh) + “px”));

}

else{

int width = 1200;

int height = 900;



double scalew =(double)width/Xero.APPLICATION.getCamera().getWidth();

double scaleh =(double)height/Xero.APPLICATION.getCamera().getHeight();



child.setConstraintX(new SizeValue((int)Math.round((double)(getValue(child.getConstraintX().toString())-120)/scalew) + “px”));

child.setConstraintY(new SizeValue((int)Math.round((double)getValue(child.getConstraintY().toString())/scaleh) + “px”));



child.setConstraintWidth(new SizeValue((int)Math.round((double)getValue(child.getConstraintWidth().toString())/scalew) + “px”));

child.setConstraintHeight(new SizeValue((int)Math.round((double)getValue(child.getConstraintHeight().toString())/scaleh) + “px”));

}

}

if(child.getElements().size() != 0){

resize(child);

}

}

}[/java]

Well, you could always use %. You can get the pixels from the camera’s width and height and use the percentage of that value.



What worries me though it the rounding. One pixel can make a difference. I’m not saying it’s a big thing, but it’s there. Not too hard to fix. At that point, once it’s been tested, the image could be resized with the necessary pixel(s) to fit most resolutions, or other means could be used (like a small transparent border around the image or some other trick).



I will test this out tomorrow as it is past 4am here.



But, good going there DarkPhoenixX! :slight_smile:

Not just good going! It’s working.

If you love to use 0.7 pixel instead be my guest.



Well, you could always use %. You can get the pixels from the camera’s width and height and use the percentage of that value.

Why should I? That makes no sense!

Honest I can take critic, but complaining and making no sense is a bit much.

Do just once at a time! x3

Whoa whoa. Calm down.


DarkPhoenixX said:
Not just good going! It's working.
If you love to use 0.7 pixel instead be my guest.

I would prefer a perfect fit, yes. But if I were given a choice between not working and .7, I might take the .7 if the layout isn't breaking the visual appeal of whatever is on the screen. Barred that I'd use other, more complicated ways.

I don't know what bit you today but don't take it out on me. As for the rest, I'll let it slide. I have no inclination to fall into childish arguments with you.

Oh, don’t take me so serious, I have my own kind of humor :wink:



Ok, first 0.7 pixel is not possible, because one pixel is one diode on your screen, meaning whatever you do, you will have an error of 1px. That’s why I was sarcastic.



Second, % has a big disadvantage. First its complicate to create, since

I have to calculate the percent and create a table layer → meaning, I can’t overlay a element with another element (not the way I want),

and I have to calculate the element size too.

Even if I do all this, it wouldn’t be so exact as absolute.

Not to mention, one little change and I have to calculate again.



Hope everything is clear now!



Edit:

And killing points is not a nice way to say “thank you”.

Feels like the dog has bitten me in the hand… and with dog i didn’t mean you, I meant the thing you asked, which had bitten me!

1 Like

Let’s wipe that slate clean shall we?



I agree with pretty much all you’re saying. I don’t think it easily is doable to perfectly scale things so they are accurate at each and every resolution. That’s a granted.



As for the point, well, I’ll remove it. But I didn’t downgrade the helping post itself; only the following comment which was pretty rude when read on my side.



I do have some time right now to test things out, so I’ll do that in a bit and post back with some results.



Let’s start this again. :slight_smile: