def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip (required)") return self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() print("Found: LED Strip ({0})".format( config.UID_LED_STRIP_BRICKLET)) except: print("Not Found: LED Strip ({0})".format( config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.speaker = PongSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) self.led_strip.register_callback( self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) self.init_game()
def test_cat(self): f = [] c = KeyPress.compile("A<A>.a<a>", A=lambda: f.append('A'), a=lambda: f.append('a')) key_press = KeyPress(c) key_press.process_input('A') key_press.process_input(12) key_press.process_input(13) key_press.process_input('a') self.assertEqual(['A', 'a'], f) self.assertEqual("match", key_press.status())
def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip (required)") return self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) except: print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.display = TetrisSegmentDisplay(self.ipcon) self.speaker = TetrisSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) self.init_game()
def go_to_playlist_menu(self): res = self.comm.call("led", "set", {"anim": ["playlist_menu"]}) res = self.comm.call("stream_receiver", "multicast", {}) self.inputter.set_key_press(KeyPress(self.playlist_menu)) self.startup_timer = threading.Timer(self.menu_linger_time, self.leave_submenu) self.startup_timer.start()
def test_star2(self): # (Aa)* f = [] c = KeyPress.compile("(A<A>a<a>)*", A=lambda: f.append('A'), a=lambda: f.append('a')) key_press = KeyPress(c) key_press.process_inputs(['A', 'a', 'A']) self.assertEqual(['A', 'a', 'A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['a']) self.assertEqual(['A', 'a', 'A', 'a'], f) self.assertEqual("match", key_press.status())
def go_to_users_playlist_menu(self, user): res = self.comm.call("led", "set", {"anim": [user + "_menu"]}) self.inputter.set_key_press(KeyPress(self.user_playlist_menu[user])) if self.startup_timer != None: self.startup_timer.cancel() self.startup_timer = threading.Timer(self.menu_linger_time, self.leave_submenu) self.startup_timer.start()
def test_time4(self): c = KeyPress.compile(".C100-300<one>300-500<two>500-700<three>.c", one=lambda: f.append("one"), two=lambda: f.append("two"), three=lambda: f.append("three")) f = [] key_press = KeyPress(c) self.assertEqual({100,300}, key_press.process_input('C')) self.assertEqual([], f) self.assertEqual({300,500}, key_press.process_input(200)) self.assertEqual(['one'], f) self.assertEqual({500,700}, key_press.process_input(400)) self.assertEqual(['one', 'two'], f) self.assertEqual(set(), key_press.process_input(600)) self.assertEqual(['one', 'two', 'three'], f) self.assertEqual(set(), key_press.process_input('c')) self.assertEqual("match", key_press.status())
def test_time3(self): c = KeyPress.compile(".C(.A100-300+a<one>|.A200-400+a<two>)*.c", one=lambda: f.append("one"), two=lambda: f.append("two")) f = [] key_press = KeyPress(c) self.assertEqual(set(), key_press.process_input('C')) self.assertEqual({100,200,300,400}, key_press.process_input('A')) self.assertEqual({200,400}, key_press.process_input(350)) self.assertEqual(set(), key_press.process_input('a')) self.assertEqual(set(), key_press.process_input('c')) self.assertEqual("match", key_press.status()) self.assertEqual(['two'], f)
def mkMorse(self, seq, l): s = "" i = "." for c in seq: if c == '.': s += i + self.down + "0-" + str(self.t0) + "+" + self.up if c == '-': s += i + self.down + str(self.t0) + "-1000" + "+" + self.up i = "0-500" s += str(self.t1) + "-2000<match>" return KeyPress.compile(s, match=l)
def test_time2(self): # Aa12-15* c = KeyPress.compile("Aa12-15*") f = [] key_press = KeyPress(c) key_press.process_inputs(['A', 'a', 4, 8, 12, 13]) self.assertEqual("match", key_press.status())
def test_star(self): # A* f = [] c = KeyPress.compile("(A<A>)*", A=lambda: f.append('A')) key_press = KeyPress(c) key_press.process_inputs(['A', 'A']) self.assertEqual(['A', 'A'], f) self.assertEqual("match", key_press.status())
def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip or LED Strip V2 (required)") return if not config.IS_LED_STRIP_V2: self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) else: self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() if not config.IS_LED_STRIP_V2: print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET)) except: if not config.IS_LED_STRIP_V2: print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.speaker = PongSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) if not config.IS_LED_STRIP_V2: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) else: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, self.frame_rendered) self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING) self.init_game()
def __init__(self, inputter): self.inputter = inputter morse_maker = MorseMaker('C', 'c', 200, 500) self.morseAlphbeth = KeyPress.mkUnion( morse_maker.mkAll(lambda c: print("=== %s" % c)) + [ KeyPress.compile(".A.a<go_to_normal>", go_to_normal=lambda: self.go_normal()) ]) self.main_menu = KeyPress.mkUnion([ KeyPress.compile(".A.C.c.a<go_to_morse>", go_to_morse=lambda: self.go_morse()), KeyPress.compile(".A.a<A>", A=lambda: print("A")), KeyPress.compile(".B.b<B>", B=lambda: print("B")), ]) self.go_normal()
class Pong: PADDLE_SIZE = 3 # Antialased ball? # PONG_COLOR_INDEX_BALL_TOP = 8 # PONG_COLOR_INDEX_BALL_LEFT = 9 # PONG_COLOR_INDEX_BALL_RIGHT = 10 # PONG_COLOR_INDEX_BALL_BOTTOM = 11 COLORS = [ ( 0, 0, 0), # off # ( 10, 10, 10), # grey (255, 0, 0), # red (255, 80, 0), # orange (255, 255, 0), # yellow ( 0, 255, 0), # green ( 0, 0, 255), # blue (255, 0, 150), # violet (255, 0, 40), # purple ( 0, 0, 0), # ball top ( 0, 0, 0), # ball left ( 0, 0, 0), # ball right ( 0, 0, 0) # ball bottom ] SCORE_FONT = { 0: ["222", "202", "202", "202", "222"], 1: ["020", "020", "020", "020", "020"], 2: ["222", "002", "222", "200", "222"], 3: ["222", "002", "222", "002", "222"], 4: ["202", "202", "222", "002", "002"], 5: ["222", "200", "222", "002", "222"], 6: ["222", "200", "222", "202", "222"], 7: ["222", "002", "002", "002", "002"], 8: ["222", "202", "222", "202", "222"], 9: ["222", "202", "222", "002", "002"], } playfield = [x[:] for x in [[0]*config.LED_COLS]*config.LED_ROWS] score = [0, 0] paddle_position_x = [4, 15] paddle_position_y = [3, 3] ball_position = [10, 5] ball_direction = [0.1, 0.2] timer = None loop = True def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip or LED Strip V2 (required)") return if not config.IS_LED_STRIP_V2: self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) else: self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() if not config.IS_LED_STRIP_V2: print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET)) except: if not config.IS_LED_STRIP_V2: print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.speaker = PongSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) if not config.IS_LED_STRIP_V2: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) else: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, self.frame_rendered) self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING) self.init_game() def init_game(self): self.new_ball() self.paddle_position_y = [3, 3] self.score = [0, 0] def frame_rendered(self, length): self.write_playfield() def write_playfield(self): if not self.okay: return field = copy.deepcopy(self.playfield) self.add_score_to_playfield(field) self.add_paddles_to_playfield(field) self.add_ball_to_playfield(field) # Reorder LED data into R, G and B channel r = [] g = [] b = [] frame = [] for row in range(config.LED_ROWS): col_range = range(config.LED_COLS) if row % 2 == 0: col_range = reversed(col_range) for col in col_range: r.append(self.COLORS[field[row][col]][0]) g.append(self.COLORS[field[row][col]][1]) b.append(self.COLORS[field[row][col]][2]) frame.append(self.COLORS[field[row][col]][0]) frame.append(self.COLORS[field[row][col]][1]) frame.append(self.COLORS[field[row][col]][2]) if not config.IS_LED_STRIP_V2: # Make chunks of size 16 r_chunk = [r[i:i+16] for i in range(0, len(r), 16)] g_chunk = [g[i:i+16] for i in range(0, len(g), 16)] b_chunk = [b[i:i+16] for i in range(0, len(b), 16)] for i in range(len(r_chunk)): length = len(r_chunk[i]) # Fill up chunks with zeros r_chunk[i].extend([0]*(16-len(r_chunk[i]))) g_chunk[i].extend([0]*(16-len(g_chunk[i]))) b_chunk[i].extend([0]*(16-len(b_chunk[i]))) try: self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i]) except: break else: try: self.led_strip.set_led_values(0, frame) except: return def add_score_to_playfield(self, field): for row in range(3): for col in range(5): field[row][col+1] = int(self.SCORE_FONT[self.score[0]][col][row]) field[row+17][col+1] = int(self.SCORE_FONT[self.score[1]][col][row]) def add_ball_to_playfield(self, field): x = max(0, min(19, int(self.ball_position[0]))) y = max(0, min(9, int(self.ball_position[1]))) field[x][y] = config.PONG_COLOR_INDEX_BALL # Antialased ball? # x = max(0, min(19, self.ball_position[0])) # y = max(0, min(9, self.ball_position[1])) # ix = int(x) # iy = int(y) # field[ix][iy] = config.PONG_COLOR_INDEX_BALL # if ix + 1 < config.LED_ROWS: # field[ix+1][iy] = PONG_COLOR_INDEX_BALL_RIGHT # if ix - 1 > 0: # field[ix-1][iy] = PONG_COLOR_INDEX_BALL_LEFT # if iy + 1 < config.LED_COLS: # field[ix][iy+1] = PONG_COLOR_INDEX_BALL_TOP # if iy - 1 > 0: # field[ix][iy-1] = PONG_COLOR_INDEX_BALL_BOTTOM # # dx = x - int(x) # dy = x - int(x) # self.COLORS[PONG_COLOR_INDEX_BALL_RIGHT] = (0, 255*dx/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_LEFT] = (0, 255*(1-dx)/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_TOP] = (0, 255*dy/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_BOTTOM] = (0, 255*(1-dy)/64, 0) def add_paddles_to_playfield(self, field): for player in range(2): for i in range(self.PADDLE_SIZE): field[self.paddle_position_x[player]][self.paddle_position_y[player]+i] = config.PONG_COLOR_INDEX_PLAYER[player] def move_paddle(self, player, change): new_pos = self.paddle_position_y[player] + change if new_pos >= 0 and new_pos <= config.LED_COLS - self.PADDLE_SIZE: self.paddle_position_y[player] = new_pos def new_ball(self): self.ball_position = [(config.LED_ROWS - 1.0) / 2.0, (config.LED_COLS - 1.0) / 2.0] self.ball_direction = [random.choice([-0.2, 0.2]), random.choice([random.randrange(1, 9)/10.0, random.randrange(-9, -1)/10.0])] def tick(self): # Move ball for i in range(2): self.ball_position[i] += self.ball_direction[i] # Wall collision top/bottom if self.ball_position[1] < 0 or self.ball_position[1] >= config.LED_COLS: self.ball_direction[1] = -self.ball_direction[1] # Wall collision left/right def hit_left_right(player): self.speaker.beep_sirene() self.new_ball() self.score[player] += 1 if self.score[player] > 9: self.score[player] = 0 if self.ball_position[0] < 0: hit_left_right(1) if self.ball_position[0] >= config.LED_ROWS: hit_left_right(0) # Paddle collision def hit_paddle(skew): self.speaker.beep_paddle_hit() self.ball_direction[0] = -self.ball_direction[0] self.ball_direction[1] -= skew for i in range(2): self.ball_direction[i] *= 1.1 # Increase speed if self.ball_direction[0] < 0: if self.paddle_position_x[0] + 0.5 <= self.ball_position[0] <= self.paddle_position_x[0] + 1.5: if self.paddle_position_y[0] - 0.5 <= self.ball_position[1] <= self.paddle_position_y[0] + self.PADDLE_SIZE + 0.5: paddle_skew = (self.paddle_position_y[0] + self.PADDLE_SIZE/2.0 - self.ball_position[1])/10.0 hit_paddle(paddle_skew) if self.ball_direction[0] > 0: if self.paddle_position_x[1] - 0.5 <= self.ball_position[0] <= self.paddle_position_x[1] + 0.5: if self.paddle_position_y[1] - 0.5 <= self.ball_position[1] <= self.paddle_position_y[1] + self.PADDLE_SIZE + 0.5: paddle_skew = (self.paddle_position_y[1] + self.PADDLE_SIZE/2.0 - self.ball_position[1])/10.0 hit_paddle(paddle_skew) def run_game_loop(self): self.frame_rendered(0) self.timer = RepeatedTimer(0.1, self.tick) while self.loop: key = self.kp.read_single_keypress().lower() if key == 'a': self.move_paddle(0, -1) elif key == 's': self.move_paddle(0, 1) elif key == 'k': self.move_paddle(1, -1) elif key == 'l': self.move_paddle(1, 1) elif key == 'r': self.init_game() elif not config.HAS_GUI and key == 'q': break if not config.IS_LED_STRIP_V2: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, None) else: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, None) self.timer.stop() self.kp.stop()
def __init__(self, logger, exc_cb, inputter): self.logger = logger self.comm = Comm(5000, "buttons", {}, self.logger, exc_cb) self.inputter = inputter self.menu_linger_time = 5.0 self.main_menu = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.go_to_playlist_menu()), KeyPress.compile(".B.b<match>", match=lambda: self.multicast_play({ "artist": ["bryan adams"], "title": ["summer of 69"] })), KeyPress.compile(".C.c<match>", match=lambda: self.go_to_radio_menu()), KeyPress.compile(".D.d<match>", match=lambda: self.multicast_play({ "artist": ["volbeat"], "title": ["for evigt"] })), KeyPress.compile(".E.e<match>", match=lambda: self.apple_dock()), KeyPress.compile(".F.f<match>", match=lambda: self.go_to_podcast_menu()), KeyPress.compile(".H.h<match>", match=lambda: self.go_to_flow_menu()), ]) self.radio_menu = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.radio_channel("p1")), KeyPress.compile(".B.b<match>", match=lambda: self.radio_channel("p2")), KeyPress.compile(".C.c<match>", match=lambda: self.radio_channel("p3")), KeyPress.compile(".D.d<match>", match=lambda: self.radio_channel("24syv")), ]) self.podcast_menu = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.start_podcast("baelte")), KeyPress.compile(".B.b<match>", match=lambda: self.start_podcast("orientering")), KeyPress.compile(".C.c<match>", match=lambda: self.start_podcast("mads")), KeyPress.compile(".D.d<match>", match=lambda: self.start_podcast("d6m")), ]) self.flow_menu = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.flow({"to": ["0"]})), KeyPress.compile(".B.b<match>", match=lambda: self.flow({"prev": [1]})), KeyPress.compile(".C.c<match>", match=lambda: self.flow({"to": ["random"]})), KeyPress.compile(".D.d<match>", match=lambda: self.flow({"next": ["1"]})), KeyPress.compile(".E.e<match>", match=lambda: self.flow({"to": ["last"]})), KeyPress.compile(".H.h<match>", match=lambda: self.stop()), ]) self.playlist_menu = KeyPress.mkUnion([ KeyPress.compile( ".A.a<match>", match=lambda: self.go_to_users_playlist_menu("user_k")), KeyPress.compile( ".B.b<match>", match=lambda: self.go_to_users_playlist_menu("user_r")), KeyPress.compile( ".C.c<match>", match=lambda: self.go_to_users_playlist_menu("user_c")), KeyPress.compile( ".D.d<match>", match=lambda: self.go_to_users_playlist_menu("user_h")), KeyPress.compile( ".E.e<match>", match=lambda: self.go_to_users_playlist_menu("user_a")), KeyPress.compile( ".F.f<match>", match=lambda: self.go_to_users_playlist_menu("user_s")), ]) self.user_playlist_menu = {} self.user_playlist_menu["user_k"] = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.multicast_play({ "source": ["list"], "query": ["svensk"] })), ]) self.user_playlist_menu["user_r"] = KeyPress.mkUnion([ KeyPress.compile(".A.a<match>", match=lambda: self.multicast_play({ "source": ["list"], "query": ["metal"] })), KeyPress.compile( ".B.b<match>", match=lambda: self.multicast_play({"artist": ["metallica"]})), ]) self.user_playlist_menu["user_c"] = KeyPress.mkUnion([]) self.user_playlist_menu["user_h"] = KeyPress.mkUnion([]) self.user_playlist_menu["user_a"] = KeyPress.mkUnion([]) self.user_playlist_menu["user_s"] = KeyPress.mkUnion([]) print("==== press 'A' for playlists") print("==== press 'B' for youtube play") print("==== press 'C' for radio") print("==== press 'D' for Volbeat - For Evigt") print("==== press 'E' for Knight Rider") print("==== press 'F' for Pod cast") print("==== press 'H' for Flow control") print("==== press 'q' to quit") self.go_to_main_menu() self.inputter.click_NAD_button(3)
def go_to_flow_menu(self): res = self.comm.call("led", "set", {"anim": ["flow_menu"]}) self.inputter.set_key_press(KeyPress(self.flow_menu)) self.startup_timer = threading.Timer(self.menu_linger_time, self.leave_submenu) self.startup_timer.start()
def test_composite(self): f = [] # A(bc|d)*a c = KeyPress.compile("A<A>(b<b>c<c>|d<dd>)*a<a>", A=lambda: f.append('A'), a=lambda: f.append('a'), b=lambda: f.append('b'), c=lambda: f.append('c'), dd=lambda: f.append('d')) key_press = KeyPress(c) self.assertEqual("in progress", key_press.status()) key_press.process_input('A') self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_input('b') self.assertEqual(['A', 'b'], f) self.assertEqual("in progress", key_press.status()) key_press.process_input('c') self.assertEqual(['A', 'b', 'c'], f) self.assertEqual("in progress", key_press.status()) key_press.process_input('a') self.assertEqual(['A', 'b', 'c', 'a'], f) self.assertEqual("match", key_press.status())
def test_time(self): # A12-15<call>13-16*a c = KeyPress.compile("A<A>12-15<call>13-16*a<a>", A=lambda: f.append('A'), a=lambda: f.append('a'), call=lambda: f.append('12-15')) f = [] key_press = KeyPress(c) self.assertEqual({12,15}, key_press.process_input('A')) self.assertEqual({12,15}, key_press.process_input(4)) self.assertEqual({12,15}, key_press.process_input(8)) self.assertEqual({13,16}, key_press.process_input(12)) self.assertEqual({13,16}, key_press.process_input(13)) self.assertEqual(set(), key_press.process_input('a')) self.assertEqual(['A', '12-15', 'a'], f) self.assertEqual("match", key_press.status()) f = [] key_press.reset() self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['A', 4, 8]) self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['a']) self.assertEqual(['A'], f) self.assertEqual("failed", key_press.status()) f = [] key_press.reset() self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['A', 4, 13, 20]) self.assertEqual(['A', '12-15'], f) self.assertEqual("failed", key_press.status())
class Pong: PADDLE_SIZE = 3 # Antialased ball? # PONG_COLOR_INDEX_BALL_TOP = 8 # PONG_COLOR_INDEX_BALL_LEFT = 9 # PONG_COLOR_INDEX_BALL_RIGHT = 10 # PONG_COLOR_INDEX_BALL_BOTTOM = 11 COLORS = [ (0, 0, 0), # off # ( 10, 10, 10), # grey (255, 0, 0), # red (255, 80, 0), # orange (255, 255, 0), # yellow (0, 255, 0), # green (0, 0, 255), # blue (255, 0, 150), # violet (255, 0, 40), # purple (0, 0, 0), # ball top (0, 0, 0), # ball left (0, 0, 0), # ball right (0, 0, 0) # ball bottom ] SCORE_FONT = { 0: ["222", "202", "202", "202", "222"], 1: ["020", "020", "020", "020", "020"], 2: ["222", "002", "222", "200", "222"], 3: ["222", "002", "222", "002", "222"], 4: ["202", "202", "222", "002", "002"], 5: ["222", "200", "222", "002", "222"], 6: ["222", "200", "222", "202", "222"], 7: ["222", "002", "002", "002", "002"], 8: ["222", "202", "222", "202", "222"], 9: ["222", "202", "222", "002", "002"], } playfield = [x[:] for x in [[0] * config.LED_COLS] * config.LED_ROWS] score = [0, 0] paddle_position_x = [4, 15] paddle_position_y = [3, 3] ball_position = [10, 5] ball_direction = [0.1, 0.2] timer = None loop = True def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip (required)") return self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() print("Found: LED Strip ({0})".format( config.UID_LED_STRIP_BRICKLET)) except: print("Not Found: LED Strip ({0})".format( config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.speaker = PongSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) self.led_strip.register_callback( self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) self.init_game() def init_game(self): self.new_ball() self.paddle_position_y = [3, 3] self.score = [0, 0] def frame_rendered(self, length): self.write_playfield() def write_playfield(self): if not self.okay: return field = copy.deepcopy(self.playfield) self.add_score_to_playfield(field) self.add_paddles_to_playfield(field) self.add_ball_to_playfield(field) # Reorder LED data into R, G and B channel r = [] g = [] b = [] for row in range(config.LED_ROWS): col_range = range(config.LED_COLS) if row % 2 == 0: col_range = reversed(col_range) for col in col_range: r.append(self.COLORS[field[row][col]][config.R_INDEX]) g.append(self.COLORS[field[row][col]][config.G_INDEX]) b.append(self.COLORS[field[row][col]][config.B_INDEX]) # Make chunks of size 16 r_chunk = [r[i:i + 16] for i in range(0, len(r), 16)] g_chunk = [g[i:i + 16] for i in range(0, len(g), 16)] b_chunk = [b[i:i + 16] for i in range(0, len(b), 16)] for i in range(len(r_chunk)): length = len(r_chunk[i]) # Fill up chunks with zeros r_chunk[i].extend([0] * (16 - len(r_chunk[i]))) g_chunk[i].extend([0] * (16 - len(g_chunk[i]))) b_chunk[i].extend([0] * (16 - len(b_chunk[i]))) try: self.led_strip.set_rgb_values(i * 16, length, r_chunk[i], g_chunk[i], b_chunk[i]) except: break def add_score_to_playfield(self, field): for row in range(3): for col in range(5): field[row][col + 1] = int( self.SCORE_FONT[self.score[0]][col][row]) field[row + 17][col + 1] = int( self.SCORE_FONT[self.score[1]][col][row]) def add_ball_to_playfield(self, field): x = max(0, min(19, int(self.ball_position[0]))) y = max(0, min(9, int(self.ball_position[1]))) field[x][y] = config.PONG_COLOR_INDEX_BALL # Antialased ball? # x = max(0, min(19, self.ball_position[0])) # y = max(0, min(9, self.ball_position[1])) # ix = int(x) # iy = int(y) # field[ix][iy] = config.PONG_COLOR_INDEX_BALL # if ix + 1 < config.LED_ROWS: # field[ix+1][iy] = PONG_COLOR_INDEX_BALL_RIGHT # if ix - 1 > 0: # field[ix-1][iy] = PONG_COLOR_INDEX_BALL_LEFT # if iy + 1 < config.LED_COLS: # field[ix][iy+1] = PONG_COLOR_INDEX_BALL_TOP # if iy - 1 > 0: # field[ix][iy-1] = PONG_COLOR_INDEX_BALL_BOTTOM # # dx = x - int(x) # dy = x - int(x) # self.COLORS[PONG_COLOR_INDEX_BALL_RIGHT] = (0, 255*dx/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_LEFT] = (0, 255*(1-dx)/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_TOP] = (0, 255*dy/64, 0) # self.COLORS[PONG_COLOR_INDEX_BALL_BOTTOM] = (0, 255*(1-dy)/64, 0) def add_paddles_to_playfield(self, field): for player in range(2): for i in range(self.PADDLE_SIZE): field[self.paddle_position_x[player]][ self.paddle_position_y[player] + i] = config.PONG_COLOR_INDEX_PLAYER[player] def move_paddle(self, player, change): new_pos = self.paddle_position_y[player] + change if new_pos >= 0 and new_pos <= config.LED_COLS - self.PADDLE_SIZE: self.paddle_position_y[player] = new_pos def new_ball(self): self.ball_position = [(config.LED_ROWS - 1.0) / 2.0, (config.LED_COLS - 1.0) / 2.0] self.ball_direction = [ random.choice([-0.2, 0.2]), random.choice([ random.randrange(1, 9) / 10.0, random.randrange(-9, -1) / 10.0 ]) ] def tick(self): # Move ball for i in range(2): self.ball_position[i] += self.ball_direction[i] # Wall collision top/bottom if self.ball_position[1] < 0 or self.ball_position[ 1] >= config.LED_COLS: self.ball_direction[1] = -self.ball_direction[1] # Wall collision left/right def hit_left_right(player): self.speaker.beep_sirene() self.new_ball() self.score[player] += 1 if self.score[player] > 9: self.score[player] = 0 if self.ball_position[0] < 0: hit_left_right(1) if self.ball_position[0] >= config.LED_ROWS: hit_left_right(0) # Paddle collision def hit_paddle(skew): self.speaker.beep_paddle_hit() self.ball_direction[0] = -self.ball_direction[0] self.ball_direction[1] -= skew for i in range(2): self.ball_direction[i] *= 1.1 # Increase speed if self.ball_direction[0] < 0: if self.paddle_position_x[0] + 0.5 <= self.ball_position[ 0] <= self.paddle_position_x[0] + 1.5: if self.paddle_position_y[0] - 0.5 <= self.ball_position[ 1] <= self.paddle_position_y[ 0] + self.PADDLE_SIZE + 0.5: paddle_skew = (self.paddle_position_y[0] + self.PADDLE_SIZE / 2.0 - self.ball_position[1]) / 10.0 hit_paddle(paddle_skew) if self.ball_direction[0] > 0: if self.paddle_position_x[1] - 0.5 <= self.ball_position[ 0] <= self.paddle_position_x[1] + 0.5: if self.paddle_position_y[1] - 0.5 <= self.ball_position[ 1] <= self.paddle_position_y[ 1] + self.PADDLE_SIZE + 0.5: paddle_skew = (self.paddle_position_y[1] + self.PADDLE_SIZE / 2.0 - self.ball_position[1]) / 10.0 hit_paddle(paddle_skew) def run_game_loop(self): self.frame_rendered(0) self.timer = RepeatedTimer(0.1, self.tick) while self.loop: key = self.kp.read_single_keypress().lower() if key == 'a': self.move_paddle(0, -1) elif key == 's': self.move_paddle(0, 1) elif key == 'k': self.move_paddle(1, -1) elif key == 'l': self.move_paddle(1, 1) elif key == 'r': self.init_game() elif not config.HAS_GUI and key == 'q': break self.led_strip.register_callback( self.led_strip.CALLBACK_FRAME_RENDERED, None) self.timer.stop() self.kp.stop()
class Tetris: FIELD_ROWS = config.LED_ROWS+4 # 22 rows in playfield, with only 20 columns visible and 2 coloms border FIELD_COLS = config.LED_COLS+2 # 10 columns in playfield, 2 column border FIELD_ROW_START = 2 FIELD_COL_START = 4 COLORS = [ ( 10, 10, 10), # grey (255, 0, 0), # red (255, 80, 0), # orange (255, 255, 0), # yellow ( 0, 255, 0), # green ( 0, 0, 255), # blue (255, 0, 150), # violet (255, 0, 40), # purple ] TETROMINOS = { None: [[[0], [0], [0], [0]]], 'I': [[[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,2,0,0]], [[2,2,2,2], [0,0,2,0], [0,0,0,0], [0,2,0,0]], [[0,0,0,0], [0,0,2,0], [2,2,2,2], [0,2,0,0]], [[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,2,0,0]]], 'J': [[[6,0,0], [0,6,6], [0,0,0], [0,6,0]], [[6,6,6], [0,6,0], [6,6,6], [0,6,0]], [[0,0,0], [0,6,0], [0,0,6], [6,6,0]]], 'L': [[[0,0,5], [0,5,0], [0,0,0], [5,5,0]], [[5,5,5], [0,5,0], [5,5,5], [0,5,0]], [[0,0,0], [0,5,5], [5,0,0], [0,5,0]]], 'O': [[[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]], [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]], [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]]], 'S': [[[0,3,3], [0,3,0], [0,0,0], [3,0,0]], [[3,3,0], [0,3,3], [0,3,3], [3,3,0]], [[0,0,0], [0,0,3], [3,3,0], [0,3,0]]], 'T': [[[0,7,0], [0,7,0], [0,0,0], [0,7,0]], [[7,7,7], [0,7,7], [7,7,7], [7,7,0]], [[0,0,0], [0,7,0], [0,7,0], [0,7,0]]], 'Z': [[[4,4,0], [0,0,4], [0,0,0], [0,4,0]], [[0,4,4], [0,4,4], [4,4,0], [4,4,0]], [[0,0,0], [0,4,0], [0,4,4], [4,0,0]]] } GAME_OVER_TEXT = [ "GameOverGameOverGameOverGameOverGameOverGameOverGameOve", " ", " GGGG OO ", " G GG O O ", " G aaa mmm mm ee O O v v ee rr ", " G GG a m m m e e O O v v e e r r ", " G G aaaa m m m eeee O O v v eeee r ", " G G a a m m m e O O v v e r ", " GGGG aaaa m m m eee OO v eee r ", " ", " ", "GameOverGameOverGameOverGameOverGameOverGameOverGameOve" ] GAME_OVER_COLORS = { ' ': 0, 'G': 1, 'a': 2, 'm': 3, 'e': 4, 'O': 5, 'v': 6, 'r': 7 } drop_timer = None tetromino_current = 'O' tetromino_form = 0 tetromino_pos_row = FIELD_ROW_START tetromino_pos_col = FIELD_COL_START playfield = [x[:] for x in [[0]*FIELD_COLS]*FIELD_ROWS] random_bag = ['O', 'I', 'S', 'Z', 'L', 'J', 'T'] random_bag_index = len(random_bag)-1 game_over_position = 0 is_game_over = False loop = True def __init__(self, ipcon): self.okay = False self.ipcon = ipcon if not config.UID_LED_STRIP_BRICKLET: print("Not Configured: LED Strip or LED Strip V2 (required)") return if not config.IS_LED_STRIP_V2: self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon) else: self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon) try: self.led_strip.get_frame_duration() if not config.IS_LED_STRIP_V2: print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET)) except: if not config.IS_LED_STRIP_V2: print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET)) else: print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET)) return self.kp = KeyPress(self.ipcon) self.display = TetrisSegmentDisplay(self.ipcon) self.speaker = TetrisSpeaker(self.ipcon) self.okay = True self.led_strip.set_frame_duration(40) if not config.IS_LED_STRIP_V2: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, self.frame_rendered) else: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, self.frame_rendered) self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING) self.init_game() def init_game(self): self.tetromino_current = 'O' self.tetromino_form = 0 self.tetromino_pos_row = self.FIELD_ROW_START self.tetromino_pos_col = self.FIELD_COL_START # Add border to playfield self.playfield = [x[:] for x in [[0]*self.FIELD_COLS]*self.FIELD_ROWS] self.playfield[0] = [255]*self.FIELD_COLS self.playfield[-1] = [255]*self.FIELD_COLS for col in self.playfield[1:-1]: col[0] = 255 col[-1] = 255 # initialize current tetronimo randomly self.tetromino_current = self.get_random_tetromino() self.is_game_over = False if self.drop_timer: self.drop_timer.interval = 1 def frame_rendered(self, length): self.write_playfield() # See http://tetris.wikia.com/wiki/Random_Generator for # details of random bag implementation according to tetris specification def get_random_tetromino(self): self.random_bag_index += 1 if self.random_bag_index >= len(self.random_bag): self.random_bag_index = 0 random.shuffle(self.random_bag) return self.random_bag[self.random_bag_index] def add_tetromino_to_field(self, field, pos_row, pos_col, tetromino, form): for index_col, col in enumerate(self.TETROMINOS[tetromino]): for index_row, color in enumerate(col[form]): if color != 0: row = pos_row + index_row col = pos_col + index_col if row >= 0 and row < self.FIELD_ROWS and col >= 0 and col < self.FIELD_COLS: field[row][col] = color def tetromino_fits(self, field, pos_row, pos_col, tetromino, form): for index_col, col in enumerate(self.TETROMINOS[tetromino]): for index_row, color in enumerate(col[form]): if color != 0: row = pos_row + index_row col = pos_col + index_col if row >= 0 and row < self.FIELD_ROWS and col >= 0 and col < self.FIELD_COLS: if field[row][col] != 0: return False return True def write_playfield(self): if not self.okay: return field = copy.deepcopy(self.playfield) if not self.is_game_over: self.add_tetromino_to_field(field, self.tetromino_pos_row, self.tetromino_pos_col, self.tetromino_current, self.tetromino_form) # Reorder LED data into R, G and B channel r = [] g = [] b = [] frame = [] for row in reversed(range(3, self.FIELD_ROWS-1)): col_range = range(1, self.FIELD_COLS-1) if row % 2 == 0: col_range = reversed(col_range) for col in col_range: r.append(self.COLORS[field[row][col]][0]) g.append(self.COLORS[field[row][col]][1]) b.append(self.COLORS[field[row][col]][2]) frame.append(self.COLORS[field[row][col]][0]) frame.append(self.COLORS[field[row][col]][1]) frame.append(self.COLORS[field[row][col]][2]) if not config.IS_LED_STRIP_V2: # Make chunks of size 16 r_chunk = [r[i:i+16] for i in range(0, len(r), 16)] g_chunk = [g[i:i+16] for i in range(0, len(g), 16)] b_chunk = [b[i:i+16] for i in range(0, len(b), 16)] for i in range(len(r_chunk)): length = len(r_chunk[i]) # Fill up chunks with zeros r_chunk[i].extend([0]*(16-len(r_chunk[i]))) g_chunk[i].extend([0]*(16-len(g_chunk[i]))) b_chunk[i].extend([0]*(16-len(b_chunk[i]))) try: self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i]) except: break else: try: self.led_strip.set_led_values(0, frame) except: return def clear_lines(self, rows_to_clear): if not self.okay: return self.drop_timer.stop() rows_save = {} for to_clear in rows_to_clear: rows_save[to_clear] = self.playfield[to_clear] self.display.increase_line_count(len(rows_to_clear)) self.speaker.beep_delete_line(len(rows_to_clear)) for i in range(6): if i % 2 == 0: for to_clear in rows_to_clear: self.playfield[to_clear] = [255] + [0]*(self.FIELD_COLS-2) + [255] else: for to_clear in rows_to_clear: self.playfield[to_clear] = rows_save[to_clear] time.sleep(0.1) for to_clear in rows_to_clear: for row in reversed(range(1, to_clear+1)): self.playfield[row] = self.playfield[row-1] self.playfield[1] = [255] + [0]*(self.FIELD_COLS-2) + [255] self.drop_timer.start() def check_for_lines_to_clear(self): rows_to_clear = [] for row_index, col in enumerate(self.playfield[1:-1]): to_clear = True for color in col[1:-1]: if color == 0: to_clear = False break if to_clear: rows_to_clear.append(row_index+1) if len(rows_to_clear) > 0: self.clear_lines(rows_to_clear) def new_tetromino(self): self.add_tetromino_to_field(self.playfield, self.tetromino_pos_row, self.tetromino_pos_col, self.tetromino_current, self.tetromino_form) self.tetromino_current = None self.check_for_lines_to_clear() self.tetromino_current = self.get_random_tetromino() self.tetromino_pos_row = self.FIELD_ROW_START self.tetromino_pos_col = self.FIELD_COL_START self.tetromino_form = 0 if not self.tetromino_fits(self.playfield, self.tetromino_pos_row, self.tetromino_pos_col, self.tetromino_current, self.tetromino_form): self.is_game_over = True self.game_over_position = 0 self.drop_timer.interval = 0.15 def next_game_over_step(self): for row in range(len(self.GAME_OVER_TEXT)): for col in range(config.LED_COLS): k = (self.game_over_position+col) % len(self.GAME_OVER_TEXT[0]) self.playfield[7+row][1+col] = self.GAME_OVER_COLORS[self.GAME_OVER_TEXT[row][k]] self.game_over_position += 1 def drop_tetromino(self): if self.is_game_over: self.next_game_over_step() return if self.tetromino_fits(self.playfield, self.tetromino_pos_row+1, self.tetromino_pos_col, self.tetromino_current, self.tetromino_form): self.tetromino_pos_row += 1 else: self.new_tetromino() def move_tetromino(self, row, col, form): if self.is_game_over: return if self.tetromino_fits(self.playfield, self.tetromino_pos_row+row, self.tetromino_pos_col+col, self.tetromino_current, form): self.tetromino_pos_row += row self.tetromino_pos_col += col self.tetromino_form = form if row > 0: # restart drop timer, so we don't drop two tetrominos in a row self.drop_timer.stop() self.drop_timer.start() elif row == 1: # user is at bottom and hits button to go down again self.new_tetromino() def run_game_loop(self): self.frame_rendered(0) self.drop_timer = RepeatedTimer(1.0, self.drop_tetromino) while self.loop: key = self.kp.read_single_keypress() if key == 'a': self.speaker.beep_input() self.move_tetromino(0, -1, self.tetromino_form) elif key == 'd': self.speaker.beep_input() self.move_tetromino(0, 1, self.tetromino_form) elif key == 's': self.speaker.beep_input() self.move_tetromino(1, 0, self.tetromino_form) elif key == 'k': self.speaker.beep_input() self.move_tetromino(0, 0, (self.tetromino_form-1) % 4) elif key == 'l': self.speaker.beep_input() self.move_tetromino(0, 0, (self.tetromino_form+1) % 4) elif key == 'r': self.init_game() elif not config.HAS_GUI and key == 'q': break if not config.IS_LED_STRIP_V2: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, None) else: self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, None) self.drop_timer.stop() self.kp.stop()
def test_count(self): #A{3,5} c = KeyPress.compile("A{3,5}", done=lambda: f.append('done')) f = [] key_press = KeyPress(c) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("match", key_press.status()) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("match", key_press.status()) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("match", key_press.status()) key_press.process_inputs(['A']) self.assertEqual([], f) self.assertEqual("failed", key_press.status())
def test_union(self): # A|a c = KeyPress.compile("A<A>|a<a>", A=lambda: f.append('A'), a=lambda: f.append('a')) f = [] key_press = KeyPress(c) key_press.process_input('A') self.assertEqual(['A'], f) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['a']) self.assertEqual(['a'], f) self.assertEqual("match", key_press.status())
def go_morse(self): print("going morse") self.inputter.set_key_press(KeyPress(self.morseAlphbeth))
def test_zero_or_one(self): # AB?C c = KeyPress.compile("A<A>(B<B>)?C<C>", A=lambda: f.append('A'), B=lambda: f.append('B'), C=lambda: f.append('C')) f = [] key_press = KeyPress(c) key_press.process_inputs(['A']) self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['B']) self.assertEqual(['A', 'B'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['C']) self.assertEqual(['A', 'B', 'C'], f) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['A']) self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['C']) self.assertEqual(['A', 'C'], f) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['A']) self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['B']) self.assertEqual(['A', 'B'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['B']) self.assertEqual(['A', 'B'], f) self.assertEqual("failed", key_press.status())
def test_any_order(self): #A&bc&D c = KeyPress.compile("A<A>&b<b>c<c>&D<D>", A=lambda: f.append('A'), b=lambda: f.append('b'), c=lambda: f.append('c'), D=lambda: f.append('D')) f = [] key_press = KeyPress(c) key_press.process_inputs(['A']) self.assertEqual(['A'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['b', 'c']) self.assertEqual(['A', 'b', 'c'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['D']) self.assertEqual(['A', 'b', 'c', 'D'], f) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['D']) self.assertEqual(['D'], f) self.assertEqual("in progress", key_press.status()) key_press.process_inputs(['D']) self.assertEqual(['D'], f) self.assertEqual("failed", key_press.status()) #------------------ #test all combinations: f = [] key_press.reset() key_press.process_inputs(['A', 'b', 'c', 'D']) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['A', 'D', 'b', 'c']) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['b', 'c', 'A', 'D']) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['b', 'c', 'D', 'A']) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['D', 'A', 'b', 'c']) self.assertEqual("match", key_press.status()) f = [] key_press.reset() key_press.process_inputs(['D', 'b', 'c', 'A']) self.assertEqual("match", key_press.status()) #------------------ f = [] key_press.reset() key_press.process_inputs(['A', 'c', 'b', 'D']) self.assertEqual("failed", key_press.status())
def go_normal(self): print("going normal") self.inputter.set_key_press(KeyPress(self.main_menu))
def go_to_main_menu(self): print("going to main menu...") self.inputter.set_key_press(KeyPress(self.main_menu)) self.startup_timer = None