99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
'''
|
|
Shuffled Camera Feed Puzzle
|
|
===========================
|
|
|
|
This demonstrates using Scatter widgets with a live camera.
|
|
You should see a shuffled grid of rectangles that make up the
|
|
camera feed. You can drag the squares around to see the
|
|
unscrambled camera feed or double click to scramble the grid
|
|
again.
|
|
'''
|
|
|
|
|
|
from kivy.app import App
|
|
from kivy.uix.camera import Camera
|
|
from kivy.uix.widget import Widget
|
|
from kivy.uix.slider import Slider
|
|
from kivy.uix.scatter import Scatter
|
|
from kivy.animation import Animation
|
|
from kivy.graphics import Color, Rectangle
|
|
from kivy.properties import NumericProperty
|
|
from random import randint, random
|
|
from functools import partial
|
|
|
|
|
|
class Puzzle(Camera):
|
|
|
|
blocksize = NumericProperty(100)
|
|
|
|
def on_texture_size(self, instance, value):
|
|
self.build()
|
|
|
|
def on_blocksize(self, instance, value):
|
|
self.build()
|
|
|
|
def build(self):
|
|
self.clear_widgets()
|
|
texture = self.texture
|
|
if not texture:
|
|
return
|
|
bs = self.blocksize
|
|
tw, th = self.texture_size
|
|
for x in range(int(tw / bs)):
|
|
for y in range(int(th / bs)):
|
|
bx = x * bs
|
|
by = y * bs
|
|
subtexture = texture.get_region(bx, by, bs, bs)
|
|
# node = PuzzleNode(texture=subtexture,
|
|
# size=(bs, bs), pos=(bx, by))
|
|
node = Scatter(pos=(bx, by), size=(bs, bs))
|
|
with node.canvas:
|
|
Color(1, 1, 1)
|
|
Rectangle(size=node.size, texture=subtexture)
|
|
self.add_widget(node)
|
|
|
|
self.shuffle()
|
|
|
|
def shuffle(self):
|
|
texture = self.texture
|
|
bs = self.blocksize
|
|
tw, th = self.texture_size
|
|
count = int(tw / bs) * int(th / bs)
|
|
indices = list(range(count))
|
|
childindex = 0
|
|
while indices:
|
|
index = indices.pop(randint(0, len(indices) - 1))
|
|
x = bs * (index % int(tw / bs))
|
|
y = bs * int(index / int(tw / bs))
|
|
child = self.children[childindex]
|
|
a = Animation(d=random() / 4.) + Animation(pos=(x, y),
|
|
t='out_quad', d=.4)
|
|
a.start(child)
|
|
childindex += 1
|
|
|
|
def on_touch_down(self, touch):
|
|
if touch.is_double_tap:
|
|
self.shuffle()
|
|
return True
|
|
super(Puzzle, self).on_touch_down(touch)
|
|
|
|
|
|
class PuzzleApp(App):
|
|
def build(self):
|
|
root = Widget()
|
|
puzzle = Puzzle(resolution=(640, 480), play=True)
|
|
slider = Slider(min=100, max=200, step=10, size=(800, 50))
|
|
slider.bind(value=partial(self.on_value, puzzle))
|
|
|
|
root.add_widget(puzzle)
|
|
root.add_widget(slider)
|
|
return root
|
|
|
|
def on_value(self, puzzle, instance, value):
|
|
value = int((value + 5) / 10) * 10
|
|
puzzle.blocksize = value
|
|
instance.value = value
|
|
|
|
|
|
PuzzleApp().run()
|