Processingプログラミング
会津大学

Processingの基礎

1

Processing❖ マサチューセッツ工科大学メディアラボが開発した，電子アートやビジュアルデザインを扱いやすい統合開発環境❖ 可視化が簡単なため，初心者でも学びやすい❖ プログラミング言語であるJavaやPythonなどで使用❖ この講習で行うこと❖ アニメーションの基礎❖ 物理シミュレーション，ゲームプログラミング

2

Processing❖ 基本的にスケッチブックとよばれる統合開発環境に，プログラムを記述して実行する❖ 右上の部分が Python であれば，Pythonで実行できる❖ ▶ をクリックすることで，プログラムを実行できるプログラムを実行

幅800，高さ600のウィンドウが表示

3

ウィンドウを作成❖ size(w, h): 幅w，高さhのウィンドウを作成する❖ w : 整数値，幅(ピクセル)❖ h : 整数値，高さ(ピクセル)❖ Processingの座標系
原点(0, 0)❖ ウィンドウの左上: 原点❖ 横方向: X軸方向
❖ 右向きが正方向❖ 縦方向: Y軸方向
❖ 下向きが正方向+Y+X

4

Processingでの描画方法❖ 関数を実行することで，Processingで描画できる
1. 点を描く，線を描く，図形を描く関数
2. 線の色・太さ，塗りつぶしなどのオプションを決める関数❖ ウィンドウの大きさを指定して，オプションを決めた後，描画するプログラムを書くのが，Processingの基本❖ 線を描くサンプルプログラム
size(600, 400)
# ウィンドウの⼤きさ
strokeWeight(4.5)# 線の太さstroke(50.0, 60.0, 200.0)# 線の⾊
line(100.0, 100.0, 300.0, 200.0) # 線を描画

5

基本的な描画関数の紹介❖ strokeWeight(float w): 線（枠線）の太さをwに設定する❖ noStroke(): 線（枠線）を描画しない設定にする❖ line(float x0, float y0, float x1, float y1): 直線を引く❖ 座標(x0, y0)から，座標(x1, y1) へ線を描画❖ rect(float x, float y, float w, float h): 長方形を描く❖ 四角形の左上頂点(x, y)とし，幅w，高さhの長方形❖ ellipse(float x, float y, float w, float h): 楕円を描く❖ 中心座標(x, y)とし，幅w，高さhである楕円を描画❖ 幅と高さを同じ値にすると円となる6

基本的な描画関数の紹介❖ stroke(float r, float g, float b): 線（枠線）の色を設定❖ fill(float r, float g, float g): 塗りつぶし色を設定❖ 赤成分r，緑成分g，青成分bは0から255の値とする❖ 赤成分r，緑成分g，青成分bの関係（代表例）
赤成分r

緑成分g

青成分b

黒000

白255255255

赤25500緑02550青00255黄255

255

0

マゼンタ

255

0255

シアン0255

255

色見本

7

基本的な描画関数の紹介❖ background(float r, float g, float b): 背景色を設定❖ 赤成分r，緑成分g，青成分bは0から255の値とする❖ background(float w): 背景色を設定❖ 1つの値しか指定しない場合，0(黒)〜255(白)の範囲でグレースケールの背景となる❖ 成分wの関係（代表例）
w
064
128
192
255

色見本

8

描画の注意
❖ プログラムは上から下に順番に実行されるため，最初に描いた図形が最背面，最後に描いた図形が最前面となる❖ 設定した線の太さ，線の色，塗りつぶし色に関しては，設定を変更しない限り，状態が継続される❖ ウィンドウを作成した後，ウインドウの幅は変数width，ウインドウの高さは変数heightとして利用できる❖ これらの変数は，Processingが定義している変数なので，宣言することなく利用できる❖ ウインドウの中心の座標は(width/2, height/2)となる

9

練習問題
1. 日本の国旗を描いてください❖ 幅 : 高さ ＝ 3 : 2
2. オランダの国旗を描いてください❖ 幅 : 高さ ＝ 3 : 2
3. スイスの国旗を描いてください❖ 幅 : 高さ ＝ 1 : 1

