在 Kivy 中创建方向键(限制移动)
Creating a D-pad in Kivy (constrain movement)
我对使用 Kivy 进行作业还很陌生,我对一个特定问题感到困惑。我的目标是创建一个如下图所示的方向键,蓝色圆圈将从图像的中心开始并且可以被拖动,但圆圈只能沿着箭头所描绘的方向移动(向上,下、左、右)并且不能超过箭头。现在,我只关心图形布局,所以我所做的只是一个具有下面拖动行为的小部件。有什么方法可以限制圆圈的运动吗?
图片:
The current achievable graphical layout for the d-pad
Python代码:
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.app import App
class Circle(DragBehavior, Widget):
def on_touch_move(self, touch):
tx, ty = touch.pos
sx, sy = self.pos
return super(Circle, self).on_touch_move(touch)
class Test(Widget):
pass
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
Kivy 文件:
<Circle>:
size: 100,74
drag_rectangle: self.x+36, self.y+28, 16, 25
drag_timeout: 10000000
drag_distance: 0
canvas:
Color:
rgba: 0,0,1,.5
Ellipse:
pos: self.pos
size: self.size
<Test>:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: root.width,root.height
pos: 0,0
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
size: root.width,root.height
pos: 0,0
source: 'icons/XY_bar.png'
Circle:
pos: root.width/2.3,root.height/2.25
这只是一些提示,蓝色圆圈并不完全限制在轴上
.py
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.app import App
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock
class Circle(DragBehavior, Widget):
def on_touch_move(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_move(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_move(touch)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_down(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_down(touch)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_up(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_up(touch)
class Test(Widget):
c = ObjectProperty()
joystick_x = NumericProperty(0)
joystick_y = NumericProperty(0)
redlinex = NumericProperty(0)
redliney = NumericProperty(0)
greenlinex = NumericProperty(0)
greenliney = NumericProperty(0)
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
Clock.schedule_interval(self.update, 1/10.0)
def update(self, *args):
self.joystick_x = self.c.pos[0]
self.joystick_y = self.c.pos[1]
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
kv
<Test>:
c: c
redlinex: self.pos[0] + self.size[0]/8.0
redliney: self.pos[1] + self.size[1]/2.0 - 50
greenlinex: self.pos[0] +self.size[0]/2.0 - 50
greenliney: self.pos[1] + self.size[1]/8.0
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: .75,.75,.75,1
Ellipse:
pos: root.joystick_x - 50, root.joystick_y - 50
size: 200, 200
Color:
rgba: 1,0,0,1
Rectangle:
pos: root.redlinex, root.redliney
size: 3 * self.size[0]/4.0, 100
Triangle:
points: root.redlinex, root.redliney, root.redlinex - 50, root.redliney + 50, root.redlinex, root.redliney + 100
Triangle:
points: root.redlinex + 3 * self.size[0]/4.0, root.redliney, root.redlinex + 3 * self.size[0]/4.0 + 50, root.redliney + 50, root.redlinex + 3 * self.size[0]/4.0, root.redliney + 100
Color:
rgba: .33, .51, .21, 1
Rectangle:
pos: root.greenlinex, root.greenliney
size: 100, 3 * self.size[1]/4.0
Triangle:
points: root.greenlinex, root.greenliney, root.greenlinex + 50, root.greenliney - 50, root.greenlinex + 100, root.greenliney
Triangle:
points: root.greenlinex, root.greenliney + 3 * self.size[1]/4.0, root.greenlinex + 50, root.greenliney + 3 * self.size[1]/4.0 + 50, root.greenlinex + 100, root.greenliney + 3 * self.size[1]/4.0
Circle:
canvas:
Color:
rgba: .16, .25, .6, 1
Ellipse:
pos: self.pos
size: self.size
id: c
pos: root.pos[0] + root.size[0]/2.0 - 50, root.pos[1] + root.size[1]/2.0 - 50
size: 100, 100
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
产出
我对使用 Kivy 进行作业还很陌生,我对一个特定问题感到困惑。我的目标是创建一个如下图所示的方向键,蓝色圆圈将从图像的中心开始并且可以被拖动,但圆圈只能沿着箭头所描绘的方向移动(向上,下、左、右)并且不能超过箭头。现在,我只关心图形布局,所以我所做的只是一个具有下面拖动行为的小部件。有什么方法可以限制圆圈的运动吗?
图片: The current achievable graphical layout for the d-pad
Python代码:
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.app import App
class Circle(DragBehavior, Widget):
def on_touch_move(self, touch):
tx, ty = touch.pos
sx, sy = self.pos
return super(Circle, self).on_touch_move(touch)
class Test(Widget):
pass
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
Kivy 文件:
<Circle>:
size: 100,74
drag_rectangle: self.x+36, self.y+28, 16, 25
drag_timeout: 10000000
drag_distance: 0
canvas:
Color:
rgba: 0,0,1,.5
Ellipse:
pos: self.pos
size: self.size
<Test>:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: root.width,root.height
pos: 0,0
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
size: root.width,root.height
pos: 0,0
source: 'icons/XY_bar.png'
Circle:
pos: root.width/2.3,root.height/2.25
这只是一些提示,蓝色圆圈并不完全限制在轴上
.py
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.app import App
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock
class Circle(DragBehavior, Widget):
def on_touch_move(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_move(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_move(touch)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_down(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_down(touch)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
if self.parent.redliney <= touch.pos[1] <= self.parent.redliney + 100:
return super(Circle, self).on_touch_up(touch)
elif self.parent.greenlinex <= touch.pos[0] <= self.parent.greenlinex + 100:
return super(Circle, self).on_touch_up(touch)
class Test(Widget):
c = ObjectProperty()
joystick_x = NumericProperty(0)
joystick_y = NumericProperty(0)
redlinex = NumericProperty(0)
redliney = NumericProperty(0)
greenlinex = NumericProperty(0)
greenliney = NumericProperty(0)
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
Clock.schedule_interval(self.update, 1/10.0)
def update(self, *args):
self.joystick_x = self.c.pos[0]
self.joystick_y = self.c.pos[1]
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
kv
<Test>:
c: c
redlinex: self.pos[0] + self.size[0]/8.0
redliney: self.pos[1] + self.size[1]/2.0 - 50
greenlinex: self.pos[0] +self.size[0]/2.0 - 50
greenliney: self.pos[1] + self.size[1]/8.0
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: .75,.75,.75,1
Ellipse:
pos: root.joystick_x - 50, root.joystick_y - 50
size: 200, 200
Color:
rgba: 1,0,0,1
Rectangle:
pos: root.redlinex, root.redliney
size: 3 * self.size[0]/4.0, 100
Triangle:
points: root.redlinex, root.redliney, root.redlinex - 50, root.redliney + 50, root.redlinex, root.redliney + 100
Triangle:
points: root.redlinex + 3 * self.size[0]/4.0, root.redliney, root.redlinex + 3 * self.size[0]/4.0 + 50, root.redliney + 50, root.redlinex + 3 * self.size[0]/4.0, root.redliney + 100
Color:
rgba: .33, .51, .21, 1
Rectangle:
pos: root.greenlinex, root.greenliney
size: 100, 3 * self.size[1]/4.0
Triangle:
points: root.greenlinex, root.greenliney, root.greenlinex + 50, root.greenliney - 50, root.greenlinex + 100, root.greenliney
Triangle:
points: root.greenlinex, root.greenliney + 3 * self.size[1]/4.0, root.greenlinex + 50, root.greenliney + 3 * self.size[1]/4.0 + 50, root.greenlinex + 100, root.greenliney + 3 * self.size[1]/4.0
Circle:
canvas:
Color:
rgba: .16, .25, .6, 1
Ellipse:
pos: self.pos
size: self.size
id: c
pos: root.pos[0] + root.size[0]/2.0 - 50, root.pos[1] + root.size[1]/2.0 - 50
size: 100, 100
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0