enchant.jsの利用
(動画の解説で使用したバージョンからアップデートしています.ごめんなさい!)
enchant.jsとは?
- 株式会社UEIによって開発された国産のJavaScriptのライブラリ. Wikipediaの解説
- 2016年以降,残念ながらアップデートやサポートは行われていません(事業移管)
- 主としてゲーム開発を(効率良くできるように)支援することを目的として制作されたもの
- 少し古いフレームワークながら,情報やサンプルは極めて豊富
- Windows, Mac, iPhone/iPad, Androidのすべてで動作するアプリケーションを作ることも可能(マルチプラットフォーム)
- ユーザ(や他のプログラム)が起こした操作(イベント)に対する処理を記述していく,という,いわゆるイベント駆動型のプログラミングが必要になります.
演習でのenchant.jsの使い方
例えば,昔の本家のトップページ(今は,サイトが見当たりません)で動いていたデモ(白いクマが右へ左へ移動する)は,次のようなHTMLファイルを作成してブラウザで読み込めば再現できます.(マーカー部のように指定する)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <!DOCTYPE html> <html> <head> <title>enchant.jsサンプル</title> <meta charset="utf-8" /> <script src="http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/enchant.js" type="text/javascript"></script> <!-- プラグインも使う場合は必要なscriptタグを下記に追加 --> <script src="http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/plugins/tl.enchant.js" type="text/javascript"></script> </head> <body> <script type="text/javascript"> enchant(); // おまじない var IMG = "http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/images/chara1.png" var game = new Game(320, 320); game.preload(IMG); game.onload = function () { var bear = new Sprite(32, 32); bear.image = game.assets[IMG]; game.rootScene.addChild(bear); bear.frame = [6, 6, 7, 7]; // select sprite frame bear.tl.moveBy(288, 0, 90) // move right .scaleTo(-1, 1, 10) // turn left .moveBy(-288, 0, 90) // move left .scaleTo(1, 1, 10) // turn right .loop(); // loop it }; game.start(); </script> </body> </html> |
上記のプログラムで黄色で網掛けしている部分はプラグインや画像の読み込みを行っています. enchant.js本体,及びそのプラグインはそれぞれ,
http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/enchant.js http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/plugins/XXX.js
に置いてあります.また,enchant.jsの開発元が提供している画像や音声素材も下記のディレクトリ配下に置いてあります.
http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/images/ (実態は: /home/wikiwiki/wiki/public_html/csd/js/images/ にあります.) http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/sounds/ (実態の場所は同様です.)
自分たちのプログラムでは,HTMLの<script>タグ
部やJavaScript内の必要箇所で,適宜これらを読み込んでください.
- 12〜30行目を別ファイル(sample.jsとか)にして,
<script type="text/javascript" src="sample.js"></script>
などと書き換えてもOKです.
事前に理解しておいた方が良いこと
enchant.jsを利用する場合,いくつかのオブジェクトを組み合わせて使用します.基本的なものは以下の三つです.
Core(Game)オブジェクト
- ゲーム全体を管理して,動かすシステム
- ゲームの基本的な機能を提供するもの,つまり,このCoreオブジェクトを中心にゲームは動く
- デフォルトでrootSceneという名前のSceneオブジェクトを一つ持つ
Sceneオブジェクト
- 視覚要素(Nodeオブジェクト)をまとめたもの
- 例えば,スタート画面のSceneオブジェクト,プレイ画面のSceneオブジェクト,とか
- 階層的に重ねることができる(スタック管理)
- プレイ画面のSceneオブジェクトに,スコア表示のSceneオブジェクトを重ねる,とか
Nodeオブジェクト
- ゲームを構成する視覚要素
- 実際にはNodeオブジェクトを継承したオブジェクトを使う
Node系オブジェクト | 目的 |
---|---|
Sprite |
図や画像を表示 |
Label |
文字を表示 |
Map |
ゲームマップを表示 |
enchant.js を用いて作るゲームのひな型は次のような形です.
1 2 3 4 5 6 7 8 9 10 11 12 13 | enchant(); // 1 window.onload = function() { var game = new Game(320, 320); // 2 game.preload('preload1.gif', 'preload2.wav'); // 3 game.onload = function () { // ここに処理を書く }; game.start(); // 4 } |
- 1行目でenchant.jsを初期化.必須.
- 5行目でGameオブジェクトを作成(Coreオブジェクトでも可).この場合,横320px,縦320pxのゲーム画面を作成する,ということ
- 7〜10行目がGameオブジェクトの初期設定にあたる.
- 7行目は素材のプリロード(使いたい画像や音楽ファイルを読み込んで,使えるようにしておく)
- 8〜10行目が,ゲームが動作開始したときに実行されるコード.ここがメイン.gameオブジェクトのonloadメソッドに,ゲームを開始したときに実行したいプログラムを書く形で記述する.シーンを作ったり,メニューを作ったり,・・・
- 12行目でゲーム開始.(イベント待ちの無限ループ開始)
なお,7〜10行目には本当に必要なコードだけ(例えばメニューだけとか)書いておいて,ゲーム本体のコードは別のところに書いて呼び出したり呼び出せるようにしたりするのが普通です.
さらに,enchant.js を用いて作るゲームではいくつかの状態が存在し,それぞれの状態に応じたイベントに対してどういう処理をするか,をJavaScriptで記述する形になります.(非同期型イベント処理プログラミング)
主要なイベントの例については,このページの下の方を参照してください.
自学用の参考サイト
以上を踏まえて,次のサイトで学んでください.
- ドットインストールのenchant.js入門(全12回)
- 1本3分程度の動画が12本あり,短い時間で手早く概要がつかめます
- @IT(アットマークIT)の連載記事
- 5本の記事があり,全てを読み終える頃には簡単なゲームが作れるようになります.この講義では,このサイトで勉強することを強くお勧めします.
enchant.js 怒涛の 100 tips(サービスが終了しているようです.)
ちょっとした動作確認をしたいときは・・・
講義側の立場からはあまり推奨はしませんが,以下のサイトではオンラインの(enchant.jsによる)開発・実行環境が提供されていて,ブラウザさえ使えれば(手元に何も環境がなくても)開発が進められます.
* code9leap enchant.jsの開発元が提供しているサイト (サービスが終了しているようです)
使い方は説明しません(推奨していないので)が,使うこと自体を妨げている訳ではありませんので,興味のある人は積極的に自分で調べて使ってみましょう.ただし,これらのサイトで利用できるenchant.jsは講義で準備したバージョンよりも古いので気をつけましょう.
enchant.jsのオブジェクト
enchant.jsのオブジェクトの種類は以下の通りです.
- Label・・・文字列表示
- Sprite・・・画像表示
- Map・・・タイルを並べて作った画をうを1つの大きな画像にする
- Entity・・・Sprite/Lavel/Mapの継承元
- Scene・・・描画オブジェクトを貼り付けることが可能な画面オブジェクト
- Group・・・複数の描画オブジェクトを1つにまとめられる
- Surface・・・画像や図形のデータを保持
- Node・・・表示オブジェクトの継承元
- Core・・・ゲーム画面やメインループ,シーンを管理
- EventTarget・・・イベントリスナを管理
- Sound・・・サウンドを管理
継承ツリー
オブジェクト間の継承ツリーは以下のようになります.基本的に,子オブジェクトは,親オブジェクトのメソッドやプロパティを利用できます.
描画オブジェクトツリーは以下のようになります.
基本的なプログラミング法
以下に書いてあることは, @IT(アットマークIT)の連載記事でも学べますので,説明不足に感じた場合はそちらを参照してください.
画像(スプライト)の表示
Spriteオブジェクトを使います.イメージとしては,画像表示用のオブジェクトを new で作って,それに表示したいキャラクターを登録するようなことを行います.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enchant(); var IMG = 'http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/images/chara1.png'; window.onload = function() { var core = new Core(320, 320); // var game = new Game(320, 320); でも同じ core.preload(IMG); core.onload = function() { var kuma = new Sprite(32, 32); // <-- 画像サイズに合わせる kuma.image = core.assets[IMG]; kuma.frame = 3; // 表示したいフレーム番号 kuma.x = 120; kuma.y = 50; core.rootScene.addChild(kuma); } core.start(); } |
- 7行目: スクリプト実行中に使いたい画像ファイル(png,jpg,gifなら可)は,事前にプリロードしておく必要があります.複数の場合は「,」(カンマ)で区切って列挙すればOKです.
- 14行目: スプライトを実際に表示するためには,表示オブジェクト(ここではrootScene)に追加する必要があります.
- スプライトの主なプロパティは以下です.(他にもあります)
プロパティ | 意味 |
---|---|
frame | 表示するフレーム番号 |
image | 表示する画像.あらかじめプリロードしておく必要がある |
rotation | 回転角度 |
x | x座標 |
y | y座標 |
scaleX | x方向の倍率 |
scaleY | y方向の倍率 |
キー入力検知
Coreオブジェクトのinput
プロパティを使います.
12 13 14 15 16 17 18 19 20 21 22 23 24 | // 省略 ... core.rootScene.addChild(kuma); kuma.addEventListener('enterframe', function(ev) { if( core.input.left ) this.x -= 4; // 左ボタン if( core.input.right ) this.x += 4; // 右ボタン if( core.input.up ) this.y -= 4; // 上ボタン if( core.input.down ) this.y += 4; // 下ボタン }); } core.start(); } |
- 表示スプライトのコールバックでキーを検知するようにプログラミングします.スプライトの
addEventListener
メソッドの引数に,イベントタイプであるenterframe
と,リスナ(イベントが発生した際に実行されるコールバック関数)を指定します. enterframe
イベントは,大雑把に言うと「1秒間にたーくさん発生しているイベント」のことです.ちゃんと言うと,新しいフレームが描画される際に発生するイベント.enterframe
イベントは,1秒間に「Coreオブジェクトのfps
プロパティで指定された回数」だけ発生しています.- もし
core.fps
が30なら,1秒に30回,enterframeイベントが発生し,その都度,リスナとして登録したコールバック関数が実行されます - つまり,1秒に30回,キー入力を検知する,ということです
- もし
- enchant.jsでは,デフォルトで「↑」「←」「→」「↓」「a」「b」の6つのボタンをサポートしていますが,任意のキーを割り当てたければCoreオブジェクトのkeybindメソッドを使えばOKです.引数には,キーコード,割り当てるボタン名を指定します.
core.keybind(32, SPC); ... if( core.input.SPC ) { ... }
イベント検知
イベントを検知して処理を実行するには,イベントリスナ(そのイベントが発生したときに実行されるコールバック関数)を使います.
例えば,タッチイベントを検出してスプライトをタッチ移動(ドラッグ移動)させるためには以下のように書きます.
19 20 21 22 23 24 25 26 27 28 29 30 | // 省略 ... if( core.input.down ) this.y -= 4; // 下ボタン }); kuma.on('touchmove', function(ev) { // addEventListenerはonとも書ける this.x = ev.x - this.width / 2; this.y = ev.y - this.height / 2; }); } core.start(); } |
- イベントリスナを登録するためには,EventTargetオブジェクトの
addEventListener
メソッドを使います.このメソッドは,省略してon
とも書けます. on
の引数には,イベントタイプとリスナを指定します.- イベントタイプには多くの種類がありますが,主なものは以下です.
イベントタイプ | 発生のタイミング | 発行元のオブジェクト |
---|---|---|
abuttondown |
[a]ボタンが押されたとき | Core,Scene |
abuttonup |
[a]ボタンが離されたとき | Core,Scene |
bbuttondown |
[b]ボタンが押されたとき | Core,Scene |
bbuttonup |
[b]ボタンが離されたとき | Core,Scene |
enterframe |
新しい描画フレームが開始されるとき | Core,Node |
touchend |
タッチが終了したとき | Node |
touchmove |
タッチが移動したとき | Node |
touchstart |
タッチが開始されたとき | Node |
アニメーション表示
スプライトをアニメーション表示させるためには,描画フレームごとに画像を切り替えて表示します.要は,パラパラ漫画です.
文字(ラベル)表示
Labelオブジェクトを使います.
var infolabel = new Label('サンプル'); infolabel.x = 20; // 表示位置x座標 infolabel.y = 0; // 表示位置y座標 infolabel.color = '#0000FF'; // 表示色 infolabel.font = '14px sans-serif'; // 表示フォント core.rootScene.addChild(infolabel);
- Labelオブジェクトを作る際の引数は「表示するテキスト」ですが,これを省略して,後から
text
プロパティで設定することも可能です. - 文字の色は
color
プロパティで,フォントはfont
プロパティでそれぞれ設定します.色については,以下の指定が可能です.#RGB
(各値は16進数,#00fとか)#RRGGBB
(各値は16進数,#0000ffとか)rgb(R,G,B)
(各値は10進数,rgb(0,0,255)とか)rgb(R%,G%,B%)
(各値はパーセンテージ,rgb(0%,0%,100%)とか)rgb(R,G,B,A)
(Aは透過率0.0〜1.0,rgb(0,0,255,1.0)とか)色の名前
(blueとか)
- あたりまえですが,フォントは,その端末(やブラウザ)で表示できるものでなければ正しく表示されません
音を鳴らす
Soundオブジェクトを使うと簡単に鳴らせます.
// 略 var BGM = 'http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/sounds/bgm06.wav'; var SNDEFCT = 'http://wiki.cis.iwate-u.ac.jp/~wiki/csd/js/sounds/se1.wav'; // 略 core.preload(BGM, SNDEFCT); core.bgm = Sound.load(BGM); core.se = Sound.load(SNDEFCT); core.onload = function() { core.bgm.volume = 0.5; core.bgm.play(); core.se.play(); // 略 } // 略
- サウンドファイルも要プリロードです.つまり,
core.preload
メソッドで,あらかじめ読み込んでおく必要があります. - Firefoxでmp3を再生するためには,enchant.jsの本家で配布されている「
sound.as
」と「sound.swf
」が必要らしいです.(未確認) - Soundオブジェクトの主なプロパティとメソッドは以下です.
メソッド | 機能 |
---|---|
pause() |
再生中断 |
play() |
再生開始 |
stop() |
再生停止 |
プロパティ | 設定値 |
---|---|
currentTime |
現在の再生位置(秒) |
duration |
再生時間(秒).mp3の場合は取得不可 |
volume |
音量.0〜1の範囲 |
- BGMをリピートしたい場合は
currentTime
とduration
を比較し,等しくなったタイミングでcurrentTime
をゼロにすることで実現できそうです.(必要な班は詳細を自分達で調べてください)
画面切り替え
複数のSceneオブジェクトを使えば実現できます.
- シーンは,rootSceneをベースとしたスタック構造になっています.
- Coreオブジェクトの
pushScene
メソッドで新しいシーンを追加でき, - Coreオブジェクトの
popScene
メソッドで(push前の)元のシーンに戻せます. - 指定したシーンを削除する
removeScene
メソッド,現在のシーンを別のシーンに置き換えるreplaceScene
メソッドなどもあります.