10

繰り返し処理との融合❖ グラデーションの描画例
size(810, 300) # 画⾯の⼤きさnoStroke()# 枠線を消す# ⾊を変えながら81個の⻑⽅形を描画する# ⻘⾊から⾚⾊へ
for i in range(81):fill(i * 255 / 80, 0, 255 - i * 255 / 80)rect(i * 10, 0, 10, 300)

Processingを使用したアニメーションの基礎

11

アニメーションの基礎❖ 静止画を高速に切り替えることでアニメーションが実現できる❖ アニメーションにおいて，1秒間あたりに処理させる静止画像（フレーム）数のことをフレームレートとよぶ❖ 単位: fps（60fpsは1秒間に60フレーム切り替えている）❖ Processingも同様に，各フレームを高速に切り替えることで，アニメーションを実現する❖ 初期化を行うsetupブロック（setup関数）と，フレームを描画するdrawブロック（draw関数）を定義する

12

アニメーションプログラム概要❖ setup: 最初に1度だけ実行される❖ ウインドウのサイズ設定など1度だけ必要な処理をこの中に記述する❖ draw: フレームを表示するたびに実行される❖ ここで記載していることがアニメーションで表示される
デフォルトでは1秒間に60回実行される
def setup():# 初期化処理をここに書く

setup

最初の1回だけ実行

def draw():# フレームごとの処理をここに書く

draw

1秒間に60回実行13

アニメーション例1# 1回だけ実⾏される
def setup():size(255, 255) # ウィンドウのサイズ# setupを終えた後，繰り返し実⾏される
def draw():
background(192)# 背景⾊を決める
z = frameCount % 256
fill(z, 255 - z, 255) # 円の塗りつぶし⾊を決める
ellipse(z, z, 30, 30) # 円を描画する❖ frameCount: Processingが用意している特別な変数❖ プログラムが開始されてから表示されたフレーム数を格納❖ 0から始まり，drawが終わると1つ増える❖ 剰余を利用して，変数zの値が0から255となるように設定

14

アニメーション例2# 1回だけ実⾏される
def setup():size(255, 255) # ウィンドウのサイズ# setupを終えた後，繰り返し実⾏される
def draw():z = frameCount % 256
fill(z, 255 - z, 255) # 円の塗りつぶし⾊を決める
ellipse(z, z, 30, 30) # 円を描画する❖ アニメーション例1のプログラムから『background(192)』を削除して実行した場合，どのようになるか確かめてください，
また，どうしてそうなるか，その理由を考えてください15

アニメーション失敗例# 1回だけ実⾏される
def setup():size(255, 255) # ウィンドウのサイズ# setupを終えた後，繰り返し実⾏される
def draw():x = 0background(192)# 背景⾊を決める
fill(0, 200, 200)
# 円の塗りつぶし⾊を決める
ellipse(x, x, 30, 30) # 円を描画する
x += 1❖ このプログラムは，アニメーションとしては成立しない❖ その理由を考えてみてください16

グローバル変数❖ setup関数，draw関数の外側で変数を宣言することで，プログラム（setup関数，draw関数）のどこからでも使用可能な変数のこと❖ プログラムが終わるまで，変数は存在する❖ draw関数が終わっとしても，値を維持できる❖ 関数の中で宣言した変数はその関数でしか利用できない# グローバル変数の宣⾔
x = 10def setup():# 初期化処理をここに書く
def draw():# フレームごとの処理をここに書く

17グローバル変数の使い方❖ 関数中からグローバル変数の値を変更する場合，❖ グローバル変数の値を変更する関数の先頭に global 変数名 と記述する必要がある# グローバル変数の宣⾔
x = 10def setup():# 初期化処理をここに書く
def draw():# フレームごとの処理をここに書く
global x # グローバル変数を変更するため
x += 1# グローバル変数を変更

18

