Kivy Window Resizing Messes up Screen Formatting

Started by
5 comments, last by Rutin 6 years, 3 months ago

I want to make it so the location and size of the buttons I use are changed to suit the background image when the screen is resized.

Here is my code so far:


"""
Combines various .py files and
allows the game to run.
"""
from kivy.app import App
from kivy.uix.image import Image
from kivy.config import Config
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout


class MainMenu(FloatLayout):
    def __init__(self, **kwargs):
        super(MainMenu, self).__init__(**kwargs)


        start_button = Button(pos=(25, 75),
                              background_normal="Start.png",
                              background_down="Start_Down.png",
                              size_hint=(.1, .1))

        load_button = Button(pos=(225, 75),
                             background_normal="Load.png",
                             background_down="Load_Down.png",
                             size_hint=(.1, .1))

        options_button = Button(pos=(425, 75),
                                background_normal="Options.png",
                                background_down="Options_Down.png",
                                size_hint=(.150, .1))

        quit_button = Button(pos=(708, 75),
                             background_normal="Quit.png",
                             background_down="Quit_Down.png",
                             size_hint=(.1, .1))

        background = Image(source="Main_Menu.png",
                           pos=(0, 0))

        self.add_widget(background)
        self.add_widget(start_button)
        self.add_widget(load_button)
        self.add_widget(options_button)
        self.add_widget(quit_button)

class BanditKing(App):
    def build(self):
        self.title = "Bandit King"
        self.icon = "Window_Icon.png"
        return MainMenu()


def main():
    Config.set("graphics", "width", "1600")
    Config.set("graphics", "height", "900")
    Config.write()
    BanditKing().run()


if __name__ == "__main__":
    main()

Here is what it should always look like.

image.thumb.png.ee5f34aa22ad187aa686a457c6a23eee.png

 

Here is what it does:

image.thumb.png.6ed34c84db53eee9623a2e9bf6e94507.png

You might be able to tell the "Options" button is slightly off line with the other buttons. I would also like to know how to fix that.

Advertisement

I don't use Python but I will give you an answer that is pretty much universal. In C++ I do this in a number of ways, and it can depend on if I have objects within their own view, which keeps buttons spaced the same, or if I create new button views with different to account for different resolutions.

Just a basic example:

Assuming your screen is 800x600 and you have two buttons, each are 210x59 and positioned at (165, 270), and (425, 270) *Top left x,y. The first buttons top left point is at the 20.625% mark of the screen (left to right), and the second button is at the 53.125% mark of the screen for the x axis. The y will be at 45%. You get this calculation by taking the x or y and dividing into the width or height of the res. ie.

BUTTON 1 -> 165/800 = 0.20625, 270/600 = 0.45

BUTTON 2 -> 425/800 = 0.53125, 270/600 = 0.45

Now that you know the position % marks, you can resize with ratios.

If your screen res changes to 1024x600 you would just re-set the position of the buttons like so:

BUTTON1.x = 1024*0.20625 equals->211.20

BUTTON1.y = 600*0.45 equals -> 270

You'll see they have the same % -> 211.20/1024 = 0.20625 * 100 = 20.625%

This however will only re-position objects to contain the same x,y ratio when working in a different resolution, this will indeed add spacing between the objects unless you resize the width and height as well. This means you either have to be working with a high res image that you can scale down within the ratios evenly, or design different graphics for those off ratios.

The same principle can be applied like the above to generate width and height ratios. Let us take the width and height of the button which is 210x59. To get the ratio we do the same as we did for x, y.

210/800 = 0.2625 -> 26.25%

59/600 = 0.0983333333333333 -> 9.833333333333333%

Now since we didn't up the height on res change the graphic height would be the same.

You would now have to change the graphic width and height as follows to maintain the same ratio.

BUTTON1.width = 1024*0.2625 equals ->268.8

BUTTON1.height = 600*0.0983333333333333 equals -> rounds to 59

So on display 1 with 800x600 we have buttons as follows:

Button1 = 210x59 and positioned at (165, 270)

Button2 = 210x59 and positioned at (425, 270)

On display 2 with 1024*600 we have the buttons as follows:

So on display 1 with 800x600 we have buttons as follows:

Button1 = 268.8x59 and positioned at (211.2, 270)

Button2 = 268.8x59 and positioned at (544, 270)

The below screen shots will show they have the same ratios - ignore the gray borders I used a screen snip it tool - screen size is the green.

image.png.a18cb34ad93574362a8e1089c466aba4.png

image.thumb.png.382a685589846149dc9dd615b279ec93.png

 

There are different methods such as using a view to draw your highest res graphics to, then scaling that view down which in turn scales all the graphics inside with the res change. You just need to account for the new width and height of your objects, especially for things like bounding box collision. You can also just make a variable which holds the ratio, and sets all your objects size based on that ratio to account for any changes. You'll only run into problems with this if you're not using even ratios when scaling because image width and height will not scale evenly.

I hope this helps, if you have more questions let me know.

Programmer and 3D Artist

Thank you!

I am still searching for how to get the window height/width while the game's running, but your post helped.

10 minutes ago, RidiculousName said:

Thank you!

I am still searching for how to get the window height/width while the game's running, but your post helped.

No problem! Like I said I don't know python or Kivy, but are you able to call something like:

currentSize = Window.size  ??

Is your screen width and height dynamic to a device? If you're dealing with just static sizes, you can always keep two variables that store the initial width and height values, and when you do a resolution change, just update it and use those variables to do ratio calculations.

Programmer and 3D Artist

I'm sure I can get it with something like that. I just haven't been able to find anything on it.

I might choose to just force the game to have one or two sizes.

1 hour ago, RidiculousName said:

I'm sure I can get it with something like that. I just haven't been able to find anything on it.

I might choose to just force the game to have one or two sizes.

This might be a good reference: https://kivy.org/docs/_modules/kivy/core/window.html

If you FIND keyword "size" you get the following:

I didn't look through everything but maybe:

 

def _set_system_size(self, size): self._size = size def _get_system_size(self): if self.softinput_mode == 'resize': return self._size[0], self._size[1] - self.keyboard_height return self._size system_size = AliasProperty( _get_system_size, _set_system_size, bind=('_size', )) '''Real size of the window ignoring rotation. .. versionadded:: 1.0.9 :attr:`system_size` is an :class:`~kivy.properties.AliasProperty`. ''' def _get_effective_size(self): '''On density=1 and non-ios displays, return system_size, else return scaled / rotated size. Used by MouseMotionEvent.update_graphics() and WindowBase.on_motion(). ''' w, h = self.system_size if platform == 'ios' or self._density != 1: w, h = self.size return w, h

I'm guessing your answer will be found in the above link.

Programmer and 3D Artist

This topic is closed to new replies.

Advertisement