PSM

Pプログラミング S初心者の Mメモ書き

ProcessingでPythonを使って見た

pythonの描画環境ってmatplotlib一択というところがあると思うんですが,
久方ぶりにprocessingを触っていてたまたまpythonでも書けることに気がついたので試してみました.

Javaの方が早いんだからええやんという話もありますが,
私のようなPythonくらいしか触れないプログラミングニワカ勢が世の中には他にもいらっしゃると信じて……


Processingとは

基本的にJavaベースで,
ちょっとした物理演算をしたりアニメーションを作ったりということが
お手軽にできる環境のことです.

パラメトリックデザインやコンピューテーショナルなアートが試しやすく,
アーティスト向けであるとも言えるらしいとのことです.

Processingの導入

processingで検索して一番上のサイトに行き,Downloadsから,自分の環境にあったものを導入します.
Download \ Processing.org
windows / Linux / os xそれぞれ用意されています.

注意点として1系2系3系があり,使える関数やパッケージが微妙に違うことがあります.
今回は2.2.1を使用してます.


ProcessingでPythonを使う

Python Modeをインストールします.
Skethの右上のJava▽となっている部分をプルダウンして
Add More -> Mode Manager で[Python]と検索します.
インストールが済んだらJava▽となっている部分をプルダウンして▽Pythonに変更します.

これでProcessingでPythonを使う準備が整いました.

また,実行結果をgifアニメーションで保存するために
sketch -> Import Library -> Add Libraryから[gifAnimation]と検索して
gifAnimationというパッケージをついでにインストールしておくと良いでしょう.


迷路生成

いつかの穴掘り方による迷路作成をProcessingに移行して実装してみました.
muromura.hatenablog.com

結果はこんな感じ
f:id:muromura:20180211201854g:plain

まとめ

情報系でない人間にとってはPythonの記法が一番シンプルで見返しても分かりやすい気がします.

流行りのデータサイエンスばかりでなく,
デザインもPythonで簡単にできる環境が整ってきたらいいなあと思っています(人任せ)

コード

ちょっと全体的に見苦しい感じになっていますが,
基本的には開始点と探索方向をランダムにした穴掘り法で迷路を生成してます.
fill()の中が見苦しいのは,描画色を探索順に波打つように変化させたかったからなんです......

add_library('gifAnimation')
import random
import math


def setup():
    global h, w, maze, wl, stt, stt2, ps, dr, gifMaker

    frame.setTitle("Maze")
    h = 45
    w = 45

    maze = [[1 if 0 < i < w - 1 else 0 for i in range(w)] if 0 < j < h - 1 else [
        0 for i in range(w)] for j in range(h)]  # path:0 wall:1
    wl = [[2 * i + 2, 2 * j + 2]
          for i in range(int((w - 1) / 2) - 1) for j in range(int((h - 1) / 2) - 1)]  # prepare wall
    stt = wl.pop(random.randint(0, len(wl) - 1))  # start point
    stt2 = stt
    ps = [stt]  # paths
    maze[stt[1]][stt[0]] = 0  # change start point to 0
    dr = [[-1, 0], [1, 0], [0, -1], [0, 1]]  # direction list of search

    size(h * 10, w * 10)
    frameRate(4000)
    noStroke()
    background(10)

    gifMaker = GifMaker(this, "maze.gif")
    gifMaker.setRepeat(0)
    gifMaker.setDelay(10)


def draw():
    global h, w, maze, wl, stt, stt2, ps, dr, gifMaker

    fill(255, 0, 255)
    rect(stt2[0] * 10, stt2[1] * 10, 10, 10)

    random.shuffle(dr)  # random order of search direction

    for i in range(4):
        nxtx = stt[0] + dr[i][0] * 2
        nxty = stt[1] + dr[i][1] * 2
        nxtx2 = stt[0] + dr[i][0]
        nxty2 = stt[1] + dr[i][1]

        if maze[nxty][nxtx] == 1:
            wl.remove([nxtx, nxty])  # remove searched point
            ps.append([nxtx, nxty])  # append searched point

            maze[nxty][nxtx] = 0  # 2 block
            maze[nxty2][nxtx2] = 0  # middle block

            fill(255, maze[nxty2][nxtx2] * 255 +
                 math.sin(frameCount ** 1.2 / 500) * 255, 255)
            rect(nxtx2 * 10, nxty2 * 10, 10, 10)

            fill(255, maze[nxty][nxtx] * 255 +
                 math.sin(frameCount ** 1.2 / 500) * 255, 255)
            rect(nxtx * 10, nxty * 10, 10, 10)
            break

    if i == 3:  # end of direction
        ps.remove([stt[0], stt[1]])

    gifMaker.addFrame()
    if (len(ps) == 0):
        gifMaker.finish()
        exit()
    else:
        stt = ps[random.randint(0, len(ps) - 1)]  # next point