アニメーション成功例# グローバル変数の宣⾔
x = 0# 1回だけ実⾏される
def setup():size(255, 255) # ウィンドウのサイズ# setupを終えた後，繰り返し実⾏される
def draw():
global x
background(192)# 背景⾊を決める
fill(0, 200, 200)
# 円の塗りつぶし⾊を決める
ellipse(x, x, 30, 30) # 円を描画する
x += 1x = x % 255

Processingを使用した物理ゲームの基礎

19

Processingの応用例❖ マウス・キーボードとのインタラクション❖ メディアファイル（画像，音楽，動画など）との連携❖ 電子回路との連携❖ スマートフォン，Webとの連携❖ 本講義は，ステップバイステップ形式で，簡単な物理ゲームである『ハエ叩きゲーム』の基礎を学ぶ20

Step 0 | ウィンドウを設定❖ 画面の大きさ，背景色を設定する❖ 以下のプログラムでは，❖ 画面の大きさを幅800，高さ800❖ 背景色を白❖ としているdef setup():size(800, 800)

# ウィンドウのサイズ

def draw():
background(255) # 背景⾊を決める

21

Step 1 | ハエ叩きをマウスの位置で変更❖ ハエ叩きをマウスの位置で変更できるようする❖ Processingでは，マウスの位置を取得できる特別な変数
mouseX, mouseYという変数が存在する❖ ハエ叩きの中心位置の座標を(mouseX, mouseY)にすれば良い
def draw():
background(255)sWidth = 20
# ハエ叩きの幅
sHeight = 20
# ハエ叩きの⾼さ
fill(198, 204, 255) # ハエ叩きの⾊# ハエ叩きを描画する
rect(mouseX - sWidth / 2, mouseY - sHeight / 2, sWidth, sHeight)

22

Step 2 | ハエを動かす❖ ハエの位置，速度をグローバル変数として宣言し，drawメソッドで更新する❖ 速度は1フレームで動くピクセル量となる❖ x方向とy方向の変化量を指定することで，平面を1方向に移動することができる❖ 三角比，ベクトルなどの考え方で以下は自明
11xとyの変化量が同じ場合，45度の方向で進む23

Step 2 | ハエを動かす❖ ハエの位置，速度をグローバル変数として宣言し，drawメソッドで更新する❖ 速度は1フレームで動くピクセル量となる❖ グローバル変数の追加箇所
fX = 50 # ハエのx座標
fY = 50 # ハエのy座標
fVx = 9 # ハエのx⽅向に対するの更新量
fVy = 2 # ハエのy⽅向に対するの更新量
def setup():size(800, 800) # ウィンドウのサイズ

24

Step 2 | ハエを動かす❖ drawメソッドの追加箇所
def draw():
global fX, fY, fVx, fVy # グローバル変数を変更する
background(255)sWidth = 20
# ハエ叩きの幅
sHeight = 20
# ハエ叩きの⾼さ
fill(198, 204, 255) # ハエ叩きの⾊# ハエ叩きを描画する
rect(mouseX - sWidth / 2, mouseY - sHeight / 2, sWidth, sHeight)
fill(0, 0, 0)# ハエの⾊ellipse(fX, fY, 10, 10) # ハエを描画する
fX += fVx
# ハエのx座標を更新する
fY += fVy# ハエのy座標を更新する

25

Step 3 | ハエを壁で反射させる❖ 上端，下端，左端，右端にハエが衝突した場合，ハエが反射するようにする❖ 「衝突した場合」と「ハエを反射する」をプログラムで表現する❖ 「衝突した場合」のプログラム表現❖ 上端に衝突する: ハエのy座標 < 0❖ 下端に衝突する: ハエのy座標 > ウィンドウ高さ❖ 左端に衝突する: ハエのx座標 < 0❖ 右端に衝突する: ハエのx座標 > ウィンドウ幅

上端衝突

左端衝突

右端衝突

下端衝突

26

Step 3 | ハエを壁で反射させる❖ ハエを反射するをプログラムで表現するために❖ 上端に衝突した場合❖ x方向の速度は変化せず，y方向の速度は逆になる❖ 下端に衝突した場合❖ x方向の速度は変化せず，y方向の速度は逆になる❖ 左端に衝突した場合❖ x方向の速度は逆になり，y方向の速度は変化しない❖ 右端に衝突した場合❖ x方向の速度は逆になり，y方向の速度は変化しない27

Step 3 | ハエを壁で反射させる❖ まとめると❖ 上端・下端に衝突した場合（ハエのy座標が0より小さい場合，または，ウィンドウ高さより大きい場合）❖ x方向の速度は変化せず，y方向の速度は逆になる❖ 左端・右端に衝突した場合（ハエのx座標が0より小さい場合，または，ウィンドウ幅より大きい場合）❖ x方向の速度は逆になり，y方向の速度は変化しない28

Step 3 | ハエを壁で反射させる
def draw():# 途中からfill(0, 0, 0)# ハエの⾊ellipse(fX, fY, 10, 10) # ハエを描画する
fX += fVx
# ハエのx座標を更新する
fY += fVy
# ハエのy座標を更新する
if fY < 0 or fY > height: # 上下端衝突
fVy *= -1
if fX < 0 or fX > width: # 左右端衝突
fVx *= -1

29

Step 4 | ハエ叩きとハエの衝突判定❖ ハエと壁との衝突判定を参考にして，ハエ叩きとハエの衝突判定を行う❖ ハエ叩き（四角形）の内部にハエが存在するかどうかを条件とすれば良い❖ ハエ叩きの左端と上端の座標を求めるとプログラムしやすい❖ ハエ叩きの幅と高さから，ハエ叩きの右端と下端の座標を求めることができる❖ 次のページのプログラムは衝突したと判断した場合，ハエの位置，速度をランダムな値にしている❖ random(n): 0以上n未満の実数を返す❖ 座標は整数値なので，整数型にキャストする30

Step 4 | ハエ叩きとハエの衝突判定
def draw():# 途中から
if fX < 0 or fX > width: # 左右端衝突
fVx *= -1
sLeft = mouseX - sWidth / 2# ハエ叩きの左端座標
sRight = mouseX + sWidth / 2# ハエ叩きの右端座標
sTop = mouseY - sHeight / 2# ハエ叩きの上端座標
sBottom = mouseY + sHeight / 2 # ハエ叩きの下端座標# ハエ叩きとハエの衝突（衝突後，ハエの位置と速度を変更する）
if sLeft <= fX and sRight >= fX and sTop <= fY and sBottom >= fY:
fX = int(random(width + 1))
fY = int(random(height + 1))
fVx = int(random(10)) + 1
fVy = int(random(10)) + 1

31

Step 5 | 文字列によるインタラクション❖ 画面に文字列を出力させ，ゲームの見栄えを良くする❖ ハエ叩きとハエが衝突した回数を表示する❖ 衝突した回数を保存する変数はグローバル変数とする❖ Processingでは，以下の方法で文字列を画面に出力できる❖ textSize(size): 文字の大きさをsizeにする❖ text(data, x, y): 文字列dataを座標(x, y)に出力する

32

Step 5 | 文字列によるインタラクション# グローバル変数の初期化に以下を追加
count = 0 # 衝突回数
def draw():
global fX, fY, fVx, fVy, count # グローバル変数を変更する# 中略# ハエ叩きとハエの衝突（衝突後，ハエの位置と速度を変更する）
if sLeft <= fX and sRight >= fX and sTop <= fY and sBottom >= fY:# 中略
fVy = int(random(10)) + 1
count += 1 # 衝突数を増やす# 衝突数を表⽰する
textSize(16)text(str(count), 20, 20) # ⽂字列にキャストする33

Step ∞ | 魔改造❖ これまでのプログラムを参考にして，ゲームを魔改造する❖ ハエを一定数倒せば，ゲームクリアにする❖ ハエの数を増やす❖ ハエの移動スピードを変化させる❖ ハエ叩きの進入禁止領域を定義し，ハエ叩きがそこに触れるとゲームオーバーにする❖ etc･･･❖ 発想次第でいくらでもゲームを魔改造できます❖ 発想力向上，プログラミング向上につながる