0

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
Joe Yim
  • 3
  • 3

1 Answers1

0

This is just some hints the blue circle is not exactly restricted to the axes

.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

Outputs

pic1

pic2

Simon Mengong
  • 2,625
  • 10
  • 22
  • Thank you so much for this! It sure gives me an idea on how to proceed :) May I know what is the reason you defined every on_touch function instead of just one? – Joe Yim Nov 02 '17 at 12:34
  • @JoeYim I defined them all because the drag behavior need both of them – Simon Mengong Nov 02 '17 at 18:18