Skip to content

Instantly share code, notes, and snippets.

@xu-cheng
Created July 31, 2013 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xu-cheng/6119253 to your computer and use it in GitHub Desktop.
Save xu-cheng/6119253 to your computer and use it in GitHub Desktop.
CountDown
# 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