2017/08/20(日) [n年前の日記]
#1 [python][cocos2d] cocos2d + python を勉強中
せっかくだから、cocos2d のドキュメントを眺めつつ少しだけ勉強中。ちなみに環境は、Windows10 x64 + Python 2.7.13 + cocos2d 0.6.4。
今のところ分かってきた範囲の内容を一応メモ。
今のところ分かってきた範囲の内容を一応メモ。
◎ おまじない。 :
cocos2d を使うときは、スクリプトソースの最初のあたりに以下を書く。
import cocos「cocos2d」じゃなくて「cocos」をインポートする。最初うっかり cocos2d と書いてエラーが出て「アレ?」となった…。
◎ 座標系。 :
座標系は、+X が右、+Y が上、+Z が手前。

この手のソレってフツーは +Y が下じゃねえのと思うのだけど、cocos2d が使っているOpenGLは上が +Y なので、cocos2d もこういう座標系になってるのかなと。いわゆる _右手系 ってヤツ。

この手のソレってフツーは +Y が下じゃねえのと思うのだけど、cocos2d が使っているOpenGLは上が +Y なので、cocos2d もこういう座標系になってるのかなと。いわゆる _右手系 ってヤツ。
◎ クラスの構成。 :
cocos2d の概念(?)として…以下のようになってるっぽい。たぶん。おそらく。ちょっと自信ないけど。

なので、メイン処理部分は、以下のような感じになる。
「なんだかめんどくせーな」と思わないでもないけど…。まあ、実際ゲームを作るとなれば、タイトル画面、ステージ開始デモ、ゲーム本編、ゲームオーバー画面等々、各「シーン」は必要になってくるし、それぞれのシーン内では、背景レイヤー、キャラが動くレイヤー、スコア表示レイヤー等々が必要になってくるわけで。「どうせ後で必要になってくるだろうから大枠を用意しといたよ」てのはフツーと言えばフツーかな、という気もする。
とは言え、画像を一つだけ表示して動かしてみて何か簡単に実験したい、なんて時はやっぱり面倒臭い…。が、おまじないみたいなものと思ってしまえば、まあ…どうにか…。
- レイヤー(layer)、シーン(scene)、ディレクター(director。監督)という概念(クラス)がある。
- レイヤーには、スプライト(sprite)だの、テキストラベル(label)だのを複数登録できる。
- シーンには、レイヤーを複数登録できる。
- ディレクターは、複数のシーンを登録して管理できる。

なので、メイン処理部分は、以下のような感じになる。
- director に初期化処理をさせて、
- layer を新規作成して、
- layer を登録したsceneを新規作成して、
- director に「この scene の実行を開始しろ」と指示する。
cocos.director.director.init() layer = MyLayer() main_scene = cocos.scene.Scene(layer) cocos.director.director.run(main_scene)
「なんだかめんどくせーな」と思わないでもないけど…。まあ、実際ゲームを作るとなれば、タイトル画面、ステージ開始デモ、ゲーム本編、ゲームオーバー画面等々、各「シーン」は必要になってくるし、それぞれのシーン内では、背景レイヤー、キャラが動くレイヤー、スコア表示レイヤー等々が必要になってくるわけで。「どうせ後で必要になってくるだろうから大枠を用意しといたよ」てのはフツーと言えばフツーかな、という気もする。
とは言え、画像を一つだけ表示して動かしてみて何か簡単に実験したい、なんて時はやっぱり面倒臭い…。が、おまじないみたいなものと思ってしまえば、まあ…どうにか…。
◎ 画像の表示。 :
画像の表示は… sprite でも表示すればいいんじゃないかな…。たぶん…。
_cocos2d_sprite_b.py
_enemy_ball.png
ただ、OpenGLで描画すると、拡大縮小時に画像がぼやけたり、画像の境界が微妙に表示されて汚く見えたりする時があって。
そんな時は、クッキリした感じで描画するように、画像に対してフィルタの種類を指定するという策があるらしい。ただし、cocos2d ではなく、cocos2d がベースとしてる pyglet を使って画像の読み込みと指定をする羽目になるようで。
_cocos2d/pyglet でぼやけないスプライトを描画する - Qiita
_cocos2d_sprite.py
2Dゲームと言えば、昔のスーファミやアーケードゲームの画面を連想するわけで…。当時の拡大縮小処理はドットがジャギジャギしてたよなと。なので、個人的にはクッキリジャギジャギのほうが好み…。
_cocos2d_sprite_b.py
_enemy_ball.png
# spriteを生成
self.sprite = cocos.sprite.Sprite('enemy_ball.png')
# スプライト表示位置を指定。デフォルトは (0, 0) の位置。
self.sprite.position = 320, 340
# 生成したスプライトをレイヤーに追加
self.add(self.sprite)
ただ、OpenGLで描画すると、拡大縮小時に画像がぼやけたり、画像の境界が微妙に表示されて汚く見えたりする時があって。
そんな時は、クッキリした感じで描画するように、画像に対してフィルタの種類を指定するという策があるらしい。ただし、cocos2d ではなく、cocos2d がベースとしてる pyglet を使って画像の読み込みと指定をする羽目になるようで。
_cocos2d/pyglet でぼやけないスプライトを描画する - Qiita
_cocos2d_sprite.py
# pyglet も使う
import pyglet
# (中略)
# pygletで画像を読み込み
image = pyglet.image.load('enemy_ball.png')
# 拡大縮小時にボケないようにフィルタを指定。
pyglet.gl.glBindTexture(image.texture.target, image.texture.id)
pyglet.gl.glTexParameteri(image.texture.target,
pyglet.gl.GL_TEXTURE_MIN_FILTER,
pyglet.gl.GL_NEAREST)
pyglet.gl.glTexParameteri(image.texture.target,
pyglet.gl.GL_TEXTURE_MAG_FILTER,
pyglet.gl.GL_NEAREST)
# spriteを生成
self.sprite = cocos.sprite.Sprite(image.texture)
2Dゲームと言えば、昔のスーファミやアーケードゲームの画面を連想するわけで…。当時の拡大縮小処理はドットがジャギジャギしてたよなと。なので、個人的にはクッキリジャギジャギのほうが好み…。
◎ ショートカットキー。 :
cocos2dのウインドウが表示された状態で、以下のキーを押すと、各機能が働く。
他のショートカットキーは以下を参考に。Ctrl + S や Ctrl + W があるっぽい。
_Default Handlers - cocos v0.6.4 documentation
余談だけど。FPSを表示しても、自分の環境では何故か60FPSにならなくて、55〜56FPSのあたりをフラフラしてるのが気になる…。どういう計算・仕組みになってるんだろ?
- Ctrl + F : フルスクリーン表示の切り替え。
- Ctrl + P : ポーズ機能。
- Ctrl + X : FPS表示/非表示の切り替え。
- Ctrl + I : 内蔵インタプリタの起動/非表示の切り替え。
他のショートカットキーは以下を参考に。Ctrl + S や Ctrl + W があるっぽい。
_Default Handlers - cocos v0.6.4 documentation
余談だけど。FPSを表示しても、自分の環境では何故か60FPSにならなくて、55〜56FPSのあたりをフラフラしてるのが気になる…。どういう計算・仕組みになってるんだろ?
◎ 内蔵インタプリタによる動作確認作業。 :
cocos2dのウインドウが表示された状態で Ctrl + I を押すと、内蔵のPythonインタプリタが起動する。
_Built-in Python Interpreter - cocos v0.6.4 documentation
コレを使うと、以下の動画のようなことができるっぽい。
_cocos2d basic actions - YouTube
例えばだけど、下のような感じで打っていけば、一つずつ動作を確認できたりする。
少しだけ説明しておくと…。
_Built-in Python Interpreter - cocos v0.6.4 documentation
コレを使うと、以下の動画のようなことができるっぽい。
_cocos2d basic actions - YouTube
例えばだけど、下のような感じで打っていけば、一つずつ動作を確認できたりする。
director.scene.get_children() layer = director.scene.get_children()[0] layer layer.get_children() sprite = layer.get_children()[0] sprite sprite.position sprite.position = (200, 200) sprite.position = (300, 300) from cocos.actions import * sprite.do(MoveTo((400, 400), 2)) sprite.do(RotateBy(360, 3)) sprite.do(ScaleeBy(3, 1)) sprite.do(Reverse(ScaleeBy(3, 1)))
少しだけ説明しておくと…。
- 「.get_children()」は、ソイツに登録されてる子供達の一覧を取得するメソッド。
- 「.get_children()[0]」で、ソイツの子供達の中から、一番最初の子供を取得してる。
- 「.position」は、表示座標を保持してる変数。
- 「.do()」でアクション(移動、回転、拡大縮小等)を指定できる。
[ ツッコむ ]
#2 [python][cocos2d] Python + cocos2d のアクションについて
cocos2d のアクションについては、ちょっと記述が長くなりそうなので、別記事にしてメモ。
◎ アクションについて。 :
スプライトやレイヤーを、移動、回転、拡大縮小したい時には、アクション(actions)てのが使えるらしい。例えば以下のような感じの指定ができる。
- 「(x, y) の位置まで○秒かけて移動しろ」
- 「xxx度まで、○秒かけて回転しろ」
- 「xxx倍まで、○秒かけて拡大または縮小しろ」
◎ 下準備。 :
アクションを使いたいときは、スクリプトソースの最初のほうに、以下のような行を書くと記述が楽になるらしい。
from cocos.actions import *
◎ アクションの指定の仕方。 :
アクションは、「.do()」で指定する。
移動、回転、拡大縮小のアクションは以下のような感じ。
更に、以下で囲むことで、動作の様子を変える(?)ことができる。
「〜To()」は絶対値の指定で、「〜By()」は相対値の指定、らしい。
# (400, 300) の座標まで3秒かけて移動しろ、というアクション move = MoveTo((400, 300), 3) # スプライトにアクションを指示 sprite.do( move )
移動、回転、拡大縮小のアクションは以下のような感じ。
- 移動 : MoveTo((x, y), 秒)
- 回転 : RotateBy(角度, 秒)
- 拡大縮小 : ScaleBy(倍率, 秒)
更に、以下で囲むことで、動作の様子を変える(?)ことができる。
- 逆の動作 : Reverse() で囲む
- 永久に繰り返し : Repeat() で囲む。
「〜To()」は絶対値の指定で、「〜By()」は相対値の指定、らしい。
- 「最終的に、この座標値/角度/倍率にしろ」てな時は、「〜To()」で指示。
- 「今現在の座標値/角度/倍率から、これぐらい変化させろ」てな時は、「〜By()」で指示。
◎ アクションの複数指定。 :
各アクションは、繋げて(連続して?)指示したり、同時に指示したりできる。
繋げる時は、「+」を使う。
同時に指示する時は「|」を使う。
繋げる時は、「+」を使う。
scale = ScaleBy(3, 2) # 3倍まで2秒かけて拡大 sprite.do(scale + Reverse(scale))この例だと、2秒かけて3倍拡大した後、2秒かけて1/3に縮小する。( Reverse() で囲んでるので、逆の動きをする。つまり元の大きさに戻る)。
同時に指示する時は「|」を使う。
scale = ScaleBy(3, 2) # 3倍まで2秒かけて拡大 move = MoveTo((400, 100), 2) # (400,100)の位置に2秒かけて移動 sprite.do(scale | move)この例だと、2秒かけて3倍拡大しつつ、同時に、(400,100)の位置まで移動する。
◎ サンプルソース。 :
_Writing a cocos2d application - cocos v0.6.4 documentation
の内容に細かく日本語コメントをつけたソースを一応置いときます。というか貼っときます。
_cocos2d_actions.py
_enemy_ball.png
_cocos2d_actions.py
_enemy_ball.png
"""
cocos2d : actions sample.
http://python.cocos2d.org
"""
# cocos2D を使うときは import cocos を最初のあたりに書く
import cocos
from cocos.actions import *
# pygletも使う
import pyglet
class MyLayer(cocos.layer.ColorLayer):
u"""メインのレイヤー.
カラーレイヤー(cocos.layer.ColorLayer)のサブクラス.
"""
def __init__(self):
u"""初期化処理."""
# カラーレイヤーを青色で初期化
super(MyLayer, self).__init__(64, 64, 224, 255)
# labeを作成。
# cocos.text.Label は pyglet.text.Label のラッパー。
# CocosNode の利点を持つ。
label = cocos.text.Label(
'cocos.text.Label',
font_name='Times New Roman',
font_size=24,
anchor_x='center', anchor_y='center',
position=(400, 200)
)
# ラベルをレイヤーに登録。デフォルトのz値は0
self.add(label)
# pygletを使って画像を読み込み
image = pyglet.image.load('./enemy_ball.png')
# 拡大縮小時にボケないようフィルタを指定。
pyglet.gl.glBindTexture(image.texture.target, image.texture.id)
pyglet.gl.glTexParameteri(image.texture.target,
pyglet.gl.GL_TEXTURE_MIN_FILTER,
pyglet.gl.GL_NEAREST)
pyglet.gl.glTexParameteri(image.texture.target,
pyglet.gl.GL_TEXTURE_MAG_FILTER,
pyglet.gl.GL_NEAREST)
# spriteを生成
# cocos.sprite.Sprite は pyglet.sprite.Sprite のラッパー
sprite = cocos.sprite.Sprite(image.texture, position=(400, 400))
# スプライトのスケール(拡大縮小率)を指定。デフォルトは1
sprite.scale = 6
# スプライトをレイヤーに登録。z値を1に
self.add(sprite, z=1)
# スケール変化のアクションを用意する。6倍まで1.5秒かけて変化
scale = ScaleBy(6, duration=1.5)
# ラベルにアクションを指定。スケール変化(拡大→縮小)を繰り返す
label.do(Repeat(scale + Reverse(scale)))
# スプライトにアクションを指定。スケール変化(縮小→拡大)を繰り返す
sprite.do(Repeat(Reverse(scale) + scale))
if __name__ == "__main__":
# directorの初期化は pyglet.window と同じ引数を取る
cocos.director.director.init(width=800, height=600)
# レイヤーを作成
layer = MyLayer()
# 回転アクションをレイヤーに対して指定
layer.do(RotateBy(360, duration=4))
# hello_layer レイヤーを含んだシーンを作成
scene = cocos.scene.Scene(layer)
# メインシーンを director に渡して実行
cocos.director.director.run(scene)
実行すると、レイヤーがぐるりと回りつつ、レイヤーに登録されたスプライトとラベルが拡大縮小を繰り返す、みたいな。
[ ツッコむ ]
#3 [zatta][python][cocos2d] cocos2dって名前が良くない気がする
「python cocos2d」でググってみても関連記事がなかなか出てこなくて困るなと。というのも、cocos2d-x の記事ばかり出てくるわけで。マズイことに、cocos2d-x も開発ツールの関係で Python を使うようで。そりゃリストアップされるわな…。困る…。
もはや cocos2d という名前がよろしくないのだろうなと。例えばだけど、pycocos2d みたいな名前に途中で変更していたら、こういう場面でも少しは違う結果に…。
などと思いつつ、ふとググってみたら、既に _pycocos2d という名前を使った別パッケージが存在するようで。cocos2d-x のPythonバインディング、とな…。cocos2d を参考にして作られた cocos2d-x を Python で使えるように、てな展開に首を捻ったり。cocos2d-x の成果を元々の cocos2d に反映させる流れにはならなかったのだろうか…。 _seewindcn/pycocos2d: cocos2d-x python binding を眺めた感じでは4年前に開発停止状態。作者さんのリポジトリを眺めたらどうやら Unity に移行しちゃったようで。cocos2d系には見切りをつけたということかな…。
Python + cocos2d を試してるのは、Raspberry Pi上で動くゲーム制作ライブラリとしては使えるのかなと気になってるからで。Unity は Raspberry Pi上で動かないのだよなあ…。Scratch は1フレーム1命令っぽいからリアルタイムゲームの作成なんかほぼ無理だし。
もはや cocos2d という名前がよろしくないのだろうなと。例えばだけど、pycocos2d みたいな名前に途中で変更していたら、こういう場面でも少しは違う結果に…。
などと思いつつ、ふとググってみたら、既に _pycocos2d という名前を使った別パッケージが存在するようで。cocos2d-x のPythonバインディング、とな…。cocos2d を参考にして作られた cocos2d-x を Python で使えるように、てな展開に首を捻ったり。cocos2d-x の成果を元々の cocos2d に反映させる流れにはならなかったのだろうか…。 _seewindcn/pycocos2d: cocos2d-x python binding を眺めた感じでは4年前に開発停止状態。作者さんのリポジトリを眺めたらどうやら Unity に移行しちゃったようで。cocos2d系には見切りをつけたということかな…。
Python + cocos2d を試してるのは、Raspberry Pi上で動くゲーム制作ライブラリとしては使えるのかなと気になってるからで。Unity は Raspberry Pi上で動かないのだよなあ…。Scratch は1フレーム1命令っぽいからリアルタイムゲームの作成なんかほぼ無理だし。
[ ツッコむ ]
以上、1 日分です。
