Проблемы масштабирования Kivy GridLayout - Android против P C - 16: 9 и 19: 5: 9 против 4: 3 (1920x1080 и 1440x3120 против 800x600) - PullRequest
0 голосов
/ 18 июня 2020

Я делал игру Android Змейка, используя kivy и buildozer, и после многих итераций с использованием разных значений, макетов и подходов (и множества поисков в Google, StackOverflow и kivy форумах / документации) Я дошел до точки, когда сам ищу здесь помощи.

Проблема такова;
сетка выглядит великолепно, когда окно kivy имеет размер 800x600, при этом прямоугольники должны быть идеальными, ровными квадраты. В тот момент, когда окно увеличивается до максимума и окно превращается в 1920x1080 (16: 9), квадраты становятся широкими прямоугольниками и, следовательно, неровными. К сожалению, попробовав игру на моем OnePlus 7 Pro с соотношением сторон 19: 5: 9 и разрешением 1440x3120, нежелательный результат стал еще более экстремальным.

в настоящее время я использую GridLayout, заполненный Rectangle, чтобы получить сетку уровня. Я пробовал составлять формулы на основе 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

1 Ответ

1 голос
/ 19 июня 2020

Обратите внимание, что вы не можете заполнить неквадратное окно квадратной сеткой из квадратных ячеек. Но, чтобы ячейки оставались квадратными и основывались на их размере GridLayout, попробуйте изменить класс GridCell на:

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 и * 1007. * свойства, так как Widget уже имеют их, и я удалил size из метода __init__().

И изменил 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

Это вычисляет tmp_size на основе GridLayout size, rows и cols и присваивает этот размер GridCell. Операторы if в kv необходимы, потому что правило <GridCell> применяется до того, как GridCell получит свой parent назначенный.

...