Cocos2d のイベント,キーコード,イベントハンドラ,アクション

1. エグゼクティブサマリー

Cocos2d は2次元ゲームのフレームワークである.Python で動作する. (Cocos2d から派生した Cocos2d-x は iOS や Android でも動き,普及している.)

このページでは,次の事項を見本プログラムで演習する.

関連する資料:Cocos2d の概要 [PDF], [パワーポイント]

関連する資料:ゲームエンジン[PDF], [パワーポイント]

関連する外部ページhttps://www.cocos.com/endoc.html

謝辞:Cocos2d の作者に感謝します.https://github.com/liamrahav/cocos2d-python-tutorials/blob/master/basics/ で公開されているサンプルプログラムを参考にした.

2. 前準備(必要ソフトウェアの入手)

ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。

Python 3.12 のインストール(Windows 上) [クリックして展開]

以下のいずれかの方法で Python 3.12 をインストールする。Python がインストール済みの場合、この手順は不要である。

方法1:winget によるインストール

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

winget install --scope machine --id Python.Python.3.12 -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_pip=1 Include_test=0 Include_launcher=1 InstallLauncherAllUsers=1"

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動すると PATH が自動的に設定される。

方法2:インストーラーによるインストール

  1. Python 公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンから Windows 用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」に必ずチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

AIエディタ Windsurf のインストール(Windows 上) [クリックして展開]

Pythonプログラムの編集・実行には、AIエディタの利用を推奨する。ここでは、Windsurfのインストールを説明する。Windsurf がインストール済みの場合、この手順は不要である。

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

winget install --scope machine --id Codeium.Windsurf -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --custom "/SP- /SUPPRESSMSGBOXES /NORESTART /CLOSEAPPLICATIONS /DIR=""C:\Program Files\Windsurf"" /MERGETASKS=!runcode,addtopath,associatewithfiles,!desktopicon"
powershell -Command "$env:Path=[System.Environment]::GetEnvironmentVariable('Path','Machine')+';'+[System.Environment]::GetEnvironmentVariable('Path','User'); windsurf --install-extension MS-CEINTL.vscode-language-pack-ja --force; windsurf --install-extension ms-python.python --force; windsurf --install-extension Codeium.windsurfPyright --force"

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動すると PATH が自動的に設定される。

関連する外部ページ

Windsurf の公式ページ: https://windsurf.com/

cocos2d, pyglet のインストール [クリックして展開]

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

pip install cocos2d pyglet

Windows での cocos2d, pyglet のインストールの詳細は,別ページ »で説明している.

3. 実行のための準備とその確認手順(Windows 前提)

3.1 プログラムファイルの準備

第5章に掲載するソースコードをテキストエディタ(メモ帳,Windsurf 等)に貼り付け,それぞれ以下のファイル名で保存する(文字コード:UTF-8).

3.2 実行コマンド

コマンドプロンプトでファイルの保存先ディレクトリに移動し,以下を実行する.

python mouse_click.py
python keyboard_move.py
python action_move.py
python action_jump.py

3.3 動作確認チェックリスト

確認項目期待される結果
プログラム起動時640×480 のウインドウが表示され,左下付近に「Hello,World!」のラベルが表示される
mouse_click.py:画面内をクリッククリックした座標にラベルが移動する
keyboard_move.py:画面内をクリック後,矢印キーを押す矢印キーの方向にラベルが10画素ずつ移動する
action_move.py:画面内をクリック後,スペースキーを押すラベルが2秒かけて右に200画素,上に100画素移動する(MoveBy)
action_move.py:R キーを押すラベルが2秒かけて360度回転する(RotateBy)
action_jump.py:画面内をクリック後,スペースキーを押すラベルが5秒かけて5回ジャンプしながら右に300画素,上に100画素移動する(JumpBy)
action_jump.py:S キーを押すラベルが1秒かけて2倍に拡大する(ScaleBy)
ウインドウ右上の「x」をクリックプログラムが終了する

4. 概要・使い方・実行上の注意

イベント,キーコード,イベントハンドラ

マウス操作

  1. Python プログラムの実行
  2. 画面が現れるので確認する.
  3. 画面内をクリックすると,オブジェクトが移動する.
  4. 結果を確認したら,右上の「x」をクリックして終了する.

* 演習問題: 上の手順を行いなさい.

* 演習問題: 「Hello,World!」を別のものに変えて変化を見なさい. 画面内をクリックすること. 結果を確認したら,右上の「x」をクリックして終了すること.

