Python 如何确定奇维游戏的纵横比?

Python 如何确定奇维游戏的纵横比?,python,layout,resize,kivy,aspect-ratio,Python,Layout,Resize,Kivy,Aspect Ratio,我已经开始和Kivy一起玩了,但我对这一切都很陌生,而且已经很挣扎了 我正在尝试制作一个棋盘游戏-我希望窗口可以调整大小,但我不希望调整窗口大小会弄乱游戏的纵横比(因此,换句话说,如果窗口的大小不是预期的内容纵横比,我希望窗口在内容上方或两侧有黑色条) 我能看到的确保这一点的最简单方法是: a) 锁定窗口本身的纵横比,使其始终为10:9(板和所有屏幕元素的纵横比)-即使在全屏显示时也是如此 或 b) 使用某种小部件/表面/布局,以窗口为中心,高宽比锁定为10:9。随后,我将其用作放置所有其他图像

我已经开始和Kivy一起玩了,但我对这一切都很陌生,而且已经很挣扎了

我正在尝试制作一个棋盘游戏-我希望窗口可以调整大小,但我不希望调整窗口大小会弄乱游戏的纵横比(因此,换句话说,如果窗口的大小不是预期的内容纵横比,我希望窗口在内容上方或两侧有黑色条)

我能看到的确保这一点的最简单方法是:

a) 锁定窗口本身的纵横比,使其始终为10:9(板和所有屏幕元素的纵横比)-即使在全屏显示时也是如此

b) 使用某种小部件/表面/布局,以窗口为中心,高宽比锁定为10:9。随后,我将其用作放置所有其他图像、小部件、网格等的基础

然而,我真的不知道如何做这些。我不确定是否可以锁定窗口纵横比,我找到的唯一一个可以锁定纵横比的kivy特定对象是kivy.graphics.image。。。我似乎无法将其作为我其他东西的“基础”

编辑:到目前为止,我已经写了下面的代码:它创建了一个布局(并将其稍微涂成红色),每当调整其大小时,“修复”其自身的纵横比。但是,它仍然没有在窗口中居中,而且更麻烦的是,它会导致一个无休止的循环(可能是因为方面修复代码更正了大小,但是kivy将其大小“更正”回窗口大小,再次触发方面修复,我想我可能错了)

编辑:再次修改代码,但仍然是一个无休止的循环。我认为只向家长咨询尺码信息可以解决这个问题,但显然不行

如果有人帮我修改代码,我将不胜感激

代码如下:

test.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import (ObjectProperty,
                             NumericProperty,
                             ReferenceListProperty)
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle

class Board(AnchorLayout):
    pass

class BackgroundLayout(RelativeLayout):
    def FixAspectRatio(self, *args):
        correctedsize = self.parent.size
        if correctedsize[0] > correctedsize[1]*(10/9):
            correctedsize[0] = correctedsize[1]*(10/9)
        elif correctedsize[0] < correctedsize[1]*(10/9):
            correctedsize[1] = correctedsize[0]/(10/9)
        return correctedsize

class test(App):
    game = ObjectProperty(None)

    def build(self):
        self.game = Board()
        return self.game

if __name__ == '__main__':
    test().run()
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import (ObjectProperty,
                             NumericProperty,
                             ReferenceListProperty,
                             ListProperty)
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle

class Game(FloatLayout):
    pass

class Background(Image):
    offset = ListProperty()
    magnification = NumericProperty(0)


class Bounds(RelativeLayout):
    pass

class test(App):
    game = ObjectProperty(None)

    def build(self):
        self.game = Game()
        return self.game

if __name__ == '__main__':
    test().run()
从kivy.app导入应用
从kivy.uix.widget导入widget
从kivy.uix.image导入图像
从kivy.uix.anchorlayout导入anchorlayout
从kivy.uix.floatlayout导入floatlayout
从kivy.uix.relativelayout导入relativelayout
从kivy.properties导入(ObjectProperty,
数字属性,
ReferenceListProperty)
从kivy.graphics.context\u说明导入颜色
从kivy.graphics.vertex\u指令导入矩形
课程板(主播布局):
通过
课程背景布局(相对位置):
def FIXASPECTRACTIO(自身,*参数):
correctedsize=self.parent.size
如果correctedsize[0]>correctedsize[1]*(10/9):
correctedsize[0]=correctedsize[1]*(10/9)
elif correctedsize[0]
测试.kv

<Board>
    BackgroundLayout:
        canvas.before:
            Color:
                rgba: 1, 0, 0, 0.5
            Rectangle:
                size: self.size
                pos: self.pos
        size: self.FixAspectRatio(self.parent.size)
        pos: self.parent.pos
<Game>
    Background:
        id: BackgroundId
        #Provide the image that will form the aspect-locked bounds of the
        #game.  Image widgets have aspect_lock set to True by default.
        source: 'gamebounds.png'
        #All the image to stretch to fill the available window space.
        allow_stretch: True
        size: self.parent.size
        #Find the coordinates of the bottom-left corner of the image from
        #the bottom-left corner of the window.  Call this the 'offset'.
        offset: [self.center_x - (self.norm_image_size[0]/2),
        self.center_y - (self.norm_image_size[1]/2)]
        #Find out the factor by which the image is magnified/shrunk from
        #its 'default' value:
        magnification: self.norm_image_size[0] / self.texture_size[0]

        Bounds:
            #The canvas below isn't needed, it's just used to show the 
            #position of the RelativeLayout
            canvas:
                Color:
                    rgba: 1, 0, 0, 0.5
                Rectangle:
                    size: self.size
                    pos: (0, 0)
            #Set the position of the RelativeLayout so it starts at the
            #bottom left of the image
            pos: self.parent.offset
            #Set the size of the RelativeLayout to be equal to the size of
            #the image in Background
            size: self.parent.norm_image_size

