class Race(Thread): def __init__(self, sizex = 144, sizey = 120, speed = 30, udpHostsAndPorts = [], console_out = False, invert = False): Thread.__init__(self) self.flipmatrix = FlipdotMatrix(udpHostsAndPorts, (sizex, sizey)) if len(udpHostsAndPorts) != 0 else None self.sizex = sizex self.sizey = sizey self.sizez = 100 self.speed = speed self.flipdot_out = len(udpHostsAndPorts) != 0 self.console_out = console_out self.invert = invert self.camera = (0, int(self.sizey/3), -int(self.sizez/2)) self.plain_offset = (-int(self.sizex/2), -int(self.sizey/2)) self.obstacles = [] self.car = Car(0, 0, int(self.sizez/4), int(self.sizex/7), int(self.sizey/7)) self.direction = 0 self.lost = False self.stop = False self.pause = False def run(self): collision = False while not collision and not self.stop: if self.pause: sleep(1./self.speed) continue collision = self.step() image = self.generateRaceImage() if self.invert: self.invertImage(image) if self.flipdot_out: flipImage = FlipdotImage(self.transpose(image)) self.flipmatrix.show(flipImage) if self.console_out: self.printImage(image) sleep(1./self.speed) self.lost = True def moveRight(self): self.direction = +2 def moveLeft(self): self.direction = -2 def togglePause(self): self.pause = not self.pause def transpose(self, image): new_image = [[0 for x in range(self.sizex)] for y in range(self.sizey)] for x in range(self.sizex): for y in range(self.sizey): new_image[y][x] = image[x][self.sizey - y - 1] return new_image def invertImage(self, image): for i in range(len(image)): for j in range(len(image[0])): image[i][j] = 0 if image[i][j] else 1 def printImage(self, image): for y in range(len(image[0])-1, -1, -1): line = "" for x in range(len(image)): line += "." if image[x][y] else " " print line def step(self): collision = False if randint(0,30) == 0: self.obstacles.append(Obstacle(randint(-int(self.sizex/4),int(self.sizex/4)),0,self.sizez, int(self.sizex/7), int(self.sizey/7))) self.car.moveX(self.direction) self.direction = 0 remove = [] for obj in self.obstacles: obj.moveZ(-1) if self.checkCollision(obj, self.car): collision = True if obj.center[2] < self.car.center[2]-10: remove.append(obj) for obj in remove: self.obstacles.remove(obj) return collision def checkCollision(self, obj1, obj2): if self.checkCollisionSingleAxis(obj1, obj2, 0) and self.checkCollisionSingleAxis(obj1, obj2, 1) and self.checkCollisionSingleAxis(obj1, obj2, 2): return True return False def checkCollisionSingleAxis(self, obj1, obj2, index): obj1pos = obj1.center[index] obj1size = obj1.size[index] obj2pos = obj2.center[index] obj2size = obj2.size[index] if obj1pos > obj2pos: if obj1pos - int(obj1size/2) <= obj2pos + int(obj2size/2): return True else: if obj1pos + int(obj1size/2) >= obj2pos - int(obj2size/2): return True return False def generateRaceImage(self): image = [[None for y in range(self.sizey)] for x in range(self.sizex)] for obj in [self.car] + self.obstacles: lower_left = obj.lowerLeft() for x in range(obj.size[0]): for y in range(obj.size[1]): for z in range(obj.size[2]): if obj.obj_matrix[x][y][z] == None: continue plain_point = self.inScope(lower_left[0]+x,lower_left[1]+y,lower_left[2]+z) if plain_point == None: continue if image[plain_point[0]][plain_point[1]] == None: image[plain_point[0]][plain_point[1]] = obj.obj_matrix[x][y][z] for x in range(self.sizex): for y in range(self.sizey): if image[x][y] == None: if self.plain_offset[1] + y > 0: image[x][y] = 1 else: image[x][y] = 0 return image def inScope(self, x, y, z): vector = fliputils.subVector((x,y,z), self.camera) vector = fliputils.normVector(vector) try: factor = (self.sizez - self.camera[2]) / vector[2] except ZeroDivisionError: return None endvector = fliputils.addVector(self.camera, fliputils.multiplyVector(vector, factor)) if self.plain_offset[0] <= endvector[0] and self.plain_offset[0] + self.sizex > endvector[0] + 1 and self.plain_offset[1] <= endvector[1] and self.plain_offset[1] + self.sizey > endvector[1] + 1: return (int(round(endvector[0]-self.plain_offset[0])),int(round(endvector[1]-self.plain_offset[1]))) return None
class GameHandler: def __init__(self, size, speed, udpHostsAndPorts=[], console_out=False, invert=False, panel_defaults=False, ball_speed=6, player_speed=3, scores_file="scores"): self.size = size self.speed = speed bar_size = (round(self.size[0] / 18), round(self.size[1] / 5)) ball_size = (round(self.size[0] / 18), round(self.size[0] / 18)) self.scores_file = scores_file total_scores = self.loadScores() self.players = (Player( bar_size, (round(self.size[0] / 18), round(self.size[1] / 2)), speed=player_speed, total_score=total_scores[0]), Player(bar_size, (self.size[0] - round(self.size[0] / 18), round(self.size[1] / 2)), speed=player_speed, total_score=total_scores[1])) self.inputHandler = InputHandler(self.players) self.ball = Ball(ball_size, self.get_center(), speed=ball_speed) self.stop = False self.flipmatrix = FlipdotMatrix( imageSize=size) if panel_defaults else ( FlipdotMatrix(udpHostsAndPorts, size) if len(udpHostsAndPorts) != 0 else None) self.flipdot_out = True if self.flipmatrix else False self.console_out = console_out self.invert = invert def loop(self): playing = False while not self.stop: t = time() new_game = self.step() if new_game: playing = False self.ball.stop() image = self.generatePongImage() if not playing: playing = all([x.active for x in self.players]) if playing: self.ball.change_direction((1, 0)) if self.invert: pass if self.flipdot_out: flipImage = FlipdotImage(image.T) score_string = "%d - %d" % (self.players[0].score, self.players[1].score) flipImage.blitTextAtPosition(score_string, xPos=self.get_center()[0] - 2 * (len(score_string) - 1), yPos=2 * round(self.size[1] / 12)) total_score_string = "%d - %d" % (self.players[0].total_score, self.players[1].total_score) flipImage.blitTextAtPosition(total_score_string, xPos=self.get_center()[0] - 2 * (len(total_score_string) - 1), yPos=(round(self.size[1] / 12))) if not playing: if not self.players[0].active: flipImage.blitTextAtPosition( "Press Left", xPos=self.players[0].upper_right()[0] + 2, yPos=self.size[1] - self.players[0].upper_right()[1]) if not self.players[1].active: flipImage.blitTextAtPosition( "Press Left", xPos=self.players[1].lower_left()[0] - 46, yPos=self.size[1] - self.players[1].upper_right()[1]) self.flipmatrix.show(flipImage) if self.console_out: self.printImage(image) wait = (1. / self.speed) - (time() - t) if wait > 0: sleep(wait) else: print("Too slow!") def printImage(self, image): for y in range(len(image[0]) - 1, -1, -1): line = "" for x in range(len(image)): line += "." if image[x][y] else " " print(line) def get_center(self): return (round(self.size[0] / 2), round(self.size[1] / 2)) def generatePongImage(self): image = np.zeros(self.size, dtype=np.byte) for player in self.players: player.draw(image) self.ball.draw(image) return image def step(self): for player in self.players: player.move(self.size) self.ball.move(self.size) self.ball.bounce(self.players, self.size) ball_state = self.checkBallExit() if ball_state: self.ball.center = self.get_center() if ball_state == 1: self.ball.change_direction((-1, 0)) self.players[1].score_up() else: self.ball.change_direction((1, 0)) self.players[0].score_up() new_game = False if self.players[0].score == 5 or self.players[1].score == 5: new_game = True self.players[0].reset( (round(self.size[0] / 18), self.get_center()[1]), new_game) self.players[1].reset((self.size[0] - round(self.size[0] / 18), self.get_center()[1]), new_game) self.saveScores() return new_game def saveScores(self): with open(self.scores_file, "w") as f: f.write("%d %d" % (self.players[0].total_score, self.players[1].total_score)) def loadScores(self): try: with open(self.scores_file, "r") as f: lines = f.readlines() scores = [int(x) for x in lines[0].split(" ")] except: scores = (0, 0) return scores def checkBallExit(self): return (1 if self.ball.lower_left()[0] <= 0 else (2 if self.ball.upper_right()[0] >= self.size[0] else 0))
class Clock: def __init__(self, sizex=144, sizey=120, radius=50, udpHostsAndPorts=[], hour_hand=True, minute_hand=True, second_hand=True, console_out=False, run_once=False, update_interval=0, api_defaults=False): if len(udpHostsAndPorts) != 0: self.matrix = FlipdotMatrix(udpHostsAndPorts, (sizex, sizey)) self.flipdot_out = True elif api_defaults: self.matrix = FlipdotMatrix(imageSize=(sizex, sizey)) self.flipdot_out = True else: self.matrix = None self.flipdot_out = False self.sizex = sizex self.sizey = sizey self.radius = radius self.center = (int(self.sizex / 2), int(self.sizey / 2)) self.hour_hand = hour_hand self.minute_hand = minute_hand self.second_hand = second_hand self.console_out = console_out self.update_interval = update_interval if update_interval != 0 else ( 1 if self.second_hand else 30) self.run_once = run_once def loop(self): oldImage = FlipdotImage(self.generateClockImage()) try: while True: flipImage = FlipdotImage(self.generateClockImage()) if (self.flipdot_out and flipImage.serializeImageArray() != oldImage.serializeImageArray()): self.matrix.show(flipImage) oldImage = flipImage if self.run_once: break sleep(self.update_interval) except KeyboardInterrupt: return def generateClockImage(self): image = [[0 for y in range(self.sizey)] for x in range(self.sizex)] time = datetime.datetime.now().time() image[self.center[0]][self.center[1]] = 1 hour_coords = self.circlePoint( math.radians((((time.hour % 12) / 12.) if time.hour else 0) * 360 + 270 + (time.minute / 2))) minute_coords = self.circlePoint(math.radians(time.minute * 6 + 270)) second_coords = self.circlePoint(math.radians(time.second * 6 + 270)) for i in range(60): degree = i * 6 + 90 radian = -math.radians(degree) coords = self.circlePoint(radian) if not i % 5: self.addLine(image, coords, self.center, 3, 1) else: self.addLine(image, coords, self.center, 1) if self.hour_hand: self.addLine(image, self.center, hour_coords, int(self.radius / 3), 1) if self.minute_hand: self.addLine(image, self.center, minute_coords, int(self.radius / 2)) if self.second_hand: self.addLine(image, self.center, second_coords, self.radius - int(self.radius / 8.)) tmp_image = [] for y in range(self.sizey): tmp_image.append([]) for x in range(self.sizex): tmp_image[-1].append(image[x][y]) image = tmp_image if self.console_out: for y in range(self.radius * 2): line = "" for x in range(self.radius * 2): line = line + ("." if image[ (self.center[1] - self.radius) + y][(self.center[0] - self.radius) + x] else " ") print(line) return image def circlePoint(self, t): return (int(round(self.radius * math.cos(t))) + self.center[0], int(round(self.radius * math.sin(t))) + self.center[1]) def addLine(self, image, source, destination, length, thickness=0): vector = self.subVector(destination, source) vector = self.normVector(vector) perp_vector = (-vector[1], vector[0]) for i in range(1, length + 1): coords = self.addVector(source, self.multiplyVector(vector, i)) image[int(round(coords[0]))][int(round(coords[1]))] = 1 if thickness > 0: perp_start = self.addVector( coords, self.multiplyVector(perp_vector, thickness)) for j in range(0, thickness * 2 + 1): perp_coords = self.addVector( perp_start, self.multiplyVector(perp_vector, -j)) image[int(round(perp_coords[0]))][int(round( perp_coords[1]))] = 1 def normVector(self, v): length = math.sqrt(sum([i**2 for i in v])) new_v = [] for i in range(len(v)): new_v.append(v[i] / length) return tuple(new_v) def subVector(self, v1, v2): res = [] for i in range(len(v1)): res.append(v1[i] - v2[i]) return tuple(res) def addVector(self, v1, v2): res = [] for i in range(len(v1)): res.append(v1[i] + v2[i]) return tuple(res) def multiplyVector(self, v, multiplier): return tuple([i * multiplier for i in v])
class Clock: def __init__(self, sizex = 144, sizey = 120, radius = 50, udpHostsAndPorts = [], hour_hand = True, minute_hand = True, second_hand = True, console_out = False, run_once = False, update_interval = 0, api_defaults = False): if len(udpHostsAndPorts) != 0: self.matrix = FlipdotMatrix(udpHostsAndPorts, (sizex, sizey)) self.flipdot_out = True elif api_defaults: self.matrix = FlipdotMatrix(imageSize=(sizex,sizey)) self.flipdot_out = True else: self.matrix = None self.flipdot_out = False self.sizex = sizex self.sizey = sizey self.radius = radius self.center = (int(self.sizex/2), int(self.sizey/2)) self.hour_hand = hour_hand self.minute_hand = minute_hand self.second_hand = second_hand self.console_out = console_out self.update_interval = update_interval if update_interval != 0 else (1 if self.second_hand else 30) self.run_once = run_once def loop(self): oldImage = FlipdotImage(self.generateClockImage()) try: while True: flipImage = FlipdotImage(self.generateClockImage()) if (self.flipdot_out and flipImage.serializeImageArray() != oldImage.serializeImageArray()): self.matrix.show(flipImage) oldImage = flipImage if self.run_once: break sleep(self.update_interval) except KeyboardInterrupt: return def generateClockImage(self): image = [[0 for y in range(self.sizey)] for x in range(self.sizex)] time = datetime.datetime.now().time() image[self.center[0]][self.center[1]] = 1 hour_coords = self.circlePoint(math.radians((((time.hour%12)/12.) if time.hour else 0)*360 + 270 + (time.minute/2))) minute_coords = self.circlePoint(math.radians(time.minute*6+270)) second_coords = self.circlePoint(math.radians(time.second*6+270)) for i in range(60): degree = i*6 + 90 radian = - math.radians(degree) coords = self.circlePoint(radian) if not i % 5: self.addLine(image, coords, self.center, 3, 1) else: self.addLine(image, coords, self.center, 1) if self.hour_hand: self.addLine(image, self.center, hour_coords, int(self.radius / 3), 1) if self.minute_hand: self.addLine(image, self.center, minute_coords, int(self.radius / 2)) if self.second_hand: self.addLine(image, self.center, second_coords, self.radius - int(self.radius/8.)) tmp_image = [] for y in range(self.sizey): tmp_image.append([]) for x in range(self.sizex): tmp_image[-1].append(image[x][y]) image = tmp_image if self.console_out: for y in range(self.radius*2): line = "" for x in range(self.radius*2): line = line + ("." if image[(self.center[1]-self.radius)+y][(self.center[0]-self.radius)+x] else " ") print(line) return image def circlePoint(self, t): return (int(round(self.radius*math.cos(t))) + self.center[0], int(round(self.radius*math.sin(t))) + self.center[1]) def addLine(self, image, source, destination, length, thickness = 0): vector = self.subVector(destination, source) vector = self.normVector(vector) perp_vector = (-vector[1], vector[0]) for i in range(1,length+1): coords = self.addVector(source, self.multiplyVector(vector, i)) image[int(round(coords[0]))][int(round(coords[1]))] = 1 if thickness > 0: perp_start = self.addVector(coords, self.multiplyVector(perp_vector, thickness)) for j in range(0, thickness*2+1): perp_coords = self.addVector(perp_start, self.multiplyVector(perp_vector, -j)) image[int(round(perp_coords[0]))][int(round(perp_coords[1]))] = 1 def normVector(self, v): length = math.sqrt(sum([i**2 for i in v])) new_v = [] for i in range(len(v)): new_v.append(v[i]/length) return tuple(new_v) def subVector(self, v1, v2): res = [] for i in range(len(v1)): res.append(v1[i]-v2[i]) return tuple(res) def addVector(self, v1, v2): res = [] for i in range(len(v1)): res.append(v1[i]+v2[i]) return tuple(res) def multiplyVector(self, v, multiplier): return tuple([i*multiplier for i in v])
class Race(Thread): def __init__(self, sizex=144, sizey=120, speed=30, udpHostsAndPorts=[], console_out=False, invert=False): Thread.__init__(self) self.flipmatrix = FlipdotMatrix( udpHostsAndPorts, (sizex, sizey)) if len(udpHostsAndPorts) != 0 else None self.sizex = sizex self.sizey = sizey self.sizez = 100 self.speed = speed self.flipdot_out = len(udpHostsAndPorts) != 0 self.console_out = console_out self.invert = invert self.camera = (0, int(self.sizey / 3), -int(self.sizez / 2)) self.plain_offset = (-int(self.sizex / 2), -int(self.sizey / 2)) self.obstacles = [] self.car = Car(0, 0, int(self.sizez / 4), int(self.sizex / 7), int(self.sizey / 7)) self.direction = 0 self.lost = False self.stop = False self.pause = False def run(self): collision = False while not collision and not self.stop: if self.pause: sleep(1. / self.speed) continue collision = self.step() image = self.generateRaceImage() if self.invert: self.invertImage(image) if self.flipdot_out: flipImage = FlipdotImage(self.transpose(image)) self.flipmatrix.show(flipImage) if self.console_out: self.printImage(image) sleep(1. / self.speed) self.lost = True def moveRight(self): self.direction = +2 def moveLeft(self): self.direction = -2 def togglePause(self): self.pause = not self.pause def transpose(self, image): new_image = [[0 for x in range(self.sizex)] for y in range(self.sizey)] for x in range(self.sizex): for y in range(self.sizey): new_image[y][x] = image[x][self.sizey - y - 1] return new_image def invertImage(self, image): for i in range(len(image)): for j in range(len(image[0])): image[i][j] = 0 if image[i][j] else 1 def printImage(self, image): for y in range(len(image[0]) - 1, -1, -1): line = "" for x in range(len(image)): line += "." if image[x][y] else " " print line def step(self): collision = False if randint(0, 30) == 0: self.obstacles.append( Obstacle(randint(-int(self.sizex / 4), int(self.sizex / 4)), 0, self.sizez, int(self.sizex / 7), int(self.sizey / 7))) self.car.moveX(self.direction) self.direction = 0 remove = [] for obj in self.obstacles: obj.moveZ(-1) if self.checkCollision(obj, self.car): collision = True if obj.center[2] < self.car.center[2] - 10: remove.append(obj) for obj in remove: self.obstacles.remove(obj) return collision def checkCollision(self, obj1, obj2): if self.checkCollisionSingleAxis( obj1, obj2, 0) and self.checkCollisionSingleAxis( obj1, obj2, 1) and self.checkCollisionSingleAxis( obj1, obj2, 2): return True return False def checkCollisionSingleAxis(self, obj1, obj2, index): obj1pos = obj1.center[index] obj1size = obj1.size[index] obj2pos = obj2.center[index] obj2size = obj2.size[index] if obj1pos > obj2pos: if obj1pos - int(obj1size / 2) <= obj2pos + int(obj2size / 2): return True else: if obj1pos + int(obj1size / 2) >= obj2pos - int(obj2size / 2): return True return False def generateRaceImage(self): image = [[None for y in range(self.sizey)] for x in range(self.sizex)] for obj in [self.car] + self.obstacles: lower_left = obj.lowerLeft() for x in range(obj.size[0]): for y in range(obj.size[1]): for z in range(obj.size[2]): if obj.obj_matrix[x][y][z] == None: continue plain_point = self.inScope(lower_left[0] + x, lower_left[1] + y, lower_left[2] + z) if plain_point == None: continue if image[plain_point[0]][plain_point[1]] == None: image[plain_point[0]][ plain_point[1]] = obj.obj_matrix[x][y][z] for x in range(self.sizex): for y in range(self.sizey): if image[x][y] == None: if self.plain_offset[1] + y > 0: image[x][y] = 1 else: image[x][y] = 0 return image def inScope(self, x, y, z): vector = fliputils.subVector((x, y, z), self.camera) vector = fliputils.normVector(vector) try: factor = (self.sizez - self.camera[2]) / vector[2] except ZeroDivisionError: return None endvector = fliputils.addVector( self.camera, fliputils.multiplyVector(vector, factor)) if self.plain_offset[0] <= endvector[0] and self.plain_offset[ 0] + self.sizex > endvector[0] + 1 and self.plain_offset[ 1] <= endvector[1] and self.plain_offset[ 1] + self.sizey > endvector[1] + 1: return (int(round(endvector[0] - self.plain_offset[0])), int(round(endvector[1] - self.plain_offset[1]))) return None