キーボード操作

  1. Python プログラムの実行
  2. 画面が現れるので確認する.
  3. 画面内を1回クリックしたあと,キーボードの矢印キーをいろいろ連打する.(矢印キーは4つある)
  4. 結果を確認したら,右上の「x」をクリックして終了する.

* 演習問題: 上の手順を行いなさい.

* 演習問題: 「+= 10」, 「-= 10」 の「10」を別の数値に変えて変化を見なさい.全部で4か所ある. 結果を確認したら,右上の「x」をクリックして終了すること.


アクション

関連する外部ページhttps://www.cocos.com/endoc/api/cocos.actions.interval_actions.html

移動(MoveBy, MoveTo)

  1. Python プログラムの実行
  2. 画面が現れるので確認する.
  3. key.SPACE」はスペースキーを表す.「key.R」で R キーを押すと,オブジェクトが2秒かけて360度回転する.

    画面内を1回クリックしたあと,スペースキーR キーをゆっくり何度か押しなさい.

  4. 結果を確認したら,右上の「x」をクリックして終了する.

* 演習問題: 上の手順を行いなさい.

* 演習問題: 「MoveBy((200, 100), 2)」のところを,下のように変えて変化を見なさい.

スペースキーを押して1度移動したら,何度スペースキーを押しても動かないことを確認する. 結果を確認したら,右上の「x」をクリックして終了すること.

MoveTo((300, 400), duration=5) ・・・ 5秒かけて,(300, 400)の場所に移動する.

* 演習問題: 次を追加しなさい.

字下げにも注意すること.下の図の通り,字下げしなさい.

画面内でクリックすると,オブジェクトが動くので確認すること. 結果を確認したら,右上の「x」をクリックして終了すること.

    def on_mouse_press(self, x, y, buttons, modifiers):
        self.myactor.do(cocos.actions.MoveTo((x, y), 2))

ジャンプ(JumpBy, JumpTo)

  1. Python プログラムの実行
  2. 画面が現れるので確認する.
  3. key.SPACE」はスペースキーを表す.「key.S」で S キーを押すと,オブジェクトが1秒かけて2倍に拡大する.

    画面内を1回クリックしたあと,スペースキーS キーをゆっくり何度か押しなさい.

    JumpBy((300, 100), 100, 5, duration=5) ・・・ 5秒かけて,右に300画素,上に100画素ジャンプする.ジャンプの回数は5回で,100画素分の高さである.
  4. 結果を確認したら,右上の「x」をクリックして終了する.

* 演習問題: 上の手順を行いなさい.

* 演習問題: 「JumpBy((320,0), 100, 5, duration=5)」のところを,下のように変えて変化を見なさい.

スペースキーを押して1度移動したら,何度スペースキーを押しても動かないことを確認する. 結果を確認したら,右上の「x」をクリックして終了すること.

JumpTo((100,100), 100, 5, duration=5) ・・・ 5秒かけて,(100,100)の場所にジャンプする.


* 演習問題: 次を追加しなさい.

字下げにも注意すること.下の図の通り,字下げしなさい.

画面内でクリックすると,オブジェクトが動くので確認すること. 結果を確認したら,右上の「x」をクリックして終了すること.

    def on_mouse_press(self, x, y, buttons, modifiers):
        self.myactor.do(cocos.actions.JumpTo((x, y), 100, 5, duration=5))

5. ソースコード

マウス操作(mouse_click.py)

import cocos
from cocos import scene
from cocos.layer import Layer
from cocos.director import director
from pyglet.window import key

class MyActor(cocos.text.Label):
    def __init__(self, text, x, y, size, rgba):
        super(MyActor, self).__init__(
            text, font_name="Times New Roman", font_size=size,
            anchor_x='center', anchor_y='center', color=rgba)
        self.position = cocos.euclid.Vector2(x, y)

class Layer00(Layer):
    is_event_handler = True
    def __init__(self):
        super(Layer00, self).__init__()
        self.myactor = MyActor("Hello,World!", 0, 0, 32, (0, 200, 255, 255))
        self.add(self.myactor)
    def on_mouse_press(self, x, y, buttons, modifiers):
        self.myactor.x = x
        self.myactor.y = y

director.init(width=640, height=480)
director.run(scene.Scene(Layer00()))

キーボード操作(keyboard_move.py)

import cocos
from cocos import scene
from cocos.layer import Layer
from cocos.director import director
from pyglet.window import key

class MyActor(cocos.text.Label):
    def __init__(self, text, x, y, size, rgba):
        super(MyActor, self).__init__(
            text, font_name="Times New Roman", font_size=size,
            anchor_x='center', anchor_y='center', color=rgba)
        self.position = cocos.euclid.Vector2(x, y)

