Created
July 31, 2013 04:25
-
-
Save xu-cheng/6119253 to your computer and use it in GitHub Desktop.
CountDown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CountDown Timer for iPad | |
# Copyright (c) 2013 by Xu Cheng | |
# Usage: | |
# one figure: start/pause/resume the timer. | |
# two figures: reset the timer. | |
# three figures: set the initial time of timer. | |
from scene import * | |
from time import time | |
from math import modf | |
from itertools import chain | |
from functools import partial | |
import string | |
import json | |
import sound | |
try: | |
with open('countdown.json', 'r') as f: | |
init_Time = json.load(f).get('init_time', 30.0) | |
except: | |
init_Time = 30.0 | |
class CountDownState: | |
def __init__(self, init_time = init_Time): | |
self.running = False | |
self.remaining_time = init_time | |
self.init_time = init_time | |
self.last_time = 0.0 | |
def start_or_resume(self): | |
if not self.running: | |
self.running = True | |
self.last_time = time() | |
def pause(self): | |
if self.running: | |
self.running = False | |
self.remaining_time -= (time() - self.last_time) | |
def reset(self): | |
self.running = False | |
self.remaining_time = self.init_time | |
self.last_time = 0.0 | |
def refresh_time(self): | |
if self.running: | |
now = time() | |
self.remaining_time -= (now - self.last_time) | |
self.last_time = now | |
return self.remaining_time | |
class ImageButton (Layer): | |
def __init__(self, frame, image, is_hidden=False, scene=None): | |
Layer.__init__(self, frame) | |
self.action = None | |
self.scene = scene | |
self.last_touch = None | |
self.last_touch_count = 0 | |
if image is not None: | |
self.image = image | |
if is_hidden: | |
self.hide() | |
def touch_began(self, touch): | |
self.last_touch = touch | |
self.last_touch_count = 0 | |
def touch_ended(self, touch): | |
if self.superlayer.convert_from_screen(touch.location) in self.frame: | |
if callable(self.action): | |
self.action() | |
def draw(self, a=1.0): | |
super(ImageButton, self).draw(a) | |
if self.scene and self.last_touch: | |
for touch_id,touch in self.scene.touches.iteritems(): | |
if touch_id == self.last_touch.touch_id: | |
if self.superlayer.convert_from_screen(touch.location) in self.frame: | |
self.last_touch_count += 1 | |
if self.last_touch_count > 10 and self.last_touch_count % 3 == 0 and callable(self.action): | |
self.action() | |
break | |
def hide(self): | |
self.ignores_touches = True | |
self.old_alpha = self.alpha | |
self.alpha = 0 | |
def show(self): | |
self.ignores_touches = False | |
if hasattr(self, 'old_alpha'): | |
self.alpha = self.old_alpha | |
class CountDown (Scene): | |
def setup(self): | |
self.state = CountDownState() | |
self.setting_mode = False | |
self.just_change_orientaion = False | |
self.root_layer = Layer(self.bounds) | |
sound.load_effect('Beep') | |
sound.set_volume(0.8) | |
self.images_l = ['Typicons192_Up', 'Typicons192_Down'] | |
self.images_p = ['Typicons96_Up', 'Typicons96_Down'] | |
for img in chain(self.images_l, self.images_p): | |
load_image(img) | |
# font_size font w h font w | |
# 150 '0' 83.5 173.0 ':' 50.0 | |
# 100 '0' 56.0 115.5 ':' 33.5 | |
# font_size delta_x | |
# 150 217.0 | |
# 100 145.5 | |
x = [max(self.size.as_tuple()) * 0.5 - 325.5, min(self.size.as_tuple()) * 0.5 - 218.25] | |
delta_x = [217.0, 145.5] | |
y_up = [min(self.size.as_tuple()) * 0.5 + 173.0, max(self.size.as_tuple()) * 0.5 + 115.5] | |
y_down = [min(self.size.as_tuple()) * 0.5 - 173.0, max(self.size.as_tuple()) * 0.5 - 115.5] | |
img_w = img_h = [192, 96] | |
self.buttons = [] | |
for i in xrange(0, 3): | |
frame_up_l = Rect(x[0] - img_w[0] * 0.5, y_up[0] - img_h[0] * 0.5, img_w[0], img_h[0]) | |
frame_down_l = Rect(x[0] - img_w[0] * 0.5, y_down[0] - img_h[0] * 0.5, img_w[0], img_h[0]) | |
frame_up_p = Rect(x[1] - img_w[1] * 0.5, y_up[1] - img_h[1] * 0.5, img_w[1], img_h[1]) | |
frame_down_p = Rect(x[1] - img_w[1] * 0.5, y_down[1] - img_h[1] * 0.5, img_w[1], img_h[1]) | |
frame_up = frame_up_l if self.size.w > 1000 else frame_up_p | |
img_up = self.images_l[0] if self.size.w > 1000 else self.images_p[0] | |
btn_up = ImageButton(frame_up, img_up, True, self) | |
btn_up.action = partial(self.btn_touch, True, i) | |
btn_up.frames = [frame_up_l, frame_up_p] | |
btn_up.images = [self.images_l[0], self.images_p[0]] | |
self.buttons.append(btn_up) | |
self.root_layer.add_layer(btn_up) | |
frame_down = frame_down_l if self.size.w > 1000 else frame_down_p | |
img_down = self.images_l[1] if self.size.w > 1000 else self.images_p[1] | |
btn_down = ImageButton(frame_down, img_down, True, self) | |
btn_down.action = partial(self.btn_touch, False, i) | |
btn_down.frames = [frame_down_l, frame_down_p] | |
btn_down.images = [self.images_l[1], self.images_p[1]] | |
self.buttons.append(btn_down) | |
self.root_layer.add_layer(btn_down) | |
x[0] += delta_x[0] | |
x[1] += delta_x[1] | |
def should_rotate(self, orientation): | |
self.just_changed_orientation = True | |
return True | |
def draw(self): | |
background(0, 0, 0) | |
tint(1.00, 1.00, 1.00) | |
#Format the elapsed time (dt): | |
dt = self.state.refresh_time() | |
if self.state.running and dt >=0 and dt <= 0.05: | |
sound.play_effect('Beep') | |
if dt < 0: | |
tint(1.00, 0.00, 0.00) | |
dt = -dt | |
hour = dt / 3600 | |
minutes = (dt / 60) % 60 | |
seconds = dt % 60 | |
centiseconds = modf(dt)[0] * 100 | |
s = '%02d:%02d:%02d.%02d' % (hour, minutes, seconds, centiseconds) | |
# Determine font size | |
font_size = 150 if self.size.w > 1000 else 100 | |
text(s, 'Helvetica-Bold', font_size, *self.bounds.center()) | |
if self.just_changed_orientation: | |
change_to = 0 if self.size.w > 1000 else 1 | |
for btn in self.buttons: | |
btn.frame = btn.frames[change_to] | |
btn.image = btn.images[change_to] | |
self.just_changed_orientation = False | |
self.root_layer.update(self.dt) | |
self.root_layer.draw() | |
def touch_began(self, touch): | |
self.last_touches = self.touches.copy() | |
def touch_ended(self, touch): | |
if len(self.last_touches) - len(self.touches) == 1: | |
if len(self.last_touches) == 1: # one figure | |
if not self.setting_mode: | |
if self.state.running: | |
self.state.pause() | |
else: | |
self.state.start_or_resume() | |
elif len(self.last_touches) == 2: # two figures | |
if not self.setting_mode: | |
self.state.reset() | |
elif len(self.last_touches) == 3: # three figures | |
if self.state.running: | |
return | |
if self.setting_mode: | |
self.state.init_time = self.state.remaining_time | |
try: | |
with open('countdown.json', 'w') as f: | |
json.dump({'init_time':self.state.init_time}, f) | |
except: | |
pass | |
self.state.reset() | |
for btn in self.buttons: | |
if self.setting_mode: | |
btn.hide() | |
else: | |
btn.show() | |
self.setting_mode = not self.setting_mode | |
def btn_touch(self, up, num): | |
if num == 0: | |
if up: | |
if self.state.remaining_time / 3600 < 99: | |
self.state.remaining_time += 3600 | |
else: | |
if self.state.remaining_time >= 3600: | |
self.state.remaining_time -= 3600 | |
elif num == 1: | |
if up: | |
if self.state.remaining_time / 3600 < 99: | |
self.state.remaining_time += 60 | |
else: | |
if self.state.remaining_time >= 60: | |
self.state.remaining_time -= 60 | |
elif num == 2: | |
if up: | |
if self.state.remaining_time / 3600 < 99: | |
self.state.remaining_time += 1 | |
else: | |
if self.state.remaining_time >= 1: | |
self.state.remaining_time -= 1 | |
run(CountDown()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment