Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / [Tutorial] Setting up the display for multiple devices (Percentage system)

Author
Message
Scraggle
Moderator
20
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 1st Mar 2020 18:54 Edited at: 7th Dec 2021 10:19
If you have come here looking for a ‘magic-wand’ that will make your game appear correctly no matter what display it is being run on, then you are out of luck. There is no magic-wand. But that doesn’t mean it can't be done – it can. But only if you are willing to put in the effort.

Setting up the display for your game is one of the first things you do but knowing how to set it up is not quite as straight forward as you might like.
If you are developing a game that only you will play then you can use SetVirtualResolution() and set the dimensions to that of you device. No problem there (until you change device).
However, if you are developing your game with the idea of putting it on-line for anyone to download, you have no idea what size screen they will use or what the aspect ratio that screen will be. You can still use SetVirtualResolution() and choose whatever dimensions you want but if the game is run on a device with different dimensions then AppGameKit will place black bars around the display, which is pretty ugly!

So, what can you do?

Your first though might be to go with the Percentage System instead of Virtual Resolution but that too comes with problems. You will need to choose an aspect ratio with SetDisplayAspect() for the display and if the game is run on a device with a different aspect ratio, then the image will stretch. That can be even more ugly than the black bars that come with Virtual Resolution.

Below is a solution that will provide a correct display regardless of whether you are using Percentage or Virtual resolution because in reality, they are exactly the same! At least they are when you use them in the way described here.

To set up the game using virtual resolution:

To set up the game using the percentage system:

Whilst developing your game on your desktop or laptop computer, you can simulate any size device by calling the SetWindowSize() command. With the dimensions of the device you want to simulate. If you want to simulate running the device on a standard HD screen then SetWindowSize(1920, 1080, 0) will show how it looks on that sized device. If you want to see how it looks an an iPad then simply change the dimensions to those of the iPad.
Later in the tutorial, I will demonstrate how to produce a display that is unique for each device but for now we’ll concentrate on simply getting display set up.

It doesn’t matter if you have chosen the virtual or percentage set-up because, as I said above, they produce exactly the same result. You will get a square display that is 100 x 100 ‘units’. Personally, I prefer to think in percentage terms because it is easier to get my head around that knowing that my screen is 100 x 100.

But it’s square!
Nobody has a square device. That’s why we used the SetScissor() Command will all parameters zeroed. That means AppGameKit expands its usage to fit the display size, so that you, the developer, can draw outside of the 100 x 100 ‘screen’.
In order to do that we have the commands:
GetScreenBoundsLeft()
GetScreenBoundsRight()
GetScreenBoundsTop()
GetScreenBoundsBottom()


A picture demonstrates what that means much better than words:.

The red square is our 100 x 100 'screen'.
Above we are simulating the device in Landscape mode which fits our square display to the top and bottom of the screen and centred across it. If we are in portrait mode the display would fit left and right and be centred vertically.

Here’s some code which demonstrates the above image:



In the next installment, we will cover loading and sizing sprites and placing them in the correct position.
Then finally we will create a system that will provide unique displays depending on the device. Like this:

16:9 HD screen:


4:3 iPad
Scraggle
Moderator
20
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 5th Mar 2020 17:09 Edited at: 6th Mar 2020 06:42
Part 2
Setting the device size.


We have set the display to 100 x 100 with an aspect ratio of 1. Whether you chose to do that with SetVirtualResolution(100, 100) or SetDisplayAspect(1) is irrelevant. They both produce the same result. The next step is to simulate the device size.
That is easy, all we have to do there is call SetWindowSize(width, height)
However, that means we need to hardcode for a specific device size and if we want to change that to see how the game looks on a different sized device, then we need to hardcode some other values.
My preferred method is to have a ‘debug’ menu at the start of the game which allows us to choose the device size. However, when I first started using that method I quickly got fed up of having to choose. So what I now do, and what I propose for you, is to save the display settings and choose those each time we run the game. If we want to change them, then hold shift at the start of the game and the debug menu pops up allow us to choose the device size
That sounds a lot more complex than it is. It’s actually very simply to implement and the code for it is below.

Throughout the code we’ll often need to refer to the edges of the devices screen. We’ll also need to know the width and height of it.
We’ve already established that the edges can be found with:
GetScreenBoundsLeft()
GetScreenBoundsRight()
GetScreenBoundsTop()
GetScreenBoundsBottom()


