Help us understand the problem. What is going on with this article?

PlayCanvasでスプライトアニメーション作成、そしてアニメーションからイベント発火

最初に

昔作ったゲームをブラウザゲームとして作り直そうと思っていて、

kuchiinu_a_attack03.png

こんなアニメーションをする画像をPlayCanvas上で使えるようにしたいなと考えています。

ちなみに以前作った環境ではメインループの中に入力も当たり判定も描画もぶっ込んでいるような、パワータイプなプログラムを書いていました。

今回はGUI環境に合わせてプログラムしていきたいと思います。

アセットへスプライトの原料をアップロード

画像は透過PNGで行きます。
スクリーンショット 2020-03-26 1.20.23.png

透過PNGってゲーム作るとき便利よね・・・
256色ビットマップしかゲームプログラムで使える選択肢がなくて、256色の中から透過色を一つ選ばねばならなかった頃が懐かしい・・・

テクスチャーアトラスを作成

アップした画像で右クリックして「Create Texture Atlas」を選択
スクリーンショット 2020-03-26 1.20.59.png

もとの画像はtypeが「texture」ですが、
スクリーンショット 2020-03-26 1.21.20.png

新しく生成した方はtypeが「textureatlas」となっていて、アイコンが左上にあります。
スクリーンショット 2020-03-26 1.21.30.png

もとの画像の方はもう不要なので削除しても構いません。

テクスチャアトラスをフレーム分けする

作成したテクスチャアトラスをダブルクリックするとスプライトエディタが開きます。
スクリーンショット 2020-03-26 1.23.11.png

この画像をスプライトアニメーションのコマとなるフレームに分けていきます。

スクリーンショット 2020-03-26 1.23.33.png

本来はマウスドラッグで1個1個作っていくのですが、とっっっても面倒くさいのでここで手品を使います。
(同じ大きさの矩形がお行儀よく並んでいること前提なのですが)

以下のJSONファイルを「UPLOAD TEXTURE PACKER JSON」というボタンからアップロードしてください。

spritesheet.json
{
    "frames": {
        "rei_00": {
            "frame": {"x": 0,"y": 0,"w": 256,"h": 256}
        },
        "rei_01": {
            "frame": {"x": 256,"y": 0,"w": 256,"h": 256}
        },
        "rei_02": {
            "frame": {"x": 512,"y": 0,"w": 256,"h": 256}
        },
        "down_00": {
            "frame": {"x": 0,"y": 256,"w": 256,"h": 256}
        },
        "down_01": {
            "frame": {"x": 256,"y": 256,"w": 256,"h": 256}
        },
        "down_02": {
            "frame": {"x": 512,"y": 256,"w": 256,"h": 256}
        },
        "down_03": {
            "frame": {"x": 768,"y": 256,"w": 256,"h": 256}
        },
        "a_stand_00": {
            "frame": {"x": 0,"y": 512,"w": 256,"h": 256}
        },
        "a_front_00": {
            "frame": {"x": 256,"y": 512,"w": 256,"h": 256}
        },
        "a_back_00": {
            "frame": {"x": 512,"y": 512,"w": 256,"h": 256}
        },
        "a_parry_00": {
            "frame": {"x": 0,"y": 768,"w": 256,"h": 256}
        },
        "a_parry_01": {
            "frame": {"x": 256,"y": 768,"w": 256,"h": 256}
        },
        "a_receive_00": {
            "frame": {"x": 512,"y": 768,"w": 256,"h": 256}
        },
        "a_receive_01": {
            "frame": {"x": 768,"y": 768,"w": 256,"h": 256}
        },
        "a_attack_x00": {
            "frame": {"x": 0,"y": 1024,"w": 256,"h": 256}
        },
        "a_attack_x01": {
            "frame": {"x": 256,"y": 1024,"w": 256,"h": 256}
        },
        "a_attack_x02": {
            "frame": {"x": 512,"y": 1024,"w": 256,"h": 256}
        },
        "a_attack_y00": {
            "frame": {"x": 0,"y": 1280,"w": 256,"h": 256}
        },
        "a_attack_y01": {
            "frame": {"x": 256,"y": 1280,"w": 256,"h": 256}
        },
        "a_attack_y02": {
            "frame": {"x": 512,"y": 1280,"w": 256,"h": 256}
        },
        "a_attack_z00": {
            "frame": {"x": 0,"y": 1536,"w": 256,"h": 256}
        },
        "a_attack_z01": {
            "frame": {"x": 256,"y": 1536,"w": 256,"h": 256}
        },
        "a_attack_z02": {
            "frame": {"x": 512,"y": 1536,"w": 256,"h": 256}
        },
        "b_stand_00": {
            "frame": {"x": 0,"y": 1792,"w": 256,"h": 256}
        },
        "b_front_00": {
            "frame": {"x": 256,"y": 1792,"w": 256,"h": 256}
        },
        "b_back_00": {
            "frame": {"x": 512,"y": 1792,"w": 256,"h": 256}
        },
        "b_parry_00": {
            "frame": {"x": 0,"y": 2048,"w": 256,"h": 256}
        },
        "b_parry_01": {
            "frame": {"x": 256,"y": 2048,"w": 256,"h": 256}
        },
        "b_receive_00": {
            "frame": {"x": 512,"y": 2048,"w": 256,"h": 256}
        },
        "b_receive_01": {
            "frame": {"x": 768,"y": 2048,"w": 256,"h": 256}
        },
        "b_attack_x00": {
            "frame": {"x": 0,"y": 2304,"w": 256,"h": 256}
        },
        "b_attack_x01": {
            "frame": {"x": 256,"y": 2304,"w": 256,"h": 256}
        },
        "b_attack_x02": {
            "frame": {"x": 512,"y": 2304,"w": 256,"h": 256}
        },
        "b_attack_y00": {
            "frame": {"x": 0,"y": 2560,"w": 256,"h": 256}
        },
        "b_attack_y01": {
            "frame": {"x": 256,"y": 2560,"w": 256,"h": 256}
        },
        "b_attack_y02": {
            "frame": {"x": 512,"y": 2560,"w": 256,"h": 256}
        },
        "b_attack_z00": {
            "frame": {"x": 0,"y": 2816,"w": 256,"h": 256}
        },
        "b_attack_z01": {
            "frame": {"x": 256,"y": 2816,"w": 256,"h": 256}
        },
        "b_attack_z02": {
            "frame": {"x": 512,"y": 2816,"w": 256,"h": 256}
        }
    },
    "meta": {
        "app": "",
        "version": "1.0",
        "image": "nuemaru.png",
        "format": "RGBA8888",
        "size": {"w": 1024,"h": 4096},
        "scale": "1"
    }
}

スクリーンショット 2020-03-26 2.03.59.png

JSONをアップロードすると自動で256×256のフレームに切り分けられます。
スクリーンショット 2020-03-26 15.09.08.png

使ったJSONファイルは1024×4096サイズの画像を256×256のフレームを切り分けるように記述してあります。
使う際は書き換えてください。

スプライトを作る

前項のフレーム分けでできたrei_00,rei_01,rei_02をつなげてスプライトをつくります。

一番最初にくるフレームを選択して「NEW SPRITE FROM SELECTION」をクリック。
スクリーンショット 2020-03-26 15.16.32.png

「SPRITE ASSETS」に「rei_00」というスプライトが作成されます。
続けてフレームを追加する場合は「ADD FRAMES TO SPRITE ASSET」をクリック。
スクリーンショット 2020-03-26 15.19.44.png

追加したいフレームを選択して「ADD SELECTED FRAMES」をクリック。
スクリーンショット 2020-03-26 15.24.49.png

追加完了。
スクリーンショット 2020-03-26 15.25.02.png

スプライトアニメーションの土台を作る

Root直下で「Animated Sprite」のエンティティを追加します。
スクリーンショット 2020-03-26 1.19.30.png

スプライトをエンティティにセットする。

スクリーンショット 2020-03-26 15.34.29.png

これでLaunchするとアニメーションしているのが確認できます。

スプライトからイベントを発火してみる。

ここまでくると攻撃などのアニメーション開始時に移動や攻撃判定などの処理を追加したくなるはずです。

ちょっとだけ試してみましょう。

AnimatedSpriteにスクリプトを追加し、以下のコードを追加します。

CtrlPlayer.prototype.initialize = function() {

/* 中略 */

this.entity.sprite.clip("Clip 1").on("loop",this.looploop);

}

CtrlPlayer.prototype.looploop = function(){
    console.log("looploop");
    return;
};

これで"Clip 1"のスプライトがループするときにイベントが起きるようになるので、イベントハンドラ内に移動なり当たり判定を発生させるなり煮るなり焼くなり好きにできるようになります。

他のスプライトアニメーションにイベントハンドラをセットしたい場合は、clipメソッドの引数を別のスプライトアニメーションの名前に変えてみましょう。

pc.SpriteAnimationClipの説明によるとイベントは繰り返し発生時のloop以外にも

  • end
  • pause
  • play
  • resume
  • stop

があります。

わがままを言えば、各アニメーションのフレームが変わる時・・・例えば4フレーム目だけで起こすイベントなんかを設定できたらいいんだけどなあーと思っています。(こういうのは自分で作るべき?)

bcosizm
長年、広く浅くやってきた結果、自分はどんなエンジニアといっていいのかと悩む日々。主な使用言語はC言語、C++、Java、ActionScript3、JavaScript、PHP、SQL。 プライベートでAndroidアプリ配布したり、プログラムだけでなくいろいろゴチャゴチャやってます。大昔にWindowsで「RoughMetal」「NAMAKO02」ってフリーゲーム配布してました。
http://www012.upp.so-net.ne.jp/B-cos/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした