メディア基礎演習II [F]コンピュータゲーム
担当:白井暁彦
([email protected] / K1-405室)
<演習手順書>
ver.1.0
(1)目的
Processingをつかったゲームプログラミングの基礎とクラスの概念を学ぶ
(2)背景
通常のプログラミングスタイルとゲームプログラミングにおいて本質的に異なる手法は何であろうか。ビデオゲームの プログラミングにおいては、初期化に加え、描画ループとインタラクションに最適化された高速かつ動的(Dynamic) に動作するコーディングスタイルがとられるべきであろう。また最近の(C++以降の)プログラミング言語ではオブジ ェクト化が中心にあり、その中でも「クラス」の概念を身につけ、使いこなすことでプログラムを効率よく設計するこ とは大変重要である。
本演習ではプログラミング言語「Processing」を使い、物理・数学、関数およびクラスの応用を通して、イン タラクティブなビジュアルコンピューティングの基本となるテクニックと自己表現を体得することができる。
(3)理論
3-1: Processingとは
ProcessingとはJavaベース、マルチプラットフォームで動作する統合開発環境(IDE)で、ビジュアリゼーション、ア ーティスト教育のためにMITのBenjamin Fry, Casey Reasらによって開発されたオープンソースプロジェクトである。書 式においてはJava, C/C++との高い互換性を持ち、Windows、MacOSX、Linux環境で単体動作するアプリケーションや Webページが生成できる。3D、音響、ネットワークなどのライブラリを標準で持つ。また外部ライブラリを追加するこ とによって、TwitterやARといった最新のテクノロジを使ったインタラクティブアプリケーションの開発が可能である。
3-2: ゲームプログラミング:初期化とループ
Processingにおけるプログラミングの基本は、初期化を担当するsetup()関数と、描画を担当するdraw()関数に集 約できる。リアルタイムグラフィックスを基本としているため、ゲームプログラミングの基本に近い点が多い。
本演習では「初期化とループ上の処理を分ける」という点に注目しよう。たとえば、画像を表示するために「ファイ ルから読み込み、メモリ上にある画像オブジェクトを表示する」といった処理が必要になるが、一度しか処理する必要 がないファイルからの読み込みはsetup()で処理されるべきであり、draw()内で処理されるべきではない。同様に物理シ ミュレーションやヒューマンインタフェースからの処理、音楽なども適切な場所で初期化とループが分けて処理される べきである。
3-3: 自分で学習する楽しみを覚える
本演習においては、Processingに付属のExamplesを使い、事前に用意されたサンプルプログラムを改造するところ から始める(そのほうが失敗が少なく、楽しみながら、自己表現を学べるからである)。わからない関数やオブジェク トがあれば、ダブルクリックしてCtrl+Shift+F「Find in Reference(リファレンスを調べる)」することでブラウザが起動
し、フォーマットによって整備されたマニュアルを読むことができる。つまりわからないことは自分で即座に調べられ る(ネットがある環境なら日本語訳されたマニュアルもある)。このようにして、Processingは自学自習によりゲーム プログラミングを(無料で)学ぶ上で、大変有益な開発環境であるといえる。
3-4: ゲームプログラミングにおけるクラス化
しかしながら、BASIC的な、プロシージャルな(≒手続き的な)プログラミングスタイルでは大規模なゲームプロ グラミングには対応できない。時流としてはオブジェクト指向、具体的にはクラスを使ったプログラミングが主流 である。オブジェクト指向とクラスは密接な関係があるが混乱しやすく、またクラスの概念は日本語では表現しづ らいものであり、プログラミング初学者がつまづく点であるが、本演習では実装を通してクラスの概念を体得する。 戦闘シーンがあるRPGやや弾幕飛び交うシューティングゲームを開発することを想像してみよう。『ダメージにあ わせて数字でエフェクトを描く』、『弾が当たったら自機がやられる』、と文字で書くのは簡単である。しかし「ダメ ージにあわせて」、「弾が当たった」といった状態を、いきなり個々に実装していっては、書かなければならないコ ードは大量になり、スパゲティのように複雑に絡み合い、デバッグの難しい、プロジェクト内の他者にとって理解しが たく再利用しづらいコードになる。
前述のシューティングゲームの場合、自機、敵、敵弾といったオブジェクトがありえる。そしてそれぞれの初期位置 や現在のオブジェクト座標(position)、方向や速度(direction,velocity)、色や画像、アニメーションやエフェクト、そし てゲームとして最も重要な要素である、オブジェクト同士の当たり判定(hit-test)が必要になる。これらの値(member) と処理(method)を組にして扱ったものが「クラス」である、という理解でゲームプログラミング上は問題ない。 クラスには「学校の組(クラス)のように」上層下層があったり、隣のクラスがあったりする。クラスを「ひと組」とし て扱い、役割として学級委員や美化委員、掲示係がいる。「このポスターを掲示せよ」という処理に対して、各クラス の「掲示する処理」が呼ばれる。個別の方法が異なれば、それはクラス内の「掲示する」という処理で定義されている べきである。またクラスは「継承」できる。上の学年で存在する"風紀委員"が下の学年では存在せず、細かいことが定義 されていない、という場合、上位のクラスの処理がそのまま引き継がれる。ある程度の自由度や汎用性のある処理を組 にして扱うことが便利である。このように概念を理解し、興味があれば、トラディショナルなRPGにおける「モンスタ ー」といったクラスや「たたかう」というコマンドでの実装を考えると理解の助けになる。
本演習においては、このクラスの概念をProcessingにおける物理シミュレーション的なアニメーションで実装する。 もちろんクラス化しなくても実装可能であるが、クラス化する場合としない場合を想定しつつ、見た目や機能に改良を 加えていくなど、実際に手を動かしてみてほしい。
(4) 方法
以下の手順に従って実験する。わからないことがあれば、すぐに担当教員やTAに相談すること(Processingはオ ープンソースであり、動作の完全性については保証の限りではない、そのため情報の共有がとても重要である)。 4-2: [Setup] Processingをセットアップし、Examplesを遊んでみる
4-3: [Modify] ExamplesのClockを改造し、MyClockをつくる
4-4: [Export] WebページとEXEをExportし、人に渡すものとしてデザインする
4-5: [Draw] SetupとDrawを使いゼロからProcessingによるアニメーションプログラムを書く 4-6: [Class] クラス化されたBounceBallアニメーション
4-7: [Game] Example-Topics-Motion-Collisionでテニスゲームのソースコードを改変しながら理解する
4-1: レポート及び課題
【レポート課題1】
「Examplesを試し、スクリーンショットを撮影し、動作やソースコードの内容を簡単に解説する」
【レポート課題2】
「オリジナルの『MyClock』を作成し、コメント付きWebページを作成、制作過程と内容を解説する」
【レポート課題3】
「BounceBallプログラムの実行結果とソースコードを解説する」
レポートは2週目終了後の翌週水曜日までに1通、ポストに提出する。目安としては1週目に課題1および課題2を実習
しておくべきである。2週目は進度により4-4から開始し課題3を完了させるため、最低でも4-5までは自力で挑戦し、2週 目の2限においてはレポートのほとんどが完成している状態を目指してほしい。考察のための課題やリンクは巻末に用意 してある。レポートの執筆に関しては白井研のホームページ(http://shirai.la)のDownloadコーナーにレポートのテンプ レートがあるので参考にされたい。構造化された作文のサンプルになっているので、特に提出されたレポートの作文上 の構成が十分な品質でない場合、6点以下の採点になる可能性がある。それ以上の評価としては、考察が中心となる。オ リジナルの作品としての表現性も評価するが、技術的関心、着眼、チャレンジがあるかといった点も高く評価する。逆 に、単なる感想や推測にとどまる考察、著作権侵害などは大幅に減点する。カラーでなければ伝わらない内容で、かつ カラー印刷環境がない場合、モノクロプリンタで印刷し、表紙コメント欄に「カラー原稿につきメールで別途提出しま す」と明記し、PDFやDOCを提出してかまわない。開発したプログラムを掲示したWeb(URL)による別途提出も歓迎 である。その他詳細については研究室(K1-405)を早目に訪問して相談されたい。
4-2: [Setup] Processingをセットアップし、Examplesを遊んでみる
多くの学生は他の講義・演習により既にProcessingがインストールされているようである。ここでは、セ ットアップが終わっていない学生を想定してダウンロードから、Examplesの実行までを簡単に解説する。
まずProcessingのホームページ(http://processing.org/)をブラウザで表示し「Download Processing」のリンク
からダウンロードページに進む。本稿執筆時点の最新版(1.2.1)のWindows版、「Without Java」ではないリンクをクリ ックして入手する(61.7MB)。ダウンロードが終了したら、ZIPファイルをハードディスクのどこでもよいので解凍する。 ちなみに2000ファイル以上あるので、USBメモリ等ではかなりの時間を要するので注意。
解凍したファイルの中に「Processing.exe」があるのでダブルクリックして起動する。
右のようなIDEが起動すればインストールは成功である。Explorerで「Processing.exe」を右クリックして、
「送る」メニューから「デスクトップ(ショートカット作成)」をしておくと、デスクトップから起動しやすい。 インストールが終わったら、まずはFile→Examples→Topics→Motion→Bounceを選んで、実行してみる。
実行は「Sketch」メニューから「Run」(Ctrl+R)、もしくは再生ボタンで右のような実行結果が表示される。実行 ウインドウの「×」かEscキーもしくは停止ボタンで終了できる。
【レポート課題1】「Examplesを試し、スクリーンショットを撮影し、動作やソースコードの内容を簡単に解説する」 Examplesの中から2-3種類気に入ったものを探し、スクリーンショットを取得し(PrintScreenキー、多くのPCでは Fn+PrtScr)、mspaintやWordに直接貼り付けておくといい。ソースコードを読み、実行結果を解説するが、わかる範 囲でよい。ただしいい加減な嘘や想像を盛り込まないこと。多くのExamplesでは、プログラムの冒頭に英語で解説が書 かれているので、その英語を訳せばそれなりにレポートはできる(もちろん意味不明な訳ではレポートにならない)。 中には動作しないExamplesもあるだろう、そういったものも「なぜ動かないのか」を調査してレポートしてみるとよい
(以下は作例)。
【例】Bounce(Topics→Motion→Bounce)
画面端を検出してボールが跳ね返るようなアニメーションを描くサンプル。 冒頭の
「int size = 60;」でボール(Ellipse)の幅を指定しているが、あまり大きな値(たとえば size=200)を指定するとボールの反射が働きすぎてうまく動かない。この問題は画面サイズ を大きくすることで回避できる(スクリーンショット参照)。
解説や理解のためにソースコードを改変する事を推奨する。保存する場合は
MyDocuments\Processingフォルダに保存する。ソースコードはテキストとしてWordに張 り付けてもよいが、上図のように色分けされた状態でスクリーンショットを張り付けるの もわかりやすいので良いだろう。
4-3: [Modify] ExamplesのClockを改造し、MyClockをつくる
次に、サンプルプログラムを改造して、オリジナルの時計アプリをつくる。よくできたサンプルを改変し、関数の 使いこなしおよび、リファレンスを参照して「外部画像の読み込み」を自力でできるようにすることに意識すること。 まずは、プログラム Clockを起動(File->Examples->Basics->Input->Clock)する。
ちなみにこの「Clock」には小さなバグが用意されており、Processing1.2.1ではそのまま実行してもグレーのウィン ドウが表示されるだけで時計らしいものは表示されない。まずはこのバグを取り、「MyClock」として保存しよう。 修正箇所は1か所、「void draw2() {」を「void draw() {」とするだけである。
→
「File」メニューから「Save as...」で「MyClock」として保存する。この以下MyClockにて以下の作業を行う。 (1) Windowを大きくする
→ size(400,400); //☆値は自由に変えてみるとよい。 (2) 配色を変える
以下の例を参考に配色を変えてみよう。
background(128,0,0); → background(128,0,0); //背景色(R,G,B) fill(0,80,0); → fill(0,80,0); //時計盤の色(R,G,B)
(3) 背景に画像を置く
まず画像ファイルを用意して、sketch->Add File... を選択し、背景画像を読み込む。
画像ファイルを保存する、右のようなdataフォルダができていれば成功である。その他の画像の追加も同じ手順であ る。
次に画像ファイルを背景に呼び出すための、プログラムを以下に記述する。
PImage b; → イメージファイル用のオブジェクト: b を用意 (冒頭で記述) b = loadImage("OO.jpg"); → 変数に呼び出したいイメージファイル名を指定 (setup()内で記述)
image(b, 0, 0); → image(変数名, 貼り付ける場所のX座標, Y座標) (draw()内で記述) 変数名やファイル名は各自で適当なものを割り当てて構わない。これらを指定の場所に記述し、実行する。
読み込むファイルは事前に用意しておくこと。
この際に、画像のサイズに合わせて背景のサイズを変更する必要があることに注意する。
著作権に注意して、自分ならではの「MyClock」を作成しよう。特に、次のセクション「人に渡すものとしてデザイ ンする」ということを意識して、「だれに・どんな」を意識して作ってみよう。
→
4-4: [Export] WebページとEXEをExportし、人に渡すものとしてデザインする
「File」メニューの「Export Application」をつかって、単体で動作するEXEファイルを書き出すことができる。メ ニューを選ぶと次のようなダイアログが表示されるので、動作プラットフォームを「Windows」のみチェックを入れ
「Export」を押す(他のチェックボックスもぜひ試してみてほしい)。
表示された「application.windows」フォルダには「MyClock.exe」がいるはずである。このファイルをダブルクリック することで、フルスクリーンで表示される「MyClock」実行されることを確認する。
次に「File」メニュー「Export」によって、作成した自分のアプリケーションをブラウザ内のJavaAppletで動作する ページとして書き出し(Export)することができる。作成後、表示されたフォルダ内にある「index.html」をInternet ExplorerやFirefoxなどのブラウザで読み込んでみよう(ファイルをブラウザのウィンドウにドロップするか、ファイルメ ニューで開く)。
ブラウザ上で作成したアプリケーションが動作し、表示されているはずである。冒頭のコメントなどもそのまま転記 されるので、(今回の演習ではWebサーバーへのアップロードは行わないが)実際に人に見せるものとして書き直して みよう。
【レポート課題2】
「オリジナルの『MyClock』を作成し、コメント付きWebページを作成、制作過程と内容を解説する」
4-5: [Draw] SetupとDrawを使いゼロからProcessingによるアニメーションプログラムを書く
「File」メニュー「New」によって新規プロジェクトを作成する。上記のソースコードのように短いプログラムを setupとdrawに分けて書いてみよう。
int x,y,r; void setup() { x=0; y=0; r=10; int bg = 128;
background(bg,0,0); }
void draw() {
background(0); fill(128); ellipse(x++,y++,r,r); }
実行すると画面を左から右に横切る円のアニメーションが見えるはずである。
Processingでは、起動時に一度だけしか読み込まれないsetup()と、描画のたびに読み込まれるdraw()がある(先ほど のClockの例でもあるように、正確にその名前である必要がある)。
またここでは、変数のスコープ(≒生存期限)について学ぶことができる。ローカル変数int bgはsetup() の内部でのみ有効であり、draw()内で利用しようと思っても「初期化されていない」というエラーになる。
シンプルな一例を書くことは大変勉強になる。ここで画像の読み込みや処理などを独自に実験し、繰り返し実行結果 を確認することで、Processingにおけるコーディングスタイルを完全に理解しよう。
4-6: [Class] クラス化されたBounceBallアニメーション
カラフルなボールが力学に従って弾む「BouceBall」アニメーションをクラスを使って表現する(書籍「Build with Processing[改定版]」p.197~200:リスト3-8-bより引用)。
以下に<Main>と<BounceBall>のプログラムを記述する。まずは先ほどと同様に、「File」から「New」を選択 し、新規プロジェクトを作成する。プロジェクト名は各々が決めてもかまわないが、「BounceBallDemo」などわかりや すく記述した方がよい。
<Main>
int numBalls = 100; //ボールの数
BounceBall[] balls = new BounceBall[numBalls]; //BounceBallオブジェクトの配列 void setup(){
size(400,400);
colorMode(HSB, numBalls); background(numBalls - 1); frameRate(10);
//配列の初期化
for(int i = 0; i < numBalls; i++){ //初期値を入れてBounceBallオブジェクトを作る balls[i] = new BounceBall(
width / 2, 10,
random(-20, 20), random(-30, 0), random(5, 20),
color(random(numBalls), numBalls * 0.6, numBalls - 1) );
}}
void draw(){
fadeToWhite(); //background(128);でもよい //各BounceBallオブジェクトを動かして描画 for(int i = 0; i < numBalls ; i++){
balls[i].move(); balls[i].draw(); }}
void fadeToWhite(){ //モーションブラーエフェクト noStroke();
fill(numBalls -1, numBalls * 0.1); rectMode(CORNER);
rect(0, 0, width, height); }
以下の<BounceBall>クラスは、タブを変えて打ち込む。
タブの作成は、タブ欄の右端にある矢印をクリックし、New Tab(Ctrl+Shift+N)を選択。その後タブの名前を
「BouceBall」にする。
<BounceBall>
float GRAVITY = 3; //床に落ちる重力の値 float FRICTION = 0.8; //跳ね返るときの減衰率 //BounceBallクラス
//落下して跳ねるボール public class BounceBall{ //メンバー変数
float x, y; //物体の座標 float spx, spy; //物体のスピード float radius; //物体の半径 color ball_color; //ボールの色 //コンストラクタ(初期化) BounceBall(
float _x, float _y, float _spx, float _spy, float _radius,
color _ball_color
){ //メンバー変数の初期化 x = _x;
y = _y; spx = _spx; spy = _spy; radius = _radius;
ball_color = _ball_color; // このクラスの跳ね返り } // 判定メソッドを呼び出す //ボールを動かすメソッド
public void move(){ spy += GRAVITY; x += spx;
y += spy;
this.bounce(); //このクラスの跳ね返り判定メソッドを呼び出す } //ボールをかくメソッド
public void draw(){ noStroke(); fill(ball_color); println(ball_color);
ellipse(x, y, radius*2, radius*2); } //跳ね返り判定メソッド
private void bounce(){ float bounceMinX = radius;
float bounceMaxX = width - radius; float bounceMaxY = height - radius; if(x < bounceMinX || x > bounceMaxX){ spx = -spx * FRICTION;
if(x < bounceMinX) x = bounceMinX - (x - bounceMinX); if(x > bounceMaxX) x = bounceMaxX - (x - bounceMaxX); }
if(y > bounceMaxY){ spy = -spy * FRICTION;
if(y > bounceMaxY) y= bounceMaxY - (y - bounceMaxY); }
}}
実行結果を以下に示す。
画面上部から、大量のカラフルなボールが落ちてきて、跳ね返り続ける。跳ね返りの減衰率(FRICTION)に従って徐 々にバウンドが弱まるのを確認してほしい。
【レポート課題3】
「BounceBallプログラムの実行結果とソースコードを解説する」
【注意すべきこと】
・HSBカラーモードを使って指定している(色相・明度・彩度、0~100)。 ・frameRate(10); → frameRate(60); とすることで高速に実行される。 ・クラス内の反射部分のコードは間違えやすいのでよく注意すること
・color型とfloat型などを混同しないこと
・クラスの初期化(コンストラクタ)の書き方を覚えよう ・デバッグにはprintln()が便利
4-7: [Game] ExampleのCollisionでテニスゲームのソースコードを改変しながら理解する
ここから先は、時間に余裕がある演習者のみすすめるべきである。これまでの技術と知識を活用し、Exampleの Collision(File->Examples->Topics->Motion->Collision)を利用し、クラシックなテニスゲームのソースコードの改変を 行い、ゲームプログラミングの理解を深める。
起動が確認できたら、Clockと同じように「File」メニューから「Save as...」で「MyCollision」として保存する。 このMyCollisionにて以下の作業を行う。以下は、自習のためのヒントである。
(1) ボールのスピードを速くする
この時、ただボールのスピードを速くするとパドルをすり抜けてしまう。パドルとの接触判定がうまくいっていない ので、判定文の条件を変えてより確実な当たり判定を実装しよう。
(2) クラス化・重力の追加する
BounceBallの理解を応用して、重力とクラス化を実装してみよう。
(3) 追加ライブラリによる効果音の実装
minim等追加ライブラリを利用することによってBGMや効果音(SE)を再生することができる。 (Examples-
>library)
(5) まとめ・考察
以上のような手順で、2週に分けて計画的にレポートを書きながら演習を進めること。
以下に考察のためのネタを提供しますので、興味を持てたものを中心に各々5行以上は書いてくること。 ・Processingを使って何が作れるか。有名な作品があれば紹介。
・Processingを作った人々について。 ・オープンソースとは何か。
・Processingのライセンスについて。 ・自作のゲーム制作および解説。
・Processingの外部プラグインを探し、サンプルプログラムを作って解説。 ・できるだけ短いコードで虹を描いてみる。
(6) 参考図書・URL
参考図書、Webサイトなど、レポートには参考にしたソースを明記すること。
<ウェブサイト>
Processing(本家・公式) http://processing.org/
Wikipedia「Processing」 http://ja.wikipedia.org/wiki/Processing Processing日本語サイト http://processing.jp/about/
Proce55ing(日本語情報) http://tetraleaf.com/p5_reference_alpha/info.html Ben Fry ( The aesthetics + computation in MIT ) http://acg.media.mit.edu/people/fry/ Casey Reas (GroupC) http://www.groupc.net/
JRC313(Game) http://www.jrc313.com/processing/game/play.html
こどものもうそうBlog(米光一成:「ぷよぷよ」の作者)http://blog.lv99.com/?eid=823769
<書籍>
「Build with Processing[改定版]」 前川 峻志, 田中 孝太郎, ビー・エヌ・エヌ新社
「WiiRemoteプログラミング」 白井 暁彦, 小坂 崇之, くるくる研究室, 木村 秀敬, オーム社開発部