またRaspberryPiですが、今度はお絵かきアプリを作ってみました。折れ線(Polyline)をつないで絵を描きます。ジョイスティックでカーソルを移動し、ボタンを押すと、そこを折れ点とし、さらに伸ばす、を繰り返します。
ななめの描き方のアルゴリズムがあるみたいですね。一応それらしく実装してみましたが…まあご覧の通りです。
そう言えば、signal.pause()
を今回初めて知りました。いいですね〜。
# sensehatutil.py
from sense_hat import SenseHat, ACTION_PRESSED, ACTION_HELD, ACTION_RELEASED
import numpy as np
from enum import Enum
red = (255, 0, 0)
blue = (0, 0, 255)
yellow=(255,255,0)
purple=(128,0,128)
green=(0,255,0)
indigg=(75,0,130)
orange=(255,128,0)
pink=(255,193,203)
black=(0,0,0)
height = 8
width = 8
sense = SenseHat()
def Initialize():
sense.clear()
sense.set_rotation(0)
def CreateImageArray():
return np.zeros((height, width, 3), np.uint8)
def SetArrayToPixels(imageArray):
sense.set_pixels(imageArray.reshape(height*width,3))
def PutVertex(imageArray, pt, color):
imageArray[pt[1], pt[0]] = color
return imageArray
def PutRect(imageArray, lower, upper, color):
for col in range(lower[0], upper[0]+1):
imageArray[lower[1]:upper[1]+1, col] = color
return imageArray
def PutLine(imageArray, p1, p2, color):
if abs(p1[0]-p2[0]) > abs(p1[1]-p2[1]):
if p1[0] == p2[0]:
rs = min(p1[1], p2[1])
re = max(p1[1], p2[1]) + 1
imageArray[rs:re, p1[0]] = color
return imageArray
def f(x):
return (float(p2[1])-float(p1[1]))/(float(p2[0])-float(p1[0]))*(float(x)-float(p1[0]))+float(p1[1])
col_range = range(min(p1[0], p2[0]), max(p1[0], p2[0])+1)
for col in col_range:
row = int(round(f(col)))
imageArray[row, col] = color
else:
if p1[1] == p2[1]:
cs = min(p1[0], p2[0])
ce = max(p1[0], p2[0]) + 1
imageArray[p1[1], cs:ce] = color
return imageArray
def f(y):
return (float(p2[0])-float(p1[0]))/(float(p2[1])-float(p1[1]))*(float(y)-float(p1[1]))+float(p1[0])
row_range = range(min(p1[1], p2[1]), max(p1[1], p2[1])+1)
for row in row_range:
col = int(round(f(row)))
imageArray[row, col] = color
return imageArray
def PutPolyline(imageArray, ptArray, doClose, color):
p1 = []
p_prev = []
for pt in ptArray:
if p1 == []:
p1 = pt
p_prev = pt
continue
imageArray = PutLine(imageArray, p_prev, pt, color)
p_prev = pt
if doClose:
imageArray = PutLine(imageArray, p_prev, p1, color)
return imageArray
# main.py
from signal import pause
import sensehatutil as sh
sh.Initialize()
apex = (3,3)
ptArray = list()
def AddApex(event):
global apex, ptArray
if event.action != sh.ACTION_PRESSED:
return
ptArray.append(apex)
def MoveApex(event):
global apex
if event.action != sh.ACTION_PRESSED:
return
d = event.direction
if d == 'right':
apex = (min(apex[0] + 1, sh.width-1), apex[1])
elif d == 'left':
apex = (max(apex[0] - 1, 0), apex[1])
elif d == 'up':
apex = (apex[0], max(apex[1] - 1, 0))
elif d == 'down':
apex = (apex[0], min(apex[1] + 1, sh.height-1))
def Reflesh():
global apex, ptArray
img = sh.CreateImageArray()
ptArrayTmp = list()
for pt in ptArray:
ptArrayTmp.append(pt)
ptArrayTmp.append(apex)
img = sh.PutPolyline(img, ptArrayTmp, False, sh.orange)
for pt in ptArray:
img = sh.PutVertex(img, pt, sh.purple)
img = sh.PutVertex(img, apex, sh.red)
sh.SetArrayToPixels(img)
sh.sense.stick.direction_middle = AddApex
sh.sense.stick.direction_right = MoveApex
sh.sense.stick.direction_left = MoveApex
sh.sense.stick.direction_up = MoveApex
sh.sense.stick.direction_down = MoveApex
sh.sense.stick.direction_any = Reflesh
Reflesh()
pause()