如何在kivy的单个屏幕上独立旋转两个矩形小部件?



我正在学习 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()

如果您在canvas说明中包含PushMatrix()PopMatrix(),则只有当前Widget会受到影响。然后,如果你将Widgetsizepos调整到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

每当使用涉及RotationScaleTranslatewith self.canvas时,都需要执行此操作。collide_point()仍然会看Widgetsizepos,而不是Rectangle,但至少Widget的中心和它的Rectangle应该重合。

最新更新