I am very new to using Kivy for an assignment and I am stumped on one specific issue. My goal is to create a directional pad as shown in the image below whereby the blue circle will start out at the center of the image and is able to be dragged, but the circle can only travel in the directions imaged by the arrows(up, down, left, right) and cannot go further than the arrows. Right now, I am only concerned with the graphical layout so what I have done is simply a widget with drag behaviour below. Is there some way that could constrain the movements of the circle?
Image: The current achievable graphical layout for the d-pad
Python code:
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 file:
<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
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()
<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