Skip to content

パドルとボールの表示

それではゲームを作成していきます。 最初はパドルを表示しましょう。

パドルを表示する

パドルの画像は以下を利用します。

Akashic Engine で画像を表示するための手順は大きく分けて以下になります。

  1. 画像をアセットとして登録する
  2. 登録したアセットをシーンで読み込む
  3. アセットを表示するエンティティを生成する

まず、あらかじめ assets ディレクトリ内に images ディレクトリを作成しておきます。 上記を右クリック等で保存した後、 breakout_paddle.pngassets/images に保存してください。

assets
├── game.json
└── images
    └── breakout_paddle.png
assets
├── game.json
└── images
    └── breakout_paddle.png

breakout_paddle.png をゲームに登録するために akashic scan コマンドを実行します。

akashic scan asset
akashic scan asset

akashic scan は、現在のディレクトリからアセットファイルをスキャンして game.json を更新するコマンドです。

画像アセットの登録に成功すると、以下のように出力されます。

INFO: Removed the declaration for 'image/player.png'. The corresponding files to the path are not found.
INFO: Removed the declaration for 'image/shot.png'. The corresponding files to the path are not found.
INFO: Removed the declaration for 'audio/se'. The corresponding files to the path are not found.
INFO: Added the declaration for 'breakout_paddle.png' (assets/images/breakout_paddle.png)
INFO: Done!
INFO: Removed the declaration for 'image/player.png'. The corresponding files to the path are not found.
INFO: Removed the declaration for 'image/shot.png'. The corresponding files to the path are not found.
INFO: Removed the declaration for 'audio/se'. The corresponding files to the path are not found.
INFO: Added the declaration for 'breakout_paddle.png' (assets/images/breakout_paddle.png)
INFO: Done!

元々あったアセットの定義が削除され、新規に追加したパドル画像のアセットが登録されました。

続いて画像アセットをシーンで読み込ませるための設定を追加します。 g.Scene の生成部分を以下のように修正します。

javascript
    const scene = new g.Scene({
        game,
        assetPaths: ["/assets/images/breakout_paddle.png"],
    });
    const scene = new g.Scene({
        game,
        assetPaths: ["/assets/images/breakout_paddle.png"],
    });

assetPaths に先ほど追加した画像アセットのパスを指定します。

TIP

パスが /assets/images/... のように絶対パス (/ で始まるパス) で指定されている点に注意してください。 Akashic Engine では各アセットファイルへのアクセス時に game.json が存在するディレクトリをルート (/) から始まるように指定する必要があります。

それでは実際にパドルを表示してみましょう。 ゲーム内で画像を表示するには g.Sprite を利用します。

javascript
    scene.onLoad.add(() => {
        // ここからゲーム内容を記述します
        // ...
        // ここまでゲーム内容を記述します
        // paddle を作成
        const paddle = new g.Sprite({
            scene,
            src: scene.asset.getImage("/assets/images/breakout_paddle.png"),
            x: game.width / 2,
            y: game.height - 20,
            anchorX: 0.5,
            anchorY: 0.5,
        });
        scene.append(paddle); // paddle をシーンに追加
    });
    scene.onLoad.add(() => {
        // ここからゲーム内容を記述します
        // ...
        // ここまでゲーム内容を記述します
        // paddle を作成
        const paddle = new g.Sprite({
            scene,
            src: scene.asset.getImage("/assets/images/breakout_paddle.png"),
            x: game.width / 2,
            y: game.height - 20,
            anchorX: 0.5,
            anchorY: 0.5,
        });
        scene.append(paddle); // paddle をシーンに追加
    });

パドルの生成部分について一つずつ見ていきます。

g.Sprite は任意の画像を表示するためのエンティティです。

scene には現在のシーンを指定します。

TIP

new g.Sprite({ scene })new g.Sprite({ scene: scene }) の略記法です。

src に指定している scene.asset.getImage() は画像アセットを取得するメソッドです。 Akashic Engine は画像・音声などのファイルを アセット という単位で取り扱います。 scene で読み込んだアセットは scene.asset から参照することができます。 画像を表示することは、言い換えると「src に画像アセットを指定したスプライトエンティティを生成し、それをシーンに追加する」ことになります。

x, y は対象のスプライトエンティティの座標を示しています。 Akashic Engine は以下のように左上を基点とした座標系となります。

game.width, game.height はゲーム画面の大きさを示しています。 ここでは画面下部の左右中央に配置しています。

また、アンカーをパドルの中央に設定しています。

アンカーポイントは、エンティティ座標の基準となる点であり、また回転や拡大縮小する際の中心となる点です。 (0, 0) がエンティティの左上、(0.5, 0.5) がエンティティの中央、 (1, 1) がエンティティの右下になります。 (0.5, 0.1) のように x, y で別の値を指定したり (-1.0, 2.0) など 0 から 1 の範囲外の値を指定することもできます。

ここでは回転や拡縮は利用していませんが、後の衝突判定のロジックを単純化するため、全てのスプライトエンティティのアンカーを中心に設定することにします。

以降は基本的にすべてのスプライトエンティティのアンカーを中央に設定しています。

背景を表示する

ニコ生ゲームをニコニコ生放送上で実行すると、放送のストリーム映像を背景としてその上にゲームが表示されます。 黒色や白色などの単体色の文字をゲーム上でそのまま表示すると、ストリーム映像によってはその文字が見えづらくなる可能性があります。 ストリーム映像によってゲーム体験が阻害されるのを防ぐため、カバーとなる背景を表示しておきます。 ただし、放送のストリーム映像を完全に非表示にしてしまうと視聴者としても退屈となってしまうので、今回は透過度を 50% とします。

