1 of 59

Processingでゲーム制作

Processing Community Day Tokyo 2019

FAL

作成: 2019-02-02

改定: 2019-02-10

2 of 59

はじめに

3 of 59

Processingを使ったミニゲーム作りを題材として、以下の内容をお話しします。

すみませんが大半が技術の話です。

技術の話:

 画面上でいろんなものがリアルタイムに動くような� プログラムはどうやって作ればいいのか?

表現の話:

 動き、形、色……などなど、魅力的な表現のために� どのような工夫ができるのか?

目的: ゲームを題材に

「技術」と「表現」の選択肢を増やすこと

はじめに

4 of 59

技術の話

5 of 59

  • 多くのゲームプログラムの骨組みは共通している
  • ゲームの骨組みはゲーム以外にも広く応用できる

ゲームプログラムの骨組みを覚えると�幅広い用途に応用できる

技術の話

6 of 59

多くのゲームプログラムの骨組みは共通している

技術の話 > ゲームの骨組み

Collapsing Ideas by FAL

Collapsing Ideas by FAL

Chess-like Game Generator by FAL

例: 2Dシューティング

例: 2Dアクション

例: ボードゲーム

7 of 59

ゲームの骨組みはゲーム以外にも広く応用できる

技術の話 > ゲームの骨組み

CMYK by FAL

Creative Imagery by FAL

Elektro by FAL

Amöba by FAL

Königsberg by FAL

Organic Network by FAL

いずれも、�同じようなプログラムの�土台を使いまわして、�表面だけを変更して�作っています。

8 of 59

以降、サンプルとしてソースコードが多数登場します。

サンプルコードは以下からダウンロードできますので、�分かりにくいところは一つ一つ動かしてみて、�理解を深めていただければと思います。

https://github.com/fal-works/PCD2019-game-samples

サンプルコード

技術の話

9 of 59

  • ゲーム画面上の要素は独自に動き回る
  • 独自に動く主体を作るために「クラス」を使う
  • 複雑なプログラムはクラスという部品を組み立てて作る

基本:「クラス」でプログラムを部品化する

技術の話

10 of 59

ゲーム画面上の要素は独自に動き回る

技術の話 > 基本

parcitleFlow by yasai

Rectangle Microbes by FAL

例:すべての要素が

  単一の規則で動く

例:それぞれの要素が

  独自にバラバラに動く

→ 今回こっちの方を

  やりたい

https://www.openprocessing.org/sketch/422446

11 of 59

独自に動く主体を作るために「クラス」を使う(1)

技術の話 > 基本

  • 画面中央に円を置いて、�その円が一定の方向に動き続けるようにします。
  • 動く方向は、最初にランダムに決定することとします。

どんなソースコードにする?

例題

12 of 59

独自に動く主体を作るために「クラス」を使う(2)

技術の話 > 基本

例題

[ 考え方 ]

  • 円は位置と速度を持っている
  • draw() の中で、毎フレーム、以下を行う
    • 位置を更新する
    • 現在位置に円を表示する

13 of 59

独自に動く主体を作るために「クラス」を使う(3)

技術の話 > 基本

ベタ書きの場合

位置(x座標とy座標)

速度(方向と、1フレームごとのスピード)

表示

位置の更新

setup

draw

Sample: ClassSampleBefore

14 of 59

独自に動く主体を作るために「クラス」を使う(4)

技術の話 > 基本

ベタ書きの場合

位置(x座標とy座標)

速度(方向と、1フレームごとのスピード)

表示

位置の更新

setup

draw

画面上を動く要素に関連する部分を

ひとまとめにしたい!

そこで……

15 of 59

独自に動く主体を作るために「クラス」を使う(5)

技術の話 > 基本

クラスを使う場合

位置

速度

表示

位置の更新

setup & draw の中から、

Elementクラスの部分が

「部品」として切り出された!

Sample: ClassSampleAfter

画面上を動く要素、ということで

Element と名付けたクラスを作ってみた

16 of 59

複雑なプログラムはクラスという部品を組み立てて作る

技術の話 > 基本

------

---------

----

小規模

大規模

ベタ書き

部品化

〇 手軽に

  書ける

× 長すぎて

  破綻

× 最初ちょっと

  面倒

〇 組み合わせで

  自由に

  増築できる

---------------------------

---------