背景布局:
在以下情况之前:
颜色:
rgba:1,0,0,0.5
矩形:
大小:self.size
pos:self.pos
大小:self.FixAspectRatio(self.parent.size)
pos:self.parent.pos

一种方法是创建一个布局,在给定纵横比的情况下,总是最大化子级。下面是一个例子:

from kivy.lang import Builder
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import NumericProperty

kv = """
ARLayout:
    Widget:
        canvas:
            Color:
                rgb: 1, 0, 0
            Rectangle:
                size: self.size
                pos: self.pos
"""

class ARLayout(RelativeLayout):
    # maximize the children given the ratio
    ratio = NumericProperty(10 / 9.)

    def do_layout(self, *args):
        for child in self.children:
            self.apply_ratio(child)
        super(ARLayout, self).do_layout()

    def apply_ratio(self, child):
        # ensure the child don't have specification we don't want
        child.size_hint = None, None
        child.pos_hint = {"center_x": .5, "center_y": .5}

        # calculate the new size, ensure one axis doesn't go out of the bounds
        w, h = self.size
        h2 = w * self.ratio
        if h2 > self.height:
            w = h / self.ratio
        else:
            h = h2
        child.size = w, h


class TestApp(App):
    def build(self):
        return Builder.load_string(kv)

TestApp().run()

在kivy聊天中,kived提供了很多帮助,我终于找到了一个令我满意的解决方案

下面以“背景”图像为基础确定游戏边界,然后在此背景图像上放置相对布局。对于所有后续子对象,坐标(0,0)将引用(方向锁定)背景图像的左下角,并且他们可以使用背景的“放大”属性根据屏幕大小调整其大小/位置

提供任何gamebounds.png图像,下面的代码将实现这一点。请注意,RelativeLayout以红色着色(透明度为50%)仅显示其位置(并显示它始终与gamebounds.png图像大小和位置匹配):

test.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import (ObjectProperty,
                             NumericProperty,
                             ReferenceListProperty)
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle

class Board(AnchorLayout):
    pass

class BackgroundLayout(RelativeLayout):
    def FixAspectRatio(self, *args):
        correctedsize = self.parent.size
        if correctedsize[0] > correctedsize[1]*(10/9):
            correctedsize[0] = correctedsize[1]*(10/9)
        elif correctedsize[0] < correctedsize[1]*(10/9):
            correctedsize[1] = correctedsize[0]/(10/9)
        return correctedsize

class test(App):
    game = ObjectProperty(None)

    def build(self):
        self.game = Board()
        return self.game

if __name__ == '__main__':
    test().run()
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import (ObjectProperty,
                             NumericProperty,
                             ReferenceListProperty,
                             ListProperty)
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle

class Game(FloatLayout):
    pass

class Background(Image):
    offset = ListProperty()
    magnification = NumericProperty(0)


class Bounds(RelativeLayout):
    pass

class test(App):
    game = ObjectProperty(None)

    def build(self):
        self.game = Game()
        return self.game

if __name__ == '__main__':
    test().run()
测试.kv

<Board>
    BackgroundLayout:
        canvas.before:
            Color:
                rgba: 1, 0, 0, 0.5
            Rectangle:
                size: self.size
                pos: self.pos
        size: self.FixAspectRatio(self.parent.size)
        pos: self.parent.pos
<Game>
    Background:
        id: BackgroundId
        #Provide the image that will form the aspect-locked bounds of the
        #game.  Image widgets have aspect_lock set to True by default.
        source: 'gamebounds.png'
        #All the image to stretch to fill the available window space.
        allow_stretch: True
        size: self.parent.size
        #Find the coordinates of the bottom-left corner of the image from
        #the bottom-left corner of the window.  Call this the 'offset'.
        offset: [self.center_x - (self.norm_image_size[0]/2),
        self.center_y - (self.norm_image_size[1]/2)]
        #Find out the factor by which the image is magnified/shrunk from
        #its 'default' value:
        magnification: self.norm_image_size[0] / self.texture_size[0]

        Bounds:
            #The canvas below isn't needed, it's just used to show the 
            #position of the RelativeLayout
            canvas:
                Color:
                    rgba: 1, 0, 0, 0.5
                Rectangle:
                    size: self.size
                    pos: (0, 0)
            #Set the position of the RelativeLayout so it starts at the
            #bottom left of the image
            pos: self.parent.offset
            #Set the size of the RelativeLayout to be equal to the size of
            #the image in Background
            size: self.parent.norm_image_size

背景:
id:背景id
#提供将形成图像的纵横比锁定边界的图像
#游戏。默认情况下,图像小部件的aspect_lock设置为True。
来源:“gamebounds.png”
#要拉伸以填充可用窗口空间的所有图像。
允许拉伸:真
大小:self.parent.size
#从中查找图像左下角的坐标
#窗口的左下角。称之为“偏移量”。
偏移量:[self.center\u x-(self.norm\u图像大小[0]/2],
self.center\u y-(self.norm\u图像大小[1]/2)]
#找出放大/缩小图像的因素
#其“默认”值:
放大率:self.norm\u图像大小[0]/self.texture\u大小[0]
界限:
#下面的画布不需要,它只是用来显示
#相对位置
画布:
颜色:
rgba:1,0,0,0.5
矩形:
大小:self.size
位置:(0,0)
#设置RelativeLayout的位置,使其从
#图像的左下角
位置:self.parent.offset
#将RelativeLayout的大小设置为等于
#背景中的图像
大小:self.parent.norm\u图像大小