class Layer00(Layer):
    is_event_handler = True
    def __init__(self):
        super(Layer00, self).__init__()
        self.myactor = MyActor("Hello,World!", 0, 0, 32, (0, 200, 255, 255))
        self.add(self.myactor)
    def on_key_press(self, symbol, modifiers):
        if symbol == key.RIGHT:
            self.myactor.x += 10
        elif symbol == key.LEFT:
            self.myactor.x -= 10
        elif symbol == key.UP:
            self.myactor.y += 10
        elif symbol == key.DOWN:
            self.myactor.y -= 10

director.init(width=640, height=480)
director.run(scene.Scene(Layer00()))

移動アクション(action_move.py)

import cocos
from cocos import scene
from cocos.layer import Layer
from cocos.director import director
from pyglet.window import key

class MyActor(cocos.text.Label):
    def __init__(self, text, x, y, size, rgba):
        super(MyActor, self).__init__(
            text, font_name="Times New Roman", font_size=size,
            anchor_x='center', anchor_y='center', color=rgba)
        self.position = cocos.euclid.Vector2(x, y)

class Layer00(Layer):
    is_event_handler = True
    def __init__(self):
        super(Layer00, self).__init__()
        self.myactor = MyActor("Hello,World!", 0, 0, 32, (0, 200, 255, 255))
        self.add(self.myactor)
    def on_key_press(self, symbol, modifiers):
        if symbol == key.RIGHT:
            self.myactor.x += 10
        elif symbol == key.LEFT:
            self.myactor.x -= 10
        elif symbol == key.UP:
            self.myactor.y += 10
        elif symbol == key.DOWN:
            self.myactor.y -= 10
        elif symbol == key.SPACE:
            self.myactor.do(cocos.actions.MoveBy((200, 100), 2))
        elif symbol == key.R:
            self.myactor.do(cocos.actions.RotateBy(360, 2))

director.init(width=640, height=480)
director.run(scene.Scene(Layer00()))

ジャンプアクション(action_jump.py)

import cocos
from cocos import scene
from cocos.layer import Layer
from cocos.director import director
from pyglet.window import key

class MyActor(cocos.text.Label):
    def __init__(self, text, x, y, size, rgba):
        super(MyActor, self).__init__(
            text, font_name="Times New Roman", font_size=size,
            anchor_x='center', anchor_y='center', color=rgba)
        self.position = cocos.euclid.Vector2(x, y)

class Layer00(Layer):
    is_event_handler = True
    def __init__(self):
        super(Layer00, self).__init__()
        self.myactor = MyActor("Hello,World!", 0, 0, 32, (0, 200, 255, 255))
        self.add(self.myactor)
    def on_key_press(self, symbol, modifiers):
        if symbol == key.RIGHT:
            self.myactor.x += 10
        elif symbol == key.LEFT:
            self.myactor.x -= 10
        elif symbol == key.UP:
            self.myactor.y += 10
        elif symbol == key.DOWN:
            self.myactor.y -= 10
        elif symbol == key.SPACE:
            self.myactor.do(cocos.actions.JumpBy((300, 100), 100, 5, duration=5))
        elif symbol == key.S:
            self.myactor.do(cocos.actions.ScaleBy(2, duration=1))

director.init(width=640, height=480)
director.run(scene.Scene(Layer00()))

6. まとめ

イベント

イベントとは,ユーザの入力(キーボード操作,マウス操作,ウインドウ操作など)によって発生するものである.Cocos2d では on_key_press,on_mouse_press,on_mouse_motion などのイベントが用意されている.

キーコード

キーコードとは,キーボードの各キーに割り当てられたコード(符号)である.pyglet では key.RIGHT,key.SPACE,key.A などの定数として定義されている.

イベントハンドラ

イベントハンドラとは,特定のイベントが発生したときに実行されるプログラムである.Layer クラスに is_event_handler = True を設定し,on_key_press や on_mouse_press などのメソッドを定義することで実装する.

アクション

アクションとは,オブジェクトの属性を変化させる操作である.即時(InstantAction),インターバル(IntervalAction),その他(Action)の3種類がある.MoveBy,MoveTo,JumpBy,JumpTo,RotateBy,ScaleBy などが代表的である.

do メソッド

オブジェクトにアクションを実行するには do メソッドを使用する.self.myactor.do(cocos.actions.MoveBy((200, 100), 2)) のように記述することで,移動や回転などのアクションを適用できる.