Kivy GridLayout 缩放问题 - Android vs PC - 16:9 and 19:5:9 vs 4:3(1920x1080 and 1440x3120 vs 800x600)
Kivy GridLayout scaling issues - Android vs PC - 16:9 and 19:5:9 vs 4:3(1920x1080 and 1440x3120 vs 800x600)
我一直在使用 kivy
和 buildozer
制作一个 Android 贪吃蛇游戏,并且在使用不同的值、布局和方法进行多次迭代之后(以及在 Google、Whosebug 和 kivy
forums/documentation) 我已经到了我自己在这里寻求帮助的地步。
问题是这样的;
当 kivy window 为 800x600 时,网格看起来很棒,目标是矩形是完美的,甚至边正方形。 window 最大化并且 window 变成 1920x1080(16:9) 的那一刻,正方形变成宽矩形,因此不均匀。不幸的是,在我的 OnePlus 7 Pro 上试玩这款游戏,纵横比为 19:5:9,分辨率为 1440x3120,结果更加糟糕。
目前我正在使用由 Rectangle
填充的 GridLayout
来实现关卡的网格。我试过根据 Window.size
、Window.width
制作公式,我试过使用 size_hint
、size
、width
、cols_minimum
和 kivy.metrics
到目前为止没有成功。
附带说明一下,如果我试图实现的或下面代码中的任何内容可以以更好的方式完成,请告诉我。任何替代方案将不胜感激,我对 kivy
和 Python
.
都非常缺乏经验和新手
我的代码:
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
class GridCell(Widget):
color = ListProperty([1, 1, 1, 1])
size = ListProperty([0, 0])
pos = ListProperty([0, 0])
def __init__(self, size, x, y, **kwargs):
super().__init__(**kwargs)
self.color = (0.0, 0.0, 0.0, 1.0)
self.size = (size, size)
self.pos = (x, y)
class Level(GridLayout):
def __init__(self, **kwargs):
super(Level, self).__init__(**kwargs)
self.cols = 30
self.cell_size = 28
self.spacing = 2
self.positions = [(row, column) for row in range(self.cols) for column
in range(self.cols)]
self.grid_cells = {}
self.create_grid()
def create_grid(self):
for position in self.positions:
self.grid_cells[position] = GridCell(self.cell_size, *position)
self.add_widget(self.grid_cells[position])
if __name__ == '__main__':
from kivy.app import App
Builder.load_file('grid_cell.kv')
Window.clearcolor = (1.0, 1.0, 1.0, 1.0)
class LevelApp(App):
def build(self):
self.title = 'Level'
level = Level()
return level
level_app = LevelApp()
level_app.run()
grid_cell.kv:
<GridCell>:
canvas:
Color:
rgba: self.color
Rectangle:
pos: self.pos
size: self.size
请注意,您不能用方形单元格的方形网格填充非方形 window。但是,要使单元格保持正方形并将其大小基于 GridLayout
,请尝试将 GridCell
class 更改为:
class GridCell(Widget):
color = ListProperty([1, 1, 1, 1])
def __init__(self, x, y, **kwargs):
super().__init__(**kwargs)
self.color = (0.0, 0.0, 0.0, 1.0)
self.pos = (x, y)
请注意,您不需要定义 pos
和 size
属性,因为 Widget
已经有了它们,而且我已经从 [=19] 中删除了 size
=]方法。
并将Level
更改为:
class Level(GridLayout):
def __init__(self, **kwargs):
super(Level, self).__init__(**kwargs)
self.cols = 30
self.rows = 30
self.spacing = 2
self.positions = [(row, column) for row in range(self.rows) for column
in range(self.cols)]
self.grid_cells = {}
self.create_grid()
def create_grid(self):
for position in self.positions:
self.grid_cells[position] = GridCell(*position)
self.add_widget(self.grid_cells[position])
然后在你的 kv
:
<GridCell>:
grid_cols: self.parent.cols if self.parent and self.parent.cols else 1
grid_rows: self.parent.rows if self.parent and self.parent.rows else 1
tmp_size: min(self.parent.width/self.grid_cols - self.parent.spacing[0], self.parent.height/self.grid_rows - self.parent.spacing[1]) if self.parent else 0
size_hint: None, None
size: self.tmp_size, self.tmp_size
canvas:
Color:
rgba: self.color
Rectangle:
pos: self.pos
size: self.size
这会根据 GridLayout
、size
、rows
和 cols
计算 tmp_size
,并将该大小分配给 GridCell
]. kv
中的 if
语句是必需的,因为 <GridCell>
规则在 GridCell
获得其 parent
分配之前应用。
我一直在使用 kivy
和 buildozer
制作一个 Android 贪吃蛇游戏,并且在使用不同的值、布局和方法进行多次迭代之后(以及在 Google、Whosebug 和 kivy
forums/documentation) 我已经到了我自己在这里寻求帮助的地步。
问题是这样的;
当 kivy window 为 800x600 时,网格看起来很棒,目标是矩形是完美的,甚至边正方形。 window 最大化并且 window 变成 1920x1080(16:9) 的那一刻,正方形变成宽矩形,因此不均匀。不幸的是,在我的 OnePlus 7 Pro 上试玩这款游戏,纵横比为 19:5:9,分辨率为 1440x3120,结果更加糟糕。
目前我正在使用由 Rectangle
填充的 GridLayout
来实现关卡的网格。我试过根据 Window.size
、Window.width
制作公式,我试过使用 size_hint
、size
、width
、cols_minimum
和 kivy.metrics
到目前为止没有成功。
附带说明一下,如果我试图实现的或下面代码中的任何内容可以以更好的方式完成,请告诉我。任何替代方案将不胜感激,我对 kivy
和 Python
.
我的代码:
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
class GridCell(Widget):
color = ListProperty([1, 1, 1, 1])
size = ListProperty([0, 0])
pos = ListProperty([0, 0])
def __init__(self, size, x, y, **kwargs):
super().__init__(**kwargs)
self.color = (0.0, 0.0, 0.0, 1.0)
self.size = (size, size)
self.pos = (x, y)
class Level(GridLayout):
def __init__(self, **kwargs):
super(Level, self).__init__(**kwargs)
self.cols = 30
self.cell_size = 28
self.spacing = 2
self.positions = [(row, column) for row in range(self.cols) for column
in range(self.cols)]
self.grid_cells = {}
self.create_grid()
def create_grid(self):
for position in self.positions:
self.grid_cells[position] = GridCell(self.cell_size, *position)
self.add_widget(self.grid_cells[position])
if __name__ == '__main__':
from kivy.app import App
Builder.load_file('grid_cell.kv')
Window.clearcolor = (1.0, 1.0, 1.0, 1.0)
class LevelApp(App):
def build(self):
self.title = 'Level'
level = Level()
return level
level_app = LevelApp()
level_app.run()
grid_cell.kv:
<GridCell>:
canvas:
Color:
rgba: self.color
Rectangle:
pos: self.pos
size: self.size
请注意,您不能用方形单元格的方形网格填充非方形 window。但是,要使单元格保持正方形并将其大小基于 GridLayout
,请尝试将 GridCell
class 更改为:
class GridCell(Widget):
color = ListProperty([1, 1, 1, 1])
def __init__(self, x, y, **kwargs):
super().__init__(**kwargs)
self.color = (0.0, 0.0, 0.0, 1.0)
self.pos = (x, y)
请注意,您不需要定义 pos
和 size
属性,因为 Widget
已经有了它们,而且我已经从 [=19] 中删除了 size
=]方法。
并将Level
更改为:
class Level(GridLayout):
def __init__(self, **kwargs):
super(Level, self).__init__(**kwargs)
self.cols = 30
self.rows = 30
self.spacing = 2
self.positions = [(row, column) for row in range(self.rows) for column
in range(self.cols)]
self.grid_cells = {}
self.create_grid()
def create_grid(self):
for position in self.positions:
self.grid_cells[position] = GridCell(*position)
self.add_widget(self.grid_cells[position])
然后在你的 kv
:
<GridCell>:
grid_cols: self.parent.cols if self.parent and self.parent.cols else 1
grid_rows: self.parent.rows if self.parent and self.parent.rows else 1
tmp_size: min(self.parent.width/self.grid_cols - self.parent.spacing[0], self.parent.height/self.grid_rows - self.parent.spacing[1]) if self.parent else 0
size_hint: None, None
size: self.tmp_size, self.tmp_size
canvas:
Color:
rgba: self.color
Rectangle:
pos: self.pos
size: self.size
这会根据 GridLayout
、size
、rows
和 cols
计算 tmp_size
,并将该大小分配给 GridCell
]. kv
中的 if
语句是必需的,因为 <GridCell>
规则在 GridCell
获得其 parent
分配之前应用。