Drawing with a finger~
# coding: utf-8
'''
Draw lines on the screen to reveal the 'Zen of Python' -- or replace it with your own text (by changing the MESSAGE string).
'''
from scene import *
import random
import math
import ui
from colorsys import hsv_to_rgb
A = Action
FONT_NAME = 'Ubuntu Mono'
if min(ui.get_screen_size()) > 750:
FONT_SIZE = 60
else:
FONT_SIZE = 30
SPACING = FONT_SIZE * 0.45
MESSAGE = '''CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
CSDN@HouSir
'''
class MyScene (Scene):
def setup(self):
self.hue = 0.0
self.prev_touch = None
self.letter_index = 0
self.background_color = '#262b30'
self.instructions = LabelNode('Draw with one finger.', ('HelveticaNeue-Light', 24), position=self.size/2, parent=self)
def did_change_size(self):
if self.instructions:
self.instructions.position = self.size/2
def touch_began(self, touch):
if self.instructions:
self.instructions.run_action(Action.fade_to(0, 1))
self.instructions = None
self.prev_touch = touch.location
def touch_moved(self, touch):
d = touch.location - self.prev_touch
if abs(d) < SPACING:
return
letter_pos = self.prev_touch + 0.5 * d
self.prev_touch = touch.location
letter = MESSAGE[self.letter_index]
self.letter_index += 1
self.letter_index %= len(MESSAGE)
if not letter.strip():
return
a = -math.atan2(*d) + math.pi/2
font = (FONT_NAME, FONT_SIZE)
color = hsv_to_rgb(self.hue, 0.65, 1)
label = LabelNode(letter, font=font, position=touch.location, color=color)
label.rotation = a
self.hue += 0.03
label.run_action(A.sequence(
A.move_to(letter_pos.x, letter_pos.y, 1.2, TIMING_ELASTIC_OUT),
A.wait(3),
A.scale_to(0, 0.25),
A.remove()))
self.add_child(label)
for i in range(5):
p = SpriteNode('shp:Spark', position=letter_pos, color=color)
p.blend_mode = BLEND_ADD
r = max(FONT_SIZE, 50)
dx, dy = random.uniform(-r, r), random.uniform(-r, r)
p.run_action(A.sequence(
A.group(
A.scale_to(0),
A.move_by(dx, dy, 0.5, TIMING_EASE_OUT_2)),
A.remove()))
self.add_child(p)
if __name__ == '__main__':
run(MyScene(), multi_touch=False)
Analog Clock~
'''
A simple analog clock made of ShapeNodes.
'''
from scene import *
from math import pi, sin, cos
from datetime import datetime
class Clock (Scene):
def setup(self):
r = min(self.size)/2 * 0.9
circle = ui.Path.oval(0, 0, r*2, r*2)
circle.line_width = 6
shadow = ('black', 0, 0, 15)
self.face = ShapeNode(circle, 'white', 'silver', shadow=shadow)
self.add_child(self.face)
for i in range(12):
label = LabelNode(str(i+1), font=('HelveticaNeue-UltraLight', 0.2*r))
label.color = 'black'
a = 2 * pi * (i+1)/12.0
label.position = sin(a)*(r*0.85), cos(a)*(r*0.85)
self.face.add_child(label)
self.hands = []
hand_attrs = [(r*0.6, 8, 'black'), (r*0.9, 8, 'black'), (r*0.9, 4, 'red')]
for l, w, color in hand_attrs:
shape = ShapeNode(ui.Path.rounded_rect(0, 0, w, l, w/2), color)
shape.anchor_point = (0.5, 0)
self.hands.append(shape)
self.face.add_child(shape)
self.face.add_child(ShapeNode(ui.Path.oval(0, 0, 15, 15), 'black'))
self.did_change_size()
def did_change_size(self):
self.face.position = self.size/2
def update(self):
t = datetime.now()
tick = -2 * pi / 60.0
seconds = t.second + t.microsecond/1000000.0
minutes = t.minute + seconds/60.0
hours = (t.hour % 12) + minutes/60.0
self.hands[0].rotation = 5 * tick * hours
self.hands[1].rotation = tick * minutes
self.hands[2].rotation = tick * seconds
run(Clock())
Simplex Noise~
# coding: utf-8
'''
A noise shader that produces an animation that looks a bit like bubbling lava... You can scroll infinitely in all directions via touch.
'''
from scene import *
class NoiseScene (Scene):
def setup(self):
with open('SimplexNoise.fsh') as f:
src = f.read()
shader = Shader(src)
self.sprite = SpriteNode('SimplexNoiseGradient.png', size=self.size, position=self.size/2, parent=self)
self.sprite.shader = shader
self.offset = Vector2(0, 0)
self.touch_start = Point(0, 0)
def did_change_size(self):
self.sprite.position = self.size/2
self.sprite.size = self.size
def touch_began(self, touch):
self.touch_start = touch.location
def touch_moved(self, touch):
offset = self.offset + (self.touch_start - touch.location)
self.sprite.shader.set_uniform('u_offset', offset)
def touch_ended(self, touch):
self.offset += (self.touch_start - touch.location)
run(NoiseScene(), multi_touch=False)
Stop watch
# coding: utf-8
'''
An experimental hybrid of an analog and digital stopwatch -- tap anywhere to start/stop/reset.
'''
from scene import *
import sound
from functools import partial
from time import time
import ui
if min(ui.get_screen_size()) < 750:
digit_h = 60
else:
digit_h = 100
digit_w = digit_h * 0.9
invert_shader_src = '''
#extension GL_EXT_shader_framebuffer_fetch : require
void main() {gl_FragColor = vec4(1.0 - gl_LastFragData[0].rgb, 1.0);}
'''
class ReelNode (Node):
def __init__(self, count=10):
Node.__init__(self)
self.count = count
self.labels = []
self.container = Node(parent=self)
font = ('Avenir Next', digit_h)
for i in range(count * 3):
label = LabelNode(str(i%count), font=font)
label.position = 0, -i * digit_h
self.container.add_child(label)
self.labels.append(label)
self.set_value(0)
def set_value(self, value):
value = min(self.count, max(0, value))
self.value = value
y = self.count * digit_h + digit_h * value
self.container.position = (0, y)
for label in self.labels:
label_y = y + label.position.y
label.alpha = 1.0 - abs(label_y) / (digit_h*5.0)
label.scale = label.alpha
def animate_to(self, value, d=0.2):
from_value = self.value
to_value = value
def anim(from_value, to_value, node, p):
node.set_value(from_value + p * (to_value-from_value))
animation = Action.call(partial(anim, from_value, to_value), d)
self.run_action(animation)
class StopWatch (Scene):
def setup(self):
self.started = False
self.start_time = 0
self.stopped = False
self.root = Node(parent=self)
self.reels = []
for i in range(5):
reel = ReelNode(count=6 if i in (0, 2) else 10)
x = (i-2) * digit_w
x += 10 * (1 if i%2 == 0 else -1)
reel.position = x, 0
self.root.add_child(reel)
self.reels.append(reel)
colon = LabelNode(':', font=('Avenir Next', digit_h), position=(-digit_w/2, 0), parent=self.root)
dot = LabelNode('.', font=('Avenir Next', digit_h), position=(digit_w*1.5, 0), parent=self.root)
overlay = SpriteNode(size=(max(self.size), digit_h + 10))
overlay.shader = Shader(invert_shader_src)
self.root.add_child(overlay)
self.background_color = 'black'
self.did_change_size()
def did_change_size(self):
self.root.position = self.size/2
def update(self):
if not self.started:
return
elapsed = time() - self.start_time
minutes = elapsed // 60
seconds = elapsed % 60.0
v4 = elapsed % 1.0 * 10.0
v3 = seconds % 10
v2 = (seconds // 10) + v3 / 10.0
v1 = minutes % 10 + seconds / 60.0
v0 = minutes // 10 + v1 / 10.0
self.reels[0].set_value(v0)
self.reels[1].set_value(v1)
self.reels[2].set_value(v2)
self.reels[3].set_value(v3)
self.reels[4].set_value(v4)
def touch_began(self, touch):
if not self.started:
if not self.stopped:
# Start
sound.play_effect('ui:switch19')
self.start_time = time()
self.started = True
else:
# Reset
sound.play_effect('ui:switch20')
for reel in self.reels:
reel.animate_to(0, 0.3)
self.stopped = False
else:
# Stop
sound.play_effect('ui:switch2')
self.stopped = True
self.started = False
for reel in self.reels:
reel.animate_to(int(reel.value))
if __name__ == '__main__':
run(StopWatch())
Swarm~
'''
A swarm simulation based on the 'Boids' algorithm by Craig Reynolds (http://www.red3d.com/cwr/boids/) and pseudo-code by Conrad Parker (http://www.kfish.org/boids/pseudocode.html)
You can tap the screen to scatter the swarm temporarily.
'''
from scene import *
import sound
from random import uniform, choice
import math
A = Action
SWARM_SIZE = 30
MAX_SPEED = 6
class Boid (SpriteNode):
def __init__(self, max_x, max_y, *args, **kwargs):
img = choice(['plf:Enemy_FishGreen', 'plf:Enemy_FishPink'])
SpriteNode.__init__(self, img, *args, **kwargs)
self.scale = 0.6
self.max_x = max_x
self.max_y = max_y
a = uniform(0, math.pi*2)
self.position = (uniform(0, max_x), uniform(0, max_y))
self.v = Vector2(math.cos(a), math.sin(a))
self.startled = False
def update(self, neighbors):
self.rule1(neighbors)
self.rule2(neighbors)
self.rule3(neighbors)
self.rule4(neighbors)
if abs(self.v) > MAX_SPEED:
self.v *= (MAX_SPEED / abs(self.v))
def rule1(self, neighbors):
# Move to 'center of mass' of neighbors
if not neighbors:
return Vector2(0, 0)
p = Point()
for n in neighbors:
p += n.position
m = p / len(neighbors)
if self.startled:
self.v -= (m - self.position) * 0.007
else:
self.v += (m - self.position) * 0.001
def rule2(self, neighbors):
# Don't crowd neighbors
if not neighbors:
return Vector2(0, 0)
c = Vector2()
for n in neighbors:
if abs(n.position - self.position) < 30:
c += (self.position - n.position)
self.v += c * 0.01
def rule3(self, neighbors):
# Match velocity of neighbors
if not neighbors:
return Vector2(0, 0)
v = Vector2()
for n in neighbors:
v += n.v
m = v / len(neighbors)
self.v += m * 0.01
def rule4(self, neighbors):
# Stay within screen bounds
v = Vector2()
if self.position.x < 0:
v.x = 1
if self.position.x > self.max_x:
v.x = -1
if self.position.y < 0:
v.y = 1
if self.position.y > self.max_y:
v.y = -1
self.v += v * 0.3
class SwarmScene (Scene):
def setup(self):
self.swarm = [Boid(self.size.w, self.size.h, parent=self) for i in range(SWARM_SIZE)]
self.background_color = '#003f67'
def did_change_size(self):
for b in self.swarm:
b.max_x = self.size.w
b.max_y = self.size.h
def update(self):
for boid in self.swarm:
neighbor_distance = min(self.size)/3
neighbors = [b for b in self.swarm if b != boid and abs(b.position - boid.position) < neighbor_distance]
boid.update(neighbors)
for boid in self.swarm:
boid.position += boid.v
boid.rotation = math.atan2(*reversed(boid.v)) + math.pi
def touch_began(self, touch):
self.panic(touch.location)
def panic(self, pos):
sound.play_effect('drums:Drums_06')
for b in self.swarm:
b.startled = True
s = SpriteNode('shp:wavering', position=pos, scale=0, parent=self)
s.run_action(A.sequence(A.group(A.scale_to(2), A.fade_to(0)), A.remove()))
self.run_action(A.sequence(A.wait(1), A.call(self.end_panic)))
def end_panic(self):
for b in self.swarm:
b.startled = False
if __name__ == '__main__':
run(SwarmScene(), show_fps=True)
import random
import time
FORCE_UNIVERSAL_ANSWER_RATE = 0.13
UNIVERSAL_ANSWERS = [
"你说你马呢?",
"那没事了。",
"真别逗我笑啊。",
"那可真是有趣呢。",
"就这?就这?",
"爬,爪巴,阿巴阿巴",
"不会真有人觉得是这样的吧,不会吧不会吧?"
"就这?丢人玩意"
]
STRONG_EMOTION_ANSWERS = [
"你急了急了急了?",
"他急了,他急了!"
]
QUESTION_ANSWERS = [
"不会真有人还不知道吧?",
"你都不知道,那你说你马呢?"
]
STRONG_EMOTION_PATTERNS = [
"!",
"???",
"???",
"气抖冷"
]
QUESTION_PATTERNS = [
"?",
"怎么",
"什么",
"咋",
"?"
]
def CheckPatterns(str_in, patterns):
for p in patterns:
if p in str_in:
return True
return False
def PickAnswer(question):
if random.random() < FORCE_UNIVERSAL_ANSWER_RATE:
return random.choice(UNIVERSAL_ANSWERS)
if CheckPatterns(question, STRONG_EMOTION_PATTERNS):
return random.choice(STRONG_EMOTION_ANSWERS)
elif CheckPatterns(question, QUESTION_PATTERNS):
return random.choice(QUESTION_ANSWERS)
else:
return random.choice(UNIVERSAL_ANSWERS)
def main():
while True:
question = "<<< "
print("郭狗子经典语录")
print(">>> " + PickAnswer(question))
#单位为秒,可以设置为0.2,为200毫秒
#time.sleep(0.2)
if __name__ == "__main__":
main()