LoginSignup
2
1

More than 1 year has passed since last update.

SenseHAT でお絵かきアプリ

Last updated at Posted at 2021-04-18

またRaspberryPiですが、今度はお絵かきアプリを作ってみました。折れ線(Polyline)をつないで絵を描きます。ジョイスティックでカーソルを移動し、ボタンを押すと、そこを折れ点とし、さらに伸ばす、を繰り返します。

ななめの描き方のアルゴリズムがあるみたいですね。一応それらしく実装してみましたが…まあご覧の通りです。

drawpoly1.jpg

そう言えば、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()
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1