Working version without cursor size change
This commit is contained in:
parent
48b66bbded
commit
d8600bba95
|
|
@ -0,0 +1,303 @@
|
|||
#!/usr/bin/env python3
|
||||
from random import random, randint, choice
|
||||
from datetime import timedelta
|
||||
from kivy.app import App
|
||||
from kivy.uix.widget import Widget
|
||||
from kivy.uix.button import Button, ButtonBehavior
|
||||
from kivy.uix.label import Label
|
||||
from kivy.graphics import Color, Ellipse, Line, Rectangle
|
||||
from kivy.core.window import Window
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.clock import Clock
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.uix.colorpicker import ColorPicker
|
||||
from kivy.uix.scrollview import ScrollView
|
||||
from kivy.properties import StringProperty, BooleanProperty
|
||||
from kivy.lang import Builder
|
||||
|
||||
|
||||
PASS_PENALTY = 4
|
||||
DRAWING_TIME = 60
|
||||
|
||||
|
||||
Builder.load_string('''
|
||||
<ScrollableLabel>:
|
||||
Label:
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1]
|
||||
text_size: self.width, None
|
||||
text: root.text
|
||||
markup: root.markup
|
||||
''')
|
||||
|
||||
class ScrollableLabel(ScrollView):
|
||||
text = StringProperty('')
|
||||
markup = BooleanProperty(False)
|
||||
|
||||
|
||||
|
||||
class MyPaintWidget(Label):
|
||||
_game_state = {"game_started": False,
|
||||
"game_paused": False,
|
||||
"game_finished": False
|
||||
}
|
||||
_game_wordlists = {"possible_wordlist": set(),
|
||||
"found_words": set(),
|
||||
"unfound_words": set()
|
||||
}
|
||||
pen_characteristics = {"current_color": (0,0,0,1),
|
||||
"current_width": 4
|
||||
}
|
||||
current_word = ""
|
||||
|
||||
time = timedelta(seconds=DRAWING_TIME)
|
||||
_popup = None
|
||||
|
||||
def __init__(self, text="", **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._keyboard = Window.request_keyboard(
|
||||
self._keyboard_closed, self, 'text')
|
||||
if self._keyboard.widget:
|
||||
# If it exists, this widget is a VKeyboard object which you can use
|
||||
# to change the keyboard layout.
|
||||
pass
|
||||
self._keyboard.bind(on_key_down=self._on_keyboard_down)
|
||||
with open("words.txt", "r") as wordfile:
|
||||
self._wordlist = (word.strip() for word in wordfile.readlines())
|
||||
self._game_wordlists["possible_wordlist"] = set(self._wordlist)
|
||||
self.reset_game()
|
||||
|
||||
def _keyboard_closed(self):
|
||||
print('My keyboard has been closed!')
|
||||
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
|
||||
self._keyboard = None
|
||||
|
||||
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
|
||||
print('The key', keycode, 'have been pressed')
|
||||
print(' - text is %r' % text)
|
||||
print(' - modifiers are %r' % modifiers)
|
||||
if not self._game_state["game_started"]:
|
||||
if keycode[0] == 32:
|
||||
self.start_game()
|
||||
|
||||
elif keycode[1] == 'p':
|
||||
self.toggle_pause()
|
||||
|
||||
elif self.is_game_playing:
|
||||
if keycode[0] == 32:
|
||||
self.next_word()
|
||||
elif keycode[0] == 13:
|
||||
self.pass_word()
|
||||
elif keycode[1] == 'z' and "ctrl" in modifiers:
|
||||
if self.canvas.before.children:
|
||||
self.canvas.before.remove(self.canvas.before.children[-1])
|
||||
self.canvas.before.remove(self.canvas.before.children[-1])
|
||||
self.canvas.before.remove(self.canvas.before.children[-1])
|
||||
elif self._game_state["game_finished"]:
|
||||
if keycode[0] == 8:
|
||||
self.reset_game()
|
||||
|
||||
# Keycode is composed of an integer + a string
|
||||
# If we hit escape, let the input through to leave the app
|
||||
if keycode[1] == 'escape':
|
||||
return False
|
||||
|
||||
# Return True to accept the key. Otherwise, it will be used by
|
||||
# the system.
|
||||
return True
|
||||
|
||||
def toggle_pause(self):
|
||||
self._game_state["game_paused"] = not self._game_state["game_paused"]
|
||||
|
||||
def start_game(self):
|
||||
self.text=""
|
||||
self._game_state["game_started"] = True
|
||||
self._game_state["game_paused"] = False
|
||||
self.next_word(True)
|
||||
|
||||
def next_word(self, passed=False):
|
||||
if not passed:
|
||||
self._game_wordlists["found_words"].add(self.current_word)
|
||||
self.current_word = choice(list(self._game_wordlists["possible_wordlist"]))
|
||||
self._game_wordlists["possible_wordlist"].discard(self.current_word)
|
||||
self.clear_drawing()
|
||||
|
||||
def pass_word(self):
|
||||
self._game_wordlists["unfound_words"].add(self.current_word)
|
||||
self.next_word(True)
|
||||
if self.time - timedelta(seconds=PASS_PENALTY) > timedelta(0):
|
||||
self.time -= timedelta(seconds=PASS_PENALTY)
|
||||
else:
|
||||
self.time = timedelta(0)
|
||||
|
||||
@property
|
||||
def is_game_playing(self):
|
||||
return (self._game_state["game_started"]
|
||||
and not self._game_state["game_paused"]
|
||||
and not self._game_state["game_finished"])
|
||||
|
||||
@property
|
||||
def current_color(self):
|
||||
return self.pen_characteristics["current_color"]
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
if self.is_game_playing:
|
||||
with self.canvas.before:
|
||||
if self.collide_point(touch.x, touch.y):
|
||||
Color(*self.pen_characteristics["current_color"], mode='rgba')
|
||||
diameter = self.pen_characteristics["current_width"]
|
||||
Ellipse(pos=(touch.x - diameter / 2, touch.y - diameter / 2),
|
||||
size=(2*diameter, 2*diameter))
|
||||
touch.ud['line'] = Line(points=(touch.x, touch.y), width=diameter)
|
||||
|
||||
|
||||
|
||||
def on_touch_move(self, touch):
|
||||
if self.is_game_playing:
|
||||
if 'line' in touch.ud:
|
||||
if self.collide_point(touch.x, touch.y):
|
||||
touch.ud['line'].points += [touch.x, touch.y]
|
||||
elif self.collide_point(touch.ud['line'].points[-2], touch.y):
|
||||
touch.ud['line'].points += [touch.ud['line'].points[-2], touch.y]
|
||||
elif self.collide_point(touch.x, touch.ud['line'].points[-1]):
|
||||
touch.ud['line'].points += [touch.x, touch.ud['line'].points[-1]]
|
||||
|
||||
def recap(self):
|
||||
found_words = self._game_wordlists['found_words']
|
||||
unfound_words =self._game_wordlists['unfound_words']
|
||||
lines = ["[b]Tour terminé ![/b]\n"+
|
||||
f"Trouvés: [color=#5BB834]{len(found_words)}[/color]",
|
||||
"-"+ "\n-".join(found_words) if found_words else "",
|
||||
f"Passés: [color=#FF2A40]{len(unfound_words)}[/color]",
|
||||
"- "+ "\n- ".join(unfound_words) if unfound_words else ""]
|
||||
self.clear_drawing()
|
||||
self._popup = Popup(title='Fini !',
|
||||
content=ScrollableLabel(text="[size=24]"+"\n".join(lines)+"[/size]",
|
||||
markup=True),
|
||||
size_hint=(0.6,0.6),
|
||||
auto_dismiss=False)
|
||||
self._popup.open()
|
||||
|
||||
def game_finished(self):
|
||||
self._game_state["game_finished"] = True
|
||||
self.recap()
|
||||
|
||||
def reset_game(self):
|
||||
if self._popup:
|
||||
self._popup.dismiss()
|
||||
self.color = (0,0,0,1)
|
||||
self.text = "Appuyer sur 'espace' pour commencer à jouer"
|
||||
self.time = timedelta(seconds=DRAWING_TIME)
|
||||
self._game_state["game_finished"] = False
|
||||
self._game_state["game_started"] = False
|
||||
|
||||
def clear_drawing(self):
|
||||
self.canvas.before.clear()
|
||||
|
||||
class SizeButton(Widget, ButtonBehavior):
|
||||
def __init__(self, size=1, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.dot_size = size
|
||||
with self.canvas:
|
||||
Color(0,0,0, mode="rgb")
|
||||
self.bg = Rectangle(pos=self.pos, size=self.size)
|
||||
Color(1,1,1, mode="rgb")
|
||||
self.dot = Ellipse(pos=(self.center_x-size/2, self.center_y-size/2),
|
||||
size = (size*2, size*2))
|
||||
def redraw(self, args):
|
||||
self.dot.pos = (self.center_x-size/2, self.center_y-size/2)
|
||||
self.bg.pos = self.pos
|
||||
self.bg.size = self.size
|
||||
self.bind(size=redraw, pos=redraw)
|
||||
|
||||
|
||||
class MyPaintApp(App):
|
||||
state = False
|
||||
init = True
|
||||
|
||||
def build(self):
|
||||
Window.clearcolor = (1, 1, 1, 1)
|
||||
#self.init_keyboard()
|
||||
parent = BoxLayout(orientation='vertical')
|
||||
|
||||
self.painter = MyPaintWidget(size_hint=(0.9, 1))
|
||||
Clock.schedule_interval(self.update_time, 1.0/10.0)
|
||||
clearbtn = Button(text='Clear')
|
||||
clearbtn.bind(on_release=self.clear_canvas)
|
||||
togglebtn = Button(text='Inverser la couleur du fond')
|
||||
togglebtn.bind(on_release=self.toggle_background)
|
||||
|
||||
self.right_row = BoxLayout(orientation="vertical", size_hint=(0.1,1))
|
||||
color_picker_button = Button(text="Couleur")
|
||||
color_picker_button.background_color = self.painter.pen_characteristics["current_color"]
|
||||
color_picker_button.background_normal = ''
|
||||
color_picker_button.bind(on_release=self.open_color_picker)
|
||||
self.right_row.add_widget(color_picker_button)
|
||||
for i in range(1,6):
|
||||
size_button = SizeButton(2*i)
|
||||
self.right_row.add_widget(size_button)
|
||||
|
||||
middle_row = BoxLayout(orientation="horizontal", size_hint=(1, 0.8))
|
||||
middle_row.add_widget(self.painter)
|
||||
middle_row.add_widget(self.right_row)
|
||||
|
||||
bottom_row = BoxLayout(orientation='horizontal', spacing=5, size_hint=(1, .1))
|
||||
bottom_row.add_widget(togglebtn)
|
||||
bottom_row.add_widget(clearbtn)
|
||||
|
||||
top_row = BoxLayout(orientation='horizontal', spacing=5, size_hint=(1, .1))
|
||||
self.word_label = Label(text="Mot:", color=[0,0,0,1], halign="left")
|
||||
self.time_label = Label(text=f"{self.painter.time}", color=[0,0,0,1])
|
||||
top_row.add_widget(self.word_label)
|
||||
top_row.add_widget(self.time_label)
|
||||
|
||||
parent.add_widget(top_row)
|
||||
parent.add_widget(middle_row)
|
||||
parent.add_widget(bottom_row)
|
||||
return parent
|
||||
|
||||
def open_color_picker(self, _):
|
||||
clr_picker = ColorPicker()
|
||||
clr_picker.color = self.painter.pen_characteristics["current_color"]
|
||||
def on_color_change(instance, value):
|
||||
self.painter.pen_characteristics["current_color"] = value
|
||||
self.right_row.children[-1].background_color = self.painter.current_color
|
||||
clr_picker.bind(color=on_color_change)
|
||||
popup = Popup(title="Couleur du pinceau",
|
||||
content=clr_picker,
|
||||
size_hint=(0.5,0.5))
|
||||
popup.open()
|
||||
|
||||
def update_time(self, _):
|
||||
self.word_label.text_size = (self.word_label.size[0], None)
|
||||
if self.painter.is_game_playing:
|
||||
if self.painter.time > timedelta(0):
|
||||
self.painter.time -= timedelta(milliseconds=100)
|
||||
self.word_label.text = f"Mot: {self.painter.current_word}"
|
||||
else:
|
||||
self.painter.game_finished()
|
||||
|
||||
self.time_label.text = f"{self.painter.time}"
|
||||
|
||||
def toggle_background(self, obj):
|
||||
|
||||
if self.state:
|
||||
Window.clearcolor = (1, 1, 1, 1)
|
||||
self.painter.pen_characteristics["current_color"] = (0,0,0,1)
|
||||
self.word_label.color = (0,0,0,1)
|
||||
self.time_label.color = (0,0,0,1)
|
||||
self.state = False
|
||||
else:
|
||||
Window.clearcolor = (0,0,0,1)
|
||||
self.painter.pen_characteristics["current_color"] = (1,1,1,1)
|
||||
self.word_label.color = (1,1,1,1)
|
||||
self.time_label.color = (1,1,1,1)
|
||||
self.state = True
|
||||
self.clear_canvas(obj)
|
||||
|
||||
def clear_canvas(self, _):
|
||||
self.painter.clear_drawing()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
MyPaintApp().run()
|
||||
Loading…
Reference in New Issue