本記事はphina.js Advent Calendar 2015の18日目の記事です。
← 17日目 phina.js を使って様々な図形を表示してみよう --- 国産ゲームライブラリ「phina.js」で3Dゲーム作ろうぜ! 19日目 →
2日遅れですいません…(18日が終わる2時間前にエントリーしたので許してください…)
概要
tmlib.jsの後継のライブラリであるphina.jsがリリースされたということで昔書いたゲームをphina.jsで書き直してみました(書き直すといってもそこまで大きく変える必要はないです)
自分はtmlibのバージョンを気にせずに調べまくって作ったので古いものと新しいものが混ざってたりします…(新しいtmlib.jsはphina.jsにかなり近いと思います)
tmlib.jsにはなかったとか言いながらあったりするかもしれないですが、そこはご愛敬ということで…
起動処理(tm.main -> phina.main)
tmlib.jsでは(tm.game内のtmlib.globalize()
で)一部の変数はグローバルに展開されていましたが、phina.jsでは展開するためにphina.globalize()
を使用します
tm.main -> phina.main
tm.mainでは
app = tm.display.CanvasApp("#app")
app.resize(width, height)
app.fitWindow()
app.background = "#DDDDDD"
app.fps = 60
loadScene = LoadScene({
assets: ASSETS
# ~略~
})
loadScene.onload = ->
app.replaceScene(TitleScene())
return
app.run()
と挿入位置などの設定、ロードシーンに記述などをしていましたが、phina.mainでは、GameApp()を使用してオブジェクトで設定を渡すことができるようになりました(tmlibのtm.gameあたりで既にできてたかもしれないです)
また、GameAppではTitleSceneやLoadSceneも入っているので独自のものを使わないのであれば実装が不要です
app = GameApp({
assets: ASSETS
startLabel: "title"
# ~略~
})
app.backgroundColor = "#DDDDDD"
app.fps = 60
app.run()
ただbackgroundColorやfpsなどはオブジェクトで渡せないみたいです
クラス (tm.define -> phina.define)
tmlib.jsではすべてのクラスに必要はなかったのですが、phina.jsではすべてのクラスにはtmlib.jsと同様に継承するクラスに関してはthis.superInit()
が必要になりましたthis.superInit()
が必要です(12/20 16:19修正)
Assets
{
"shooter": "img/shooter.png"
}
と指定するのではなくそれぞれ種類を指定するようになりました
sound: {
"start": "sound/btn09.#{SUPPORT_EXT}"
}
image: {
"shooter": "img/shooter.png"
}
※SUPPORT_EXTの話はすぐしたのSoundに
Sound
Sound.SUPPORT_EXT
がなくなりました
自分はChromium系ブラウザを使っているので.mp3
指定だけでは音楽が流れないので、下のように実装してます
SUPPORT_EXT = do ->
ext = ""
audio = new Audio()
if audio.canPlayType("audio/mp3") is "maybe"
ext = "mp3"
else if audio.canPlayType("audio/ogg") is "maybe"
ext = "ogg"
else if audio.canPlayType("audio/wav") is "maybe"
ext = "wav"
return ext
mp3 -> ogg -> wavという順番なのはサイズの小さいのを優先させたいからです(tmlib.jsだとwav -> mp3 -> oggでしたが…)
SoundManager
mute()
がトグルではなくミュートにするになりました
よってこれまでのトグルをするには
if SoundManager.isMute()
SoundManager.unmute()
else
SoundManager.mute()
とする必要があります
また、tmlib.jsでは実装されていたSoundManager.play()
はSound.play()
へ移動されました(SoundManager.playMusic()
に関しては利用できます)
AssetsManager.get("sound", "").play()
と使用できます
SoundManager.pause()
は一部実装されていないので今のところ動きません
Scene (Scene -> CanvasScene)
Scene
という名前からCanvasScene
という名前になってCanvasに特化したシーンになりました
fromJSON()
これに渡すchildrenが配列で渡せなくなりました
これまでは
children: [
{
type: "Label"
name: "titleLabel"
text: "Shooting"
}
]
のように指定できたのですが
phina.jsでは
children: {
"titleLabel": {
className: "Label"
text: "Shooting!"
}
}
と指定します
これまでのname
がキー名に、type
がclassName
に変わりました
また、init: []
はarguments: []
に変更されました(12/20 16:35修正)
また、一部でinit: []
と指定していた場所もinit: []
に入れる必要がなくなりそのまま指定できるようになりました(FlatButtonのLabelがButton自体になったからかもしれないです)
{
type: "FlatButton"
name: "muteButton"
init: [
{
text: ""
}
]
}
"muteButton": {
className: "Button"
text: ""
}
衝突判定
isHitElement()
がhitTestElement()
に変わりました
Sprite (Sprite/AnimationSprite -> Sprite/FrameAnimation)
また、AnimationSprite
がなくなり、Sprite
を継承してFrameAnimation
をattachTo(this)
することでSpriteSheetを利用するようになりました
Sprite("参照名", width, height)
でサイズが変更できるのですが、自分のほうではうまく変更できませんでした
setImage()がなくなったので下のように画像を変更できなくなりました
a = Sprite()
a.setImage()
変更をするにはFrameAnimation
を使ってgotoAndPlay()
で切り替えるという方法があります
display
CircleShapeやLabelなどが入っていますが、
これまで色を変更するのにfillStyle
を使っていましたがfill
になりました
それとrgba(,,,)
はtmlib.jsではつかえたのですが、phina.jsでは今のところつかえないみたいです
自分のtypoだったみたいです…すいません(12/20 16:39修正)
tmlib.jsでは何もせずともクリックを感知していましたが、phina.jsではクリックを感知するために.setInteractive(true)
が必要になります
ないとonpointstart()
などがきかないです
また、onpointingstart()
がonpointstart()
に変わりました
tmlib.jsではposition.set()
で位置を設定できましたが、phina.jsではsetPosition()
を使います
こっちも自分のtypoだったみたいです…(12/20 16:41修正)
CircleShape
サイズの指定がwidth
、height
からradius
に変わりました
ここでそのままさらっとwidth
の値をradius
にすると倍の大きさになってしまうので(当たり前ですが)注意が必要です
FlatButton
おそらく今までのFlatButton
がButton
を乗っ取りました
また、Button
内にLabel
が入っている構造ではなくそのままButton
にLabel
があるのでbutton.label.tweener
などのようにできなくなりました(方法があれば教えてください)
Input (Accelerometer -> ×)
Accelerometer
がなくなりました(今後実装予定?)
といっても実装はeventつければいいだけなのでさらっと
@rotate = {}
window.addEventListener("deviceorientation", @catchOrientation, false
)
catchOrientation: (e) ->
@rotate.beta = e.beta
@rotate.gamma = e.gamma
return
SceneやEntityなどの中でeventを生成するときはそのSceneやEntityがなくなるときにremoveしましょう…(ここで少し引っかかりました)
onDied: ->
window.removeEventListener("deviceorientation", @catchOrientation, false)
return
v2.0で実装予定だそうです!(12/20 16:41修正)
Geom
Vector2
random(min, max, len)
がうまく動いてません
v2で修正予定です
とりあえずのところは
random(min, max).mul(len)
と書くと動きます
Math
Math.rand()
がMath.randint()
に
Math.randf()
がMath.randfloat()
に変わりました
最後に
自分が関係した変更はこんな感じです
実際の今回書き直したゲームはこちら
ソースコードはこちら(汚いですが…)
御覧いただきありがとうございました
いろいろと躓いた際に助けていただいたphiさんやsimiraaaaさんやdaishiさんにも感謝の意を…