Очевидно, что я просто скучаю по некоторым знаниям, но в любом случае я задам свой вопрос.
Я пытаюсь сделать круглую точку касания на экране, чтобы имитировать джойстик. Чтобы реализовать это, я начинаю с кругового вида виджета. Итак, я нарисовал круг в виджете и переопределил Widget.collide_point()
.
Однако на тестировании:
(a) мой виджет никогда не использует подсказку местоположения внизу справа и ...
(б) кажется, что его центральная точка находится за пределами экрана.
Я думаю, что это какая-то проблема с координатами виджета, которые не были завершены во время построения (поскольку я предполагаю, что виджет контейнера перемещает его), но я не совсем понимаю, как решить эту проблему дальше.
[В сторону] Если я создаю круг с центром вокруг self.center_x
& self.center_y
, он становится частично за кадром слева внизу. Я совсем не понимаю.
Я попытался настроить обратный вызов с часами, чтобы перенастроить круг после того, как позиционирование контейнера-виджета было завершено, но это тоже не помогло.
#! /usr/bin/env python3
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Rectangle, Color, Rotate, PushMatrix, PopMatrix, Line, Ellipse
from kivy.core.window import Window
from kivy.clock import Clock
import random
WINDOW_WIDTH, WINDOW_HEIGHT = Window.size
class JoyStick( Widget ):
def __init__( self, dial_width, **kwargs ):
super( JoyStick, self ).__init__( **kwargs )
self.radius = dial_width // 2
self.radius_sq = self.radius * self.radius
with self.canvas:
Color( 200, 200, 20 )
#Ellipse( pos=( self.center_x , self.center_y ), size=(self.radius * 2, self.radius * 2))
Line( circle=( dial_width, dial_width, self.radius ) )
self.size_hint = ( None, None )
self.pos_hint = { 'right':1, 'top':0 }
def collide_point( self, x, y ):
centre_x = self.center_x
centre_y = self.center_x
print("JoyStick.collide_point( %d, %d ) -> cx=%d, cy=%d, r=%d" % ( x, y, centre_x, centre_y, self.radius ) )
# Point-in-Circle Formula: if ((x-centre_x)^2 + (y - centre_y)^2 < radius^2) -> TRUE
x_minus_cx = x - centre_x
y_minus_cy = y - centre_y
result = ( ( x_minus_cx * x_minus_cx ) + ( y_minus_cy * y_minus_cy ) < self.radius_sq )
print("JoyStick.collide_point( %d, %d ) -> %s" % ( x, y, str( result ) ) )
return result
class Screen( FloatLayout ):
def __init__(self, **kwargs):
super( Screen, self).__init__(**kwargs)
# Controller
self.joystick = JoyStick( 150 )
self.add_widget( self.joystick )
def on_touch_down( self, touch ):
if ( self.joystick.collide_point( *touch.pos ) ):
print("Joystick Handled point")
def update( self, dt ):
pass
class MainApp( App ):
def build( self ):
screen = Screen()
Clock.schedule_interval( screen.update, 1.0 / 60.0 )
return screen
if ( __name__ == '__main__' ):
MainApp().run()
Stdout - в этом случае мне пришлось растянуть окно, чтобы фактически получить клик 750x750.
JoyStick.collide_point( 531, 582 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 531, 582 ) -> False
JoyStick.collide_point( 672, 712 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 672, 712 ) -> False
JoyStick.collide_point( 737, 721 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 737, 721 ) -> True
Joystick Handled point