「CreateJS」カテゴリーアーカイブ

SpriteSheetでキャラクタアニメーション / CreateJS

CreateJSではSpriteSheetというアニメーション用に用意されたクラスがあります。
この場合はパラパラ漫画的なアニメーションです。

キャラクタのアニメーションをずらっと並べた画像を用意します。
サンプルにある下記のような感じ。
アニメーションGIFとかじゃなく、全ての動きが並んだ状態です。
https://github.com/CreateJS/EaselJS/blob/master/examples/assets/runningGrant.png

そして、下記のようにアニメーションの設定をします。
設定方法は何種類か用意されていて、細かい設定が出来るようになってます。
http://createjs.com/Docs/EaselJS/SpriteSheet.html

1
2
3
4
5
6
7
8
9
10
11
12
var playerWidth = 165;
var playerHeight = 292;
var spriteSheet = {
    images: ['path/to/image.png'],
    frames: { width: playerWidth, height: playerHeight },
    animations: {
        run: [0, 25],
        jump: [26, 63]
    }
};
var ss = new createjs.SpriteSheet(spriteSheet);
var character = new createjs.BitmapAnimation(ss);

この場合、アニメーション名「run」に 0 〜 25 までの連続した動きが使われます。
frames で指定した width, heigt で自動的に分割されます。
0 〜 25 はこの分割された配列のインデックスみたいなもんです。

「jump」のあとはそのまま「run」を再生させたり、「run」はルーブさせたりできます。

1
2
ss.getAnimation("run").next = "run";
ss.getAnimation("jump").next = "run";

キャラクタはいったん Container に登録してから使った方が後からイロイロ調整できそうです。
というか、addChild が Container にしか用意されてないので、そうしろってコトかと。

キャラクタの移動は Container で調整したいので、画像の中心に座標の原点が来るようにズラします。
移動や回転、拡縮に便利なので。

1
2
3
var player = new Container;
player.addChild(character);
character.setTransform(-playerWidth/2, -playerHeight/2);

あとはキーイベントなどに関連付けたりして、アニメーションを再生させればOKす。
再生は設定で指定したアニメーション名を使用します。

1
character.gotoAndPlay('run');

Error: Suspended

横スクロール / CreateJS

シューティングみたいな横スクロールつくってみる。
背景とか画像読み込むので PreloadJS も使う。

1
<script src="http://code.createjs.com/preloadjs-0.2.0.min.js"></script>
1
2
3
4
5
6
var manifest = [
    { src: "img/bg.png", id: "background" },
    { src: "img/fg.png", id: "foreground" }
];
var loader = new createjs.PreloadJS;
loader.loadManifest(manifest);

画像の読み込み完了してから各処理に移りたいので、下記のようにしておく。

1
2
3
4
5
6
7
8
9
10
11
12
13
var assets = [];

loader.onFileLoad = handleFileLoad;
loader.onComplete = handleComplete;

function handleFileLoad(e){
    assets.push(e);
}
function handleComplete(){
    for (var i = 0; i < assets.length; i++){
        // 読み込まれた画像を処理する
     }
}

onComplete 時には assets に読み込んだ画像データが格納されています。
画像もこれまでの円や四角と同じで Shape で作成します。

1
2
3
4
5
6
for (var i = 0; i < assets.length; i++){
    var result = assets[i].result;
    var s = new createjs.Shape;
    s.graphics.beginBitmapFill(result).drawRect(0, 0, result.width, result.height);
...
}

あとはオブジェクトごとに tick でそれぞれ動きをつければそれらしくなります。
画像を複数枚用意してアニメーションさせることも出来るみたいです。
今回は簡単に座標の移動だけやってみました。

Error: Suspended

Segmentで多関節 / CreateJS

CreateJS使って多関節やってみます。
サンプルのSegment参考にしてます。

多関節は描画が簡単なので円にします。
Shape だと親子階層出来ないので、Container 使います。

1
2
3
4
var container = new createjs.Container();
var shape = new createjs.Shape();
shape.graphics.f(color).dc(0, 0,radius);
container.addChild(shape);

CreateJS のサンプルでは下記のように Container クラスを継承して使ってました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Segment(){
    this.r = radius;
    this.color = 'yellow';
    this.init();
}
Segment.prototype = new createjs.Container();
Segment.prototype.r;
Segment.prototype.color;
Segment.prototype.Container_initialize = Segment.prototype.initialize;
Segment.prototype.init = function(){
    this.Container_initialize();
    this.addChild(this.getSprite());
};
Segment.prototype.getSprite = function(){
    var s = new createjs.Shape();
    s.graphics.f(this.color).dc(0, 0, this.r);
    return s;
};

あとはいくつか親子階層にしてみます。

1
2
3
4
5
6
7
8
9
10
var seg = [];
seg[0] = new Segment;
var parent = seg[0];

for (var i = 1; i < SEGMENT_NUM; i++){
    seg.push(new Segment);
    seg[i].setTransform(seg[i].r * 2.5, 0);
    parent.addChild(seg[i]);
    parent = seg[i];
}

あとは CreateJS の Ticker でアニメーションをつければ完成。

1
2
3
4
5
6
function tick(){
    for (var i = 1; i < SEGMENT_NUM; i++){
        // 動きをつける
    }
    stage.update();
}

Error: Suspended

DOM Element / CreateJS

CreateJSでDOM Elementを操作します。
たぶん jQuery とかの方がイロイロできそうですが、ゲーム作る時に canvas 以外も動かしたくなった時のために。
CreateJS では DOM の操作の時も canvas いるみたいです。
対象となるHTMLは下記の感じ。

1
2
3
4
5
6
<div id="target" style="background-color: blue; width: 320px; height: 240px;">
    TEST
</div>
<canvas id="demoCanvas" width="640" height="480">
    alternate content
</canvas>

DOM Element でも今までの Shape とそんな変わりない感じに使えます。
下記は試しに 30度回転。

1
2
var content = new createjs.DOMElement('target');
content.rotation = 30;

Shape で描画する時との違いは、DOM Element は canvas からはみ出ることですかね。

Drag & Drop / CreateJS

チュートリアルの Drag & Drop やってみる。
まずはオブジェクトをクリックした時のイベント指定。

1
object.onPress = handlePress;

この時 handlePress 内で onMouseMove と onMouseUp のイベント指定しちゃいます。
そうする事でマウスのボタンが押されている間だけこの指定が有効になります。

1
2
3
4
function handlePress(){
    e.onMouseMove = handleMouseMove;
    e.onMouseUp = handleMouseUp;
}

ドラッグ時の移動はマウス座標を使って指定します。
この時対象のオブジェクトは下記のように target として取得できます。

1
2
3
function handreMouseMove(e){
    e.target.setTransform(e.stageX, e.stageY);
}

CreateJS使うと簡単ね。

氷菓のエンディングっぽい動き / CreateJS

CreateJSつかって氷菓のエンディングにあるテキストでキャラクタが描かれる動きをつくってみるよ。
2クール目EDの1分過ぎくらいのとこね。

とりあえず、前回やったお絵かきを使おうかな。
描画の時に使った座標をひと通り保存して、それをテキストに置き換えることに。
なんか既に重くなりそうな雰囲気だが…

テキストはあらかじめ a-z, A-Z で用意しとく。
CreateJSのテキストオブジェクトで1文字ずつ用意してみる。

1
2
3
4
5
6
7
8
9
var text = [];
for (var i = 65; i <= 90; i++){
    var t = new createjs.Text(String.fromCharCode(i), '20px serif', color);
    text.push(t);
}
for (var i = 97; i <= 122; i++){
    var t = new createjs.Text(String.fromCharCode(i), '20px serif', color);
    text.push(t);
}

絵を描いて再生ボタンを押すとアニメーションを再生。
その際に各座標ごとにランダムでテキストオブジェクトを割り当てます。
既にあるテキストオブジェクトから下記のようにして生成できます。

1
2
var index = Math.floor(Math.random() * text.length);
var shape = new createjs.Shape(text[index]);

正確な再現はあきらめて、ランダムな位置から描画した座標に移動、そして消えるようにしてみました。
wait で指定時間だけ動きを止めることができます。
他にも scale, rotation, alpha などランダムで動かすとよりそれらしくなると思います。

1
2
3
4
5
6
7
stage.addChild(shape).setTransform(x, y);
createjs.Tween.get(shape, { loop: true })
    .wait(800)
    .to({ x: drawX, y: drawY }, 1600)
    .wait(1000)
    .to({ x: drawX + dx, y: drawY + dy, alpha: 0 }, 1500)
    .wait(300);

こんな感じでとりあえずそれらしくは出来るのですが、ちょっと細かい絵を描くとすんごい重くなります…
まあ、座標の数が増えればそんだけテキストオブジェクトの数も増えるんだから当たり前よね。
という訳で、標準で用意されてるキャッシュの機能とかで軽くなるか試してみました。

まずは snapToPixel をオンにして描画される座標を丸め込みします。
特にビットマップ画像の時は有効みたいです。
これは親オブジェクトや stage についてもオンにしておかないと有効にならないようです。

1
2
3
4
5
// stage でオン
stage.snapToPixelEnabled = true;

// オブジェクトでオン
t.snapToPixelEnabled = true;

あとはキャッシュ機能もオンにするとだいぶ改善されます。
最初のテキストオブジェクト生成時に下記のよう指定します。
引数はキャッシュする範囲の始点と幅と高さです。
この場合はオブジェクトの大きさにします。

1
2
3
var w = t.getMeasuredWidth();
var h = t.getMeasuredHeight();
t.cache(0, 0, w, h);

拡大するときはさらにオプションで指定可能です。
移動や回転、透過してもキャッシュは有効なのでかなり自由度高いと思う。

マウスの動きに合わせて線を引く / CreateJS

チュートリアルにある Finger Paint やってみる。
マウスイベントの続きだけど、canvas (CreateJSのstage) でのイベント処理と言う感じ。

MouseMove イベントで拾ったマウス座標を使って、一つ前から今の座標まで線を引きます。
stage でも図形と同じように下記のように指定します。

1
stage.onMouseMove = handleMouseMove;

前回の座標を old として、MouseMove イベントで呼び出される度に線を引きます。
現在の座標は event.stageX, event.stageY を使います。

1
2
3
4
function handleMouseMove(event){
    line.graphics.s('#F00').ss(size, 'round').mt(old.x, old.y).lt(event.stageX, event.stageY);
    old = { x: event.stageX, y: event.stageY };
}

ちなみにキャンバスからマウスがはみ出た場合に、座標がキャンバスサイズ以上にならないオプションも用意されてます。
その際、キャンバスからはみ出た実際の座標は event.rawX, event.rawY で取得できるみたい。ホント気が利くなあ。

1
2
stage = new createjs.Stage('canvas');
stage.mouseMoveOutside = true; // はみ出ない

Mouse Interaction / CreateJS

CreateJSでつくったオブジェクトをマウスイベントに反応させる。
付属のチュートリアルに沿ってやってくよ。

クリックだけなら必要ないけど、マウスオーバー・マウスアウト使う時は下記のような宣言が必要です。
enableMouseOver は引数に一秒間に何回マウスオーバーを拾うか指定できる。(20回がデフォ)

1
2
stage = new createjs.Stage('canvas');
stage.enableMouseOver(10);

イベントはオブジェクト毎に指定します。
onClick, onMouseOver, onMouseOut, onPress, onDoubleClick などに指定可能です。

1
2
3
4
var object = new createjs.Shape();
object.onClick = function(){
    alert('クリック');
};

テキストだと隙間があるので hitArea の指定が可能です。

1
2
3
text = new createjs.Text('Text with hitArea', 'bold 20px Arial', 'red');
text.hitArea = new createjs.Shape();
text.hitArea.graphics.f('white').dr(0, 0, text.getMeasuredWidth(), text.getMeasuredHeight());

他にも、複数オブジェクトをまとめられる Container とかあって便利!
その場合は、コンテナにイベント付けたら子のオブジェクトのイベントを無視できたりと、すごくよくできてます。

1
2
container = new createjs.Container();
container.mouseChildren = false;

座標系変換 / CreateJS

CreateJSのチュートリアルにある座標系変換。
マウス座標をオブジェクトの座標に変換する場合、以下のようにします。

1
var pt = circle.globalToLocal(stage.mouseX, stage.mouseY);

stage.mouseX, stage.mouseYからマウス座標がとれるので、それを globalToLocal でオブジェクトの座標系に変換します。
この場合、pt.x, pt.y に変換後の座標がはいってます。
さらに hitTest を使用すれば、マウスがオブジェクトに乗っかってるか判定できます。

1
2
3
if (circle.hitTest(pt.x, pt.y)){
    // hit!
}

これで複雑な親子構造になっているオブジェクトでも簡単に座標計算できます。
逆の localToGlobal も、アニメーションするオブジェクト同士の localToLocal も用意されてます。

Tween 機能でアニメーションをつける / CreateJS

CreateJSのTween機能でアニメーションつけてみる。
これを使うとまとめて設定できます。

1
2
3
var start = 0;
var end = 400;
createjs.Tween.get(circle,{loop:true}).to({x:end}, 5000).to({x:start}, 0);

get で対象オブジェクトを指定します。
その際にオプション指定できます。
{ loop: true } はアニメーションのループを指定。
オプションは公式のドキュメント参照。
http://createjs.com/Docs/TweenJS/Tween.html

to で動きの指定と、完了までの時間をミリ秒で指定できます。
to は複数指定できるので、一連のアニメーションをまとめられます。
Tween には easing 機能も用意されてるので、いろんな動きも指定できるみたいで楽しそう。