And therefore the width can be found with GetScreenBoundsRight() - GetScreenBoundsLeft()
And the height with GetScreenBoundsBottom() - GetScreenBoundsTop()
But that is a lot to type each time you need it so you might want to simplify that with a UDT. You will also be using this UDT later when we define other areas of the display.

You'll also need some code to establish the bounds. It's all in the project below but here's a taster:

I’ve called it tBounds t to signify that it is a ‘type’ and Bounds because we are defining a bounding area. As I said above, this is not just for the full display, you’ll be adding other bounds areas later.
We can set the bounds for the display by calling SetBounds() with the four GetScreenBounds…() parameters:


For now, let’s get on with getting sprites on screen.

Loading sprites, setting them to the correct size and positioning them correctly

For this part, a video would be much easier to follow, and I had very nearly finished putting one together when my cat knocked my laptop onto the floor. It mostly works but video playback and recording is now very jittery, so I’ll try it with images instead (cats are dicks!):

The first thing we need to do is decide how we want things to look.
For this example, I have a background screen and four GUI elements as shown in the screenshot below. What I will demonstrate is how to determine the size and location of each element so that it appears correct on all devices.


The first thing to note is that your background image is going to stretch. If you use a full screen image for your background there is nothing you can do about that. But there are solutions. You can either use an image that can stretch without being detrimental or in the case above we could split the image up and have the AppGameKit ‘circle’ separate to the fire so that the logo remains a perfect circle and the fire stretches. But for this example, we’ll just let the background image distort to fit.

You’ll need an image editor of some kind in-order to follow along from here. I use Photoshop but any editor would work as long as you can determine the size and position of each element in the image.
The first thing to do is establish a canvas size. That is the simulated size of the device but it only has to be a close approximation so that you get an idea of how it looks because (obviously) we don’t know the size of device it will ultimately be run on. You will also need to do some calculations too so making the canvas a reasonable size will make things a lot easier. I use 1000 x 500. It is a 2:1 (or 18:9) aspect ratio which is the same as a Google Pixel but making it 1000 x 500 makes thing a lot easier as you are about to see.

Step one is to open your image editor and create a new project at the size of your choice – I strongly recommend 1000 x 500 but you can go with 1920 x 1080 if you really want to.
Then place you GUI elements where you want them and resize them so that they look correct on this size ‘screen’.
If you are using Photoshop, open the ‘Properties’ window and ensure you have the Green box selected in the ‘Layer’ window. You will then see the position and dimensions of the image.
If you’re using some other image editor then you’ll have to figure out where to find these details yourself.


In my case it is positioned at 21 across and 11 down, with a width of 168 pixels and a height of 47.
Now we need to know what those dimension are relative to the size of the display and that is why 1000 x 500 makes things much easier!
You can get your calculator out if you prefer but 168/1000 = 0.168 so that is the value we will use for width. Height is slight trickier because it’s 500 pixels, 47/500 = 0.094.
We then take those two values and multiply them by the unknown size of our display. It’s unknown because we don’t know the size of the display that it will be running on but we do know how to find it. We stored the values in display.w and display.h. Therefore, the size of the sprite is:
SetSpriteSize(greenBox, display.w * 0.168, display.h * 0.094)
To set the position of the sprite, it’s a very similar process but with the addition of an offset. We get the values again from our image editor. In this case 21 pixels across and 11 down. So, again we multiply by the size of the display but this time we need to add the edge of the display.
0.011 * display.w + display.l
If we don’t add display.l then the sprite will be positioned at zero on the x axis, and we established earlier that zero is not at the edge of the screen.
The same with Y:
0.021 * display.h + display.t
So: SetSpritePosition(greenBox, 0.011 * display.w + display.l, 0.021 * display.h + display.t)

Then go through the same process for each of the elements. I won’t do that now, you can see that in the final code below.

if you download and run the code below, then the first time you run it you will get the debug menu that asks what dimension you want to simulate. If you want to change it after that you will need to hold sown the SHIFT key just after the program starts to run.

Next time we'll look at having different displays for different devices and orientations.

Attachments

Login to view attachments
Mesher
User Banned
Posted: 16th Mar 2020 20:09
Thanks Scraggle, an excellent very informative and important piece of learning here to all that will require it, which im sure everyone will in time..

Thanks for your time an energy writing this up..

Login to post a reply

Server time is: 2024-04-20 10:29:20
Your offset time is: 2024-04-20 10:29:20