パドルの生成前に以下のような背景エンティティを作成します。

javascript
    scene.onLoad.add(() => {
        // 背景を作成
        const background = new g.FilledRect({
            scene,
            cssColor: "#fff",
            x: 0,
            y: 0,
            width: game.width,
            height: game.height,
            opacity: 0.5, // 透過度 50% で表示
        });
        scene.append(background); // 背景をシーンに追加

        // paddle を作成
        const paddle = new g.Sprite({
            ...
        });
        scene.append(paddle); // paddle をシーンに追加
    });
    scene.onLoad.add(() => {
        // 背景を作成
        const background = new g.FilledRect({
            scene,
            cssColor: "#fff",
            x: 0,
            y: 0,
            width: game.width,
            height: game.height,
            opacity: 0.5, // 透過度 50% で表示
        });
        scene.append(background); // 背景をシーンに追加

        // paddle を作成
        const paddle = new g.Sprite({
            ...
        });
        scene.append(paddle); // paddle をシーンに追加
    });

g.FilledRect は単純な長方形を表示するためのエンティティです。 ここでは cssColor#fff (白) を指定した上で opacity を 0.5 に設定しています。

cssColor には CSS の color プロパティに準拠した色が指定できます。 詳細は MDN のドキュメント などを参照してください。

また背景については、他のエンティティとの衝突や回転などの処理が不要なため、 x, y が 0 になっていることに注意してください。 アンカーポイントを指定していないので、背景エンティティの左上端が位置の基準になっています。

paddle をシーンに追加する前に背景をシーンに追加している点に注意してください。 Akashic Engine は基本的にシーンに追加した順番で描画されます。 もし paddle をシーンに追加したとに背景を追加してしまうと、パドルが背景の後ろに描画されてしまいます。

ゲームの描画順に関しては 描画順を変える も併せて参照してください。

TIP

エンティティ は Akashic Engine において 画面に描画されうる全ての基底クラス を表し、 g.E として提供されています。 したがって g.FilledRectg.Spriteg.E を継承していることになります。 エンティティにはその他にもテキストを描画するための g.Label やコマ送りのフレームアニメーションを描画する g.FrameSprite などがあります。

ゲームの起動

ここまで完了したら、一度ゲームを起動してみましょう。 npm start コマンドでゲームを起動できます。

sh
npm start
npm start

コマンド実行後、以下のように出力されます。

akashic-sandbox listen port: 3000
hosting game: /path/to/your/dir/game.json
please access to http://localhost:3000/game/ by web-browser
akashic-sandbox listen port: 3000
hosting game: /path/to/your/dir/game.json
please access to http://localhost:3000/game/ by web-browser

http://localhost:3000/game/ をウェブブラウザで表示してください。 画面下部にパドルが表示されていれば成功です。

ボールの追加

次にボールを表示してみましょう。 以下の画像ファイルをダウンロードして assets/images に配置します。

assets
├── game.json
└── images
    ├── breakout_ball.png
    └── breakout_paddle.png
assets
├── game.json
└── images
    ├── breakout_ball.png
    └── breakout_paddle.png

akashic scan コマンドを実行します。

sh
akashic scan asset
akashic scan asset

assetPaths にボールの画像ファイルを登録します。

javascript
    const scene = new g.Scene({
        game,
        assetPaths: ["/assets/images/breakout_paddle.png"],
        assetPaths: [
            "/assets/images/breakout_paddle.png",
            "/assets/images/breakout_ball.png",
        ],
    });
    const scene = new g.Scene({
        game,
        assetPaths: ["/assets/images/breakout_paddle.png"],
        assetPaths: [
            "/assets/images/breakout_paddle.png",
            "/assets/images/breakout_ball.png",
        ],
    });

パドルを作成した直後にボールを作成します。

javascript
    scene.onLoad.add(() => {
        // 背景を作成
        const background = new g.FilledRect({
            ...
        });
        scene.append(background);

        // paddle を作成
        const paddle = new g.Sprite({
            ...
        });
        scene.append(paddle); // paddle をシーンに追加

        // ball を作成
        const ball = new g.Sprite({
            scene,
            src: scene.asset.getImage("/assets/images/breakout_ball.png"),
            x: paddle.x,
            anchorX: 0.5,
            anchorY: 0.5,
        });
        ball.y = paddle.y - paddle.height / 2 - ball.height / 2 - 5;
        scene.append(ball); // ball をシーンに追加
    });
    scene.onLoad.add(() => {
        // 背景を作成
        const background = new g.FilledRect({
            ...
        });
        scene.append(background);

        // paddle を作成
        const paddle = new g.Sprite({
            ...
        });
        scene.append(paddle); // paddle をシーンに追加

        // ball を作成
        const ball = new g.Sprite({
            scene,
            src: scene.asset.getImage("/assets/images/breakout_ball.png"),
            x: paddle.x,
            anchorX: 0.5,
            anchorY: 0.5,
        });
        ball.y = paddle.y - paddle.height / 2 - ball.height / 2 - 5;
        scene.append(ball); // ball をシーンに追加
    });

ball.y については ball.height が確定してから算出しています。

ゲームを表示しているブラウザをリロードしてみましょう。 パドルの上部にボールが表示されていれば成功です。

以上がゲーム作成の導入になります。 次章以降では、実際にゲームとして遊べるようにコードを修正していきます。

実行例とソースコード

Playground で実行