Как вращать два прямоугольных виджета независимо на одном экране в киве? - PullRequest
0 голосов
/ 20 января 2020

Я изучаю программирование на python и работаю над одним простым игровым приложением, в котором мне нужно повернуть два прямоугольника по нажатию на них на одном экране, но происходит, когда я нажимаю на один из них, оба прямоугольника вращаются вдоль источник этого прямоугольника, по которому щелкают, но это не относится к другому прямоугольнику, фактически его положение не совпадает с положением, и при нажатии на назначенную позицию (там, где этого прямоугольника нет) он поворачивается без вращения обоих прямоугольников. Мне просто нужно повернуть оба прямоугольника при нажатии независимо. Это сложно объяснить, поэтому, пожалуйста, попробуйте выполнить код и выясните, что происходит.

from kivy.app import App
from kivy.graphics import Rotate, Rectangle, Ellipse, Color
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, CardTransition
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, NumericProperty, ReferenceListProperty, ListProperty
from kivy.uix.floatlayout import FloatLayout

Builder.load_string('''

<Stage_2>:
    object2: Object2
    object3: Object3

    Object2:
        id: Object2
        center: self.rotate_origin

    Object3:
        id: Object3
        center: self.rotate_origin

<Manager>:
    id: screen_manager

    Screen:
        name:"P"
        FloatLayout:

            Button:
                pos_hint:{"x":0.2,"y":0.05}
                size_hint: 0.6, 0.2
                font_size: (root.width**2 + root.height**2) / 13**4
                text: "Play"
                background_color: 255,0,1,1
                on_release:
                    root.transition.direction = "up"        
                    root.current = "stage2"

    Screen:
        name: 'stage2'
        Stage_2:
            id:s2

''')

class Object2(Widget):
    def __init__(self, *args, **kwargs):
        Widget.__init__(self, *args, **kwargs)
        self.rect_pos_x = 500
        self.rect_pos_y = 425
        self.rect_pos = self.rect_pos_x, self.rect_pos_y
        self.rect_width = 150
        self.rect_height = 30
        self.rect_size = self.rect_width, self.rect_height
        self.rotate_origin_x = self.rect_pos_x + self.rect_width / 2
        self.rotate_origin_y = self.rect_pos_y + self.rect_height / 2
        self.rotate_origin = self.rotate_origin_x, self.rotate_origin_y
        self.angle = 135
        print('rect 1')
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0,197,68))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def rotate(self):
        self.canvas.clear()
        self.angle += 90
        if (self.angle > 315):
            self.angle = 225
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0, 255, 100))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            self.rotate()
            print(self.angle)
class Object3(Widget):
    def __init__(self, *args, **kwargs):
        Widget.__init__(self, *args, **kwargs)
        self.rect_pos_x = 500
        self.rect_pos_y = 250
        self.rect_pos = self.rect_pos_x, self.rect_pos_y
        self.rect_width = 150
        self.rect_height = 30
        self.rect_size = self.rect_width, self.rect_height
        self.rotate_origin_x = self.rect_pos_x + self.rect_width / 2
        self.rotate_origin_y = self.rect_pos_y + self.rect_height / 2
        self.rotate_origin = self.rotate_origin_x, self.rotate_origin_y
        self.angle = 135
        print('rect 2')
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(1,255,0))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def rotate(self):
        self.canvas.clear()
        self.angle += 90
        if (self.angle > 315):
            self.angle = 225
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0, 255, 100))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            self.rotate()
            print(self.angle)

class Stage_2(Widget):
    object2 = ObjectProperty(None)
    object3 = ObjectProperty(None)

class Manager(ScreenManager):
    pass

sm = Manager()

class ScreensApp(App):
    def build(self):
        return sm

if __name__ == '__main__':
    ScreensApp().run()

1 Ответ

1 голос
/ 20 января 2020

Если вы включите PushMatrix() и PopMatrix() в свои инструкции canvas, это повлияет только на текущий Widget. И затем, если вы отрегулируете Widget size и pos до значения Rectangle, вы должны улучшить (но не улучшить) collide_point производительность:

    with self.canvas:
        PushMatrix()
        Rotate(origin=self.rotate_origin, angle=self.angle)
        Color(rgb=(1,255,0))
        Rectangle(pos=self.rect_pos, size=self.rect_size)
        PopMatrix()
        self.pos = self.rect_pos
        self.size = self.rect_size

Это необходимо должно быть сделано всякий раз, когда вы используете with self.canvas, который включает Rotation, Scale или Translate. collide_point() все еще будет смотреть на Widget size и pos, а не на Rectangle, но, по крайней мере, центры Widget и его Rectangle должны совпадать.

...