---------------

-------

----------------------------

-----------------------

-------

--------------

---------------------

-----------------

------

-----------------------

-----------

--------------------

-------------------------

---------------------

---------------

---------------------

---------------------

---------------------

!?

※ 図はイメージです

17 of 59

多くのゲームに共通するのは、画面上の要素の

「生成・消滅」「多様性」「相互作用」である

技術の話

生成・消滅

相互作用

多様性

・プレイヤー

・敵

・攻撃

・エフェクト

いろいろいて

バラバラに動く

衝突したり

距離が近いと反応したり

次々と

生まれては

消える

Duel by FAL

18 of 59

  • 可変長リスト
  • 多数の要素を管理する専用のクラス
  • 用済みの要素には退場していただく

生成・消滅: 基本的な構造

技術の話

【この章の目標】�画面中心で要素が生まれ、

画面端で死ぬようにする

19 of 59

増えたり減ったりするものを扱うには可変長リスト(1)

技術の話 > 生成・消滅

さっきのソースコードでは要素を1個しか作れない。

複数作って動かすためには?

  • 最初に、複数のオブジェクトを格納するリストを用意
  • リストには随時、要素を追加する
  • draw() の中で毎フレーム、以下を行う
    • リスト内の全要素を更新
    • リスト内の全要素を表示

20 of 59

増えたり減ったりするものを扱うには可変長リスト(2)

技術の話 > 生成・消滅

1秒ごとに

要素を追加

全要素を

更新

全要素を

表示

※ Elementクラスはさっきと同じ

可変長リストの一種

ArrayList

Sample: ListSample1

複数の要素を

動かせるようになった!

21 of 59

多数の要素を管理する専用のクラスを作ると便利(1)

技術の話 > 生成・消滅

「リスト内の全要素を~~する」

という処理はとても頻繁に使います。

そこで、この部分を司るクラスを作ってみましょう

22 of 59

多数の要素を管理する専用のクラスを作ると便利(2)

技術の話 > 生成・消滅

drawの中から

forループ処理が

切り出された!

全要素を

更新

全要素を

表示

※ Elementクラスはさっきと同じ

Sample: ListSample2

ArrayListを継承。ArrayListの元々の機能に加え、

さらに機能を追加したクラスを作成

23 of 59

用済みの要素には死んでいただき、

死んだ要素には退場していただく(1)

技術の話 > 生成・消滅

さっきのソースコードでは要素の「削除」が無いので、

リストの中身が永遠に増える一方です。

要素が画面端に来たら削除したい。

[ 考え方 ]

  • ある要素が画面端に来たら、その要素は「死んだ」ことにする
  • 要素リストの中に死んだ要素があったら、それをリストから削除する

24 of 59

用済みの要素には死んでいただき、

死んだ要素には退場していただく(2)

技術の話 > 生成・消滅

画面外に出たら

isDeadフラグを立てる

・isDeadフラグの立った要素は

 リストから削除

・ループ途中で削除したいときは

 拡張forではなくIteratorを使う

※ 変更ない部分は省略

死んでいただく処理

退場していただく処理

Sample: ListSample3

25 of 59

  • 可変長リスト
  • 多数の要素を管理する専用のクラス
  • 用済みの要素には退場していただく

生成・消滅: 基本的な構造(再掲)

技術の話

OK?

【この章の目標】�画面中心で要素が生まれ、

画面端で死ぬようにする

26 of 59

  • 条件分岐
  • クラスの継承
  • クラスの継承のデメリット
  • 特徴そのものを切り出して部品化

多様性: 要素に個別の特徴を持たせる

技術の話

【この章の目標】�要素の形がランダムで

●か■のどちらかに

なるようにする

27 of 59

最も素朴な方法は条件分岐

技術の話 > 多様性

※ 変更ない部分は省略

typeに応じて

●か■か、表示方法を変える

Sample: FeatureSample1

28 of 59

クラスの継承によって特徴の違いを出せる(1)

技術の話 > 多様性

簡単な分岐ならさっきのでOKですが

条件分岐に頼っているとifやswitchだらけになって大変です。

他の方法を考えてみよう。

せっかくクラスを使っているのだから、

「●要素のクラス」「■要素のクラス」を作ればよいのでは?

29 of 59

クラスの継承によって特徴の違いを出せる(2)

技術の話 > 多様性

※ 変更ない部分は省略

Elementクラスとその中のdisplay()を

abstract(継承専用)にする

Elementを継承して

種類ごとにクラスを作る。

種類ごとに異なる処理だけを

ここに書く

Element

CircleElement

SquareElement

draw() の中で

new Element() の

部分も要変更 →

Sample: FeatureSample2

30 of 59

  • 継承ツリーが広く深くなると�どこがどうなってるのか分からなくなる
  • 分類が複数あったらどーする!(右図)�※とてもよくある

そこで、継承に頼らない方法が

もう一つあります

クラスの継承は複雑になると破綻する

技術の話 > 多様性

動物

ワンと鳴く

動物

ニャーと鳴く

動物

飛ぶ

動物

飛ばない

動物

ウミネコ

!?

31 of 59

特徴そのものを切り出して部品化すると

より柔軟にできる(1)

技術の話 > 多様性

Element.display() の中身を切り出して

表示専用の部品を作成

自分自身(this)を渡して

処理を委託

(これを委譲という)

※ 表示に限らず、同じ考え方で様々な部品が作れる

Sample: FeatureSample3

32 of 59

特徴そのものを切り出して部品化すると

より柔軟にできる(2)

技術の話 > 多様性

インタフェース:

あるクラスに何ができるのか? を指定するための部品

※2

p5.js だと遥かに簡単で、

クラスまで作らなくても関数オブジェクトを渡せばよいです

※1

なんでこんなことするの? という疑問をお持ちの場合、

解消にはある程度の時間が必要かもしれません。

まずは自分にとって分かりやすい方法でコードを書きつつ、

いろいろ興味の赴くままに調べてみることをお勧めします。

この話面白いんだけど……力不足ですみません……!

33 of 59

  • 条件分岐
  • クラスの継承
  • クラスの継承のデメリット
  • 特徴そのものを切り出して部品化

多様性: 要素に個別の特徴を持たせる(再掲)

技術の話

【この章の目標】�要素の形がランダムで

●か■のどちらかに

なるようにする

OK?

34 of 59

  • すべての組み合わせを判定
  • 「グループ間」と「グループ内」

相互作用: 基本となるのは「総当たり」法

技術の話

【この章の目標】�●と■が衝突したら

どちらも消えるようにする

35 of 59

すべての要素の組み合わせについて

位置関係を判定する(1)

技術の話 > 相互作用

[ 考え方 ]

  • 画面上の要素を●グループと■グループに分ける(別々のリストにする)
  • ElementList クラスに、次のような衝突判定処理を作る
    • まず、1つ目の●と、1つ目の■との距離を調べる。�距離が一定以下だったら「衝突した」ことにする。
    • 次に、1つ目の●と、2つ目の■との……(同上)
    • 1つ目の●について、全部の■を見終わったら、�次は2つ目の●について……(以下略)

36 of 59

すべての要素の組み合わせについて

位置関係を判定する(2)

技術の話 > 相互作用

・他のグループとの衝突を処理する

 collide() を追加

・全ての組み合わせを判定

・距離が一定以下なら(=衝突したら)死

●と■を別々のグループに

●と■を

衝突させる

中身は省略

(Sample参照)

Sample: CollisionSample

37 of 59

(補足)総当たり法の実装は

「グループ間」と「グループ内」で異なる

技術の話 > 相互作用

●グループと

■グループの間

●グループ内

実装例

※ さっきやったのは

  こっち

38 of 59

  • すべての組み合わせを判定
  • 「グループ間」と「グループ内」

相互作用: 基本となるのは「総当たり」法(再掲)

技術の話

OK?

【この章の目標】�●と■が衝突したら

どちらも消えるようにする

39 of 59

集大成: 以上を元に、ゲームらしきものが作れる

技術の話

サンプル『インベーダーもどき』

  • 上から敵●が降ってくる
  • 自分■はマウスで動かせる
  • マウスボタンで弾丸を発射できる
  • 弾丸が敵に衝突すると消せる

Sample: GameSample

40 of 59

主な変更点

技術の話 > 集大成

以下、サンプルスケッチ CollisionSample から

GameSample への主な変更点を記述します。

土台としては CollisionSample の時点で大方できており、

本質的な意味での変更は特にありません。

41 of 59

主な変更点 メイン(GameSample)タブ

技術の話 > 集大成

「自分」「敵」「自分の弾丸」の�3グループを用意

30フレームに1回、「敵」を追加

「自分の弾丸」と「敵」で衝突判定

Sample: GameSample

42 of 59

主な変更点 Elementタブ

技術の話 > 集大成

位置と速度の初期値をゼロに�… new Element() の後で都度設定するように

表示処理のdisplayerと同じく、�更新処理をupdaterとして切り出し�… 「自分」とそれ以外で動き方を変えられるように

Sample: GameSample

43 of 59

主な変更点 ElementComponentタブ

技術の話 > 集大成

弾丸の

表示処理

Elementから切り出した、通常の更新

「自分」の更新用。マウスで移動・発射

Sample: GameSample

44 of 59

集大成: 以上を元に、ゲームらしきものが作れる(再掲)

技術の話

サンプル『インベーダーもどき』

  • 上から敵●が降ってくる
  • 自分■はマウスで動かせる
  • マウスボタンで弾丸を発射できる
  • 弾丸が敵に衝突すると消せる

OK?

Sample: GameSample

45 of 59

表現の話

46 of 59

  • 位置
  • 回転角度
  • スケール

見た目を変えるための諸要素

表現の話

  • 透明度
  • 質感

  • 画面効果

ゲームまたは類似のスケッチを対象に

Processingの基本機能で行える表現を考えると、

基本要素はこんな感じで列挙できるのではないかと思います。

一つずつ確認していき、そのうえで、

どんな組み合わせができるか考えてみましょう。

47 of 59

  • 位置
  • 位置の時間変化=速度
  • 速度の時間変化=加速度

位置

表現の話

例: 落下

   =下方向の加速度

48 of 59

  • 角度
  • 角度の時間変化=角速度
  • 角速度の時間変化=角加速度�(↓の例には含めていません)

回転角度

表現の話

例: 等速で回転

49 of 59

スケール

表現の話

例: サイン波で拡大縮小

50 of 59

位置(加速度)

 +

回転(角加速度)

(それぞれランダムに変化)

ここまでの応用例

表現の話

Kinetic Typography by FAL

51 of 59

表現の話

Geometric Icon Maker by FAL

Amöba by FAL

例:不定形な物体

例:図形の組み合わせ

noise() で

歪ませながら

円を描くと

こうなる

52 of 59

表現の話

例:混色

例:配色

好みの配色を

試行錯誤して探す

手っ取り早いのは

colorMode(HSB) で

色相だけずらす方法

Creative Imagery by FAL

CMYK by FAL

blendMode()

をいろいろ試す

左図は

SUBTRACT

ググると

いろいろ出ます

↑順に

 色相・彩度・明度

 (色相=0 は赤)

53 of 59

透明度

表現の話

fill() でα値を指定して

半透明にする

Transparent by FAL

54 of 59

質感

表現の話

Color Field Painting by FAL

Solid Aether by FAL より画像抜粋

例:グラデーション&影

例:重ね塗り

strokeWeight() で

太線にして

line() を大量に

重ねるとこうなる

filter(BLUR) で

ぼかすと

影っぽいものを

作れる

グラデーションは

地道に

ピクセル操作

55 of 59

ここまでの応用例

表現の話

回転速度

 +

スケール

 +

形(図形の組み合わせ)

Motion Graphics by FAL

56 of 59

ここまでの応用例

表現の話

位置(ランダム移動)

&加速度(落下)

 +

回転速度

 +

色&透明度

 +

質感(背景で、ピクセルごとに�   明るさを変えてザラザラ化)

Rectangle Petals by FAL

57 of 59

画面効果

表現の話

例:画面揺らし

ランダムな値で

translate() すると

画面を揺らせる

これを

呼ぶと

発動

他、半透明な rect() を

画面全体にかけることで

フラッシュや残像効果など……

58 of 59

ここまでの応用例

表現の話

  • 飛び散るパーティクル�(速度を持った破片を飛ばす。� 透明度を徐々に上げて� 上がりきったら殺す)
  • 画面揺らし

Duel by FAL

59 of 59

  • 位置
  • 回転角度
  • スケール

見た目を変えるための諸要素(再掲)

表現の話

  • 透明度
  • 質感

  • 画面効果

好きに組み合わせてみよう!