Я пытаюсь создать королевскую игру Ur с питоном, используя Kivy libs.
То, что я пытаюсь сделать, это создать доску (что сделано, но впереди более сложная работа) и 7 штук (цифр) для каждого игрока. Мне удалось создать все 7, но я понятия не имел, как ими управлять самостоятельно или вообще двигаться.
Я нашел код, который позволил мне перемещать объект с помощью мыши, но мне нужно только перемещать объект, над которым находится моя мышь. Как будто хватаешь только шахматный кусок, который тебе нужен, а не королеву все время.
Код:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse
from kivy.clock import Clock
from random import random
class CircleWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
self.size = (50,50)
for i in range(0, 7):
self.circle = Ellipse(pos = self.pos, size = self.size)
self.canvas.add(self.circle)
# handle position change
def on_pos(self, obj, new_pos):
self.circle.pos = new_pos # when widget moves, so does the graphic instruction
class RootWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
self.cw = CircleWidget()
self.add_widget(self.cw)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
# do whatever else here
def on_touch_move(self, touch):
if touch.grab_current is self:
print("This prints all the time...")
self.cw.pos = (touch.x,touch.y)
def on_touch_up(self, touch):
if touch.grab_current is self:
touch.ungrab(self)
# and finish up here
def update(self, dt):
print("No idea why I need this")
class MyApp(App):
def build(self):
rw = RootWidget()
# call update() every second
Clock.schedule_interval(rw.update, 1.0)
return rw
MyApp().run()
Кроме того, я забыл изменить позиции всех фигур рядом друг с другом, но это не сложная задача.
Любая помощь в перемещении их по одному?
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse, Color
from kivy.core.window import Window
from random import randint
class CircleWidget(Widget):
def __init__(self, **kwargs):
super(CircleWidget, self).__init__(**kwargs)
self.size = (50, 50)
with self.canvas:
Color(0, 0, 1, 0.5)
self.circle = Ellipse(pos=self.pos, size=self.size)
self.bind(pos=self.redraw, size=self.redraw)
def redraw(self, *args):
self.circle.size = self.size
self.circle.pos = self.pos
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
# if the touch collides with our widget, let grab it
touch.grab(self)
# and accept the touch.
return True
return super(CircleWidget, self).on_touch_down(touch)
def on_touch_up(self, touch):
# check if it a grabbed touch event
if touch.grab_current is self:
# don't forget to ungrab ourself, or you might have side effects
touch.ungrab(self)
# and accept the last up
return True
return super(CircleWidget, self).on_touch_up(touch)
def on_touch_move(self, touch):
# check if it a grabbed touch event
if touch.grab_current is self:
self.pos = touch.pos
# and accept the last move
return True
return super(CircleWidget, self).on_touch_move(touch)
class RootWidget(Widget):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
for i in range(8):
self.add_widget(CircleWidget(pos=(randint(0, Window.width - 50), randint(0, Window.height - 50))))
class MyApp(App):
def build(self):
return RootWidget()
if __name__ == "__main__":
MyApp().run()
В вашем случае вы перезаписываете self.canvas, поэтому после цикла self.canvas будет только последним элементом, поэтому вы заметите, что когда вы перемещаете элемент и хотите переместить другой элемент, который перемещал предыдущие шаги.
Я рекомендую вам избегать выполнения грязной работы, у kivy есть многие из тех функций, которые реализованы с помощью Behavior
s, в этом случае правильная вещь - использовать DragBehavior
, в моем решении я реализую тот, который нарисован в.kv, поскольку он является декларативным языком. привязка - это простые спасительные строки, такие как on_pos
и другое связывание, подобное тому, которое используется для drag_rectangle.
С другой стороны, CircleWidget должен реализовать один круг, а не 7 кругов, поскольку положение кругов будет другим, в вашем случае вы делаете их похожими на один.
Решение:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.clock import Clock
from kivy.lang import Builder
kv = '''
<CircleWidget>:
size: 50, 50
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
canvas:
Ellipse:
pos: root.pos
size: root.size
'''
Builder.load_string(kv)
class CircleWidget(DragBehavior, Widget):
pass
class RootWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
for i in range(7):
cw = CircleWidget()
self.add_widget(cw)
def update(self, dt):
print("No idea why I need this")
class MyApp(App):
def build(self):
rw = RootWidget()
# call update() every second
Clock.schedule_interval(rw.update, 1.0)
return rw
MyApp().run()