目次
EaselJS の SpriteSheetBuilder クラスを使ってみる
このデモでは createjs-2015.05.21.min.js
を利用しています。
EaselJS には SpriteSheetBuilder というクラスがあります。
今回はこの SpriteSheetBuilder というクラスの使い方とこれを使って何ができるのかを見ながら解説をしていきます。
SpriteSheet クラスのインスタンスを生成できるクラス
SpriteBuilder クラスを利用すると、DisplayObject クラスを継承しているオブジェクトを使って SpriteSheet クラスのインスタンスを作成することができます。
DisplayObject は位置や変形情報、など表示関する共通のプロパティ
が定義されているようなクラスなので、Stage に addStage で追加できるようなクラス(Container,Bitmap,Shape,Text
など)がそれに属しています。
言葉だけだとイメージがつきにくいと思うので、実際にやってみようと思います。
DEMO
See the Pen 1c9e02fe1e3fb64e084bb681a02100d4 by turusuke (@turusuke) on CodePen.
この DEMO でやっていることを元に解説をしていきます。
事前準備
まず、このDEMO では SpriteSheetBuilder の機能を検証するために以下のインスタンスを用意しました。
インスタンスの作成
SpriteSheetBuilder クラスを利用するためにインスタンスを作成します。
var builder = new createjs.SpriteSheetBuilder();
フレームの登録
次に addFrame
メソッドでフレームを追加していきます。
addFrame の引数にはフレームとして利用したい DisplayObject をとります。
builder.addFrame(circle);
アニメーションの登録
フレームの登録が終わったら次は addAnimation
を使ってアニメーションを登録します。
builder.addAnimation("anim", [0, 1, 2, 3, 4, 5], null);
ここで addAnimation
に渡している引数の詳細は以下のようになっています。
引数の値 | 内容 |
---|---|
"anim" | アニメーション名。ここで登録した名前でアニメーションを呼び出す。 |
[0,1,2,3] | "anim" でアニメーションさせるフレームを配列で渡す。ここで登録した順番で再生される。 |
null | アニメーションの再生終了後の次のアニメーション名(addAnimation の第一引数で指定した名前)を指定します。デフォルトでは同じアニメーションが繰り返されるようになっているのですが、1度だけ再生したい場合は null を指定しておきます |
上記の例だと、AddFrame で登録したフレーム 0,1,2,3,4,5 番目を 0,1,2,3,4,5 の順番で再生する "anim" というアニメーションを builder に登録しています。
同じフレームを利用して別なアニメーションを登録することもできるので、途中までは同じで微妙に違いのあるアニメーションを登録したりなんてことにつかうこともできます。
ビルドして SpriteSheet クラスのインスタンスを作成
フレームの登録、アニメーションの登録が終わったら build 関数を使ってビルドします。 返り値に SpriteSheet クラスのインスタンスが返ってくるので、これを変数に代入しておきます。
spriteSheet = builder.build()
Sprite クラスに SpriteSheet のインスタンスを渡す
後は Sprite に SpriteSheet のインスタンスを渡して、Sprite のインスタンスを作成後、任意のタイミングで登録したアニメーションを再生させるができます。
Sprite のインスタンスから SpriteSheet で登録したアニメーションを再生させるためのメソッドはいくつかありますが、今回は gotoAndStop()
関数(EaselJS v0.8.1 API Documentation : EaselJS#)を使っています。
引数には先ほど設定したアニメーション名を指定しています。
sprite = new createjs.Sprite(spriteSheet) stage.addChild sprite sprite.gotoAndStop("anim")
Stage に Sprite のインスタンスを追加し、 gotoAndStop を実行することで addAnimation で指定した順序でフレームが切り替わってアニメーションするオブジェクトを追加することができました。
SpriteBuilder をパーティクルアニメーションに活用してみる
SpriteteBuilder を使えばパーツとして利用するだけでなく、アニメーションのパフォーマンスを向上させるために利用することもできます。
canvas = document.getElementById("canvas")
context = canvas.getContext("2d")
canvas.width = window.innerWidth
canvas.height = window.innerHeight
# stage = new createjs.Stage(canvas)
stage = new createjs.SpriteStage(canvas)
stage.autoClear = false
ctx = canvas.getContext("2d")
ctx.fillStyle = "rgba(0, 0, 0, 0)"
ctx.fillRect 0,0,canvas.width,canvas.height
createjs.Ticker.setFPS(60)
stage.update()
GRAVITY = 2
K = 0.9
SPEED = 12
ToRadian = (degree) ->
degree * Math.PI / 180.0
class Fireworks
constructor: (@sx = 100,@sy = 100,@particles = 70) ->
@sky = new createjs.Container()
@sky.setBounds(@sx - 175,@sy - 175, 350, 350)
@sprite = new createjs.SpriteSheetBuilder()
@r = 0
@h = Math.random() * 360 | 0
@s = 100
@l = 50
@size = 3
@index
for i in [0...@particles]
speed = Math.random() * 12 + 2
circle = new createjs.Shape()
circle.graphics.f("hsla(#{@h}, #{@s}%, #{@l}%, 1)").dc(0, 0, @size)
circle.snapToPixel = true
circle.compositeOperation = "lighter"
rad = ToRadian(Math.random() * 360 | 0)
circle.set({
x: @sx
y: @sy
vx: Math.cos(rad) * speed
vy: Math.sin(rad) * speed
})
@sky.addChild circle
setUp: (target) =>
++@h
for p in [0...target.getNumChildren()]
circle = target.getChildAt(p)
circle.vx = circle.vx * K
circle.vy = circle.vy * K
circle.x += circle.vx
circle.y += circle.vy + GRAVITY
@l = Math.random() * 100
@size = @size - 0.001
if @size > 0
circle.graphics.c().f("hsla(#{@h}, 100%, #{@l}%, 1)").dc(0, 0, @size)
return
buildParticle: =>
if @sky.alpha > 0.1
@sky.alpha -= K / 50
@skyBounds = @sky.getBounds()
@sprite.addFrame @sky,@skyBounds,1,@setUp
@buildParticle()
else
@sprite.addAnimation "anim",[0...70],false
@sprite.addEventListener("complete", (e) =>
@buildSpriteSheet = e.currentTarget.spriteSheet
@sky = null
)
@sprite.buildAsync()
return
class Anim
constructor: (buildSpriteSheet,x,y) ->
@buildSpriteSheet = buildSpriteSheet
@x = x
@y = y
@explode(@x, @y)
explode: (x,y) =>
@anim = new createjs.Sprite(@buildSpriteSheet, "anim")
@anim.compositeOperation = "lighter"
@anim.set(
x: x
y: y
regX: 300 / 2
regY: 300 / 2
)
@anim.addEventListener("animationend", =>
stage.removeChild(@anim)
)
stage.addChild @anim
return
fireworks = new Fireworks()
fireworks.buildParticle()
stage.on("fire", ->
h = canvas.height
h = 0
repeat = null
repeat = setInterval(->
if h > canvas.height
h = 0
for w in [0...40]
new Anim(fireworks.buildSpriteSheet, Math.random() * canvas.width, h)
h += 50
,100)
,null,true)
handleTick = ->
if fireworks.buildSpriteSheet?
stage.dispatchEvent "fire"
ctx.fillStyle = "rgba(0, 0, 0, 0.1)"
ctx.fillRect 0,0,canvas.width,canvas.height
stage.update()
createjs.Ticker.addEventListener("tick", handleTick)