パドルとボールの表示
それではゲームを作成していきます。 最初はパドルを表示しましょう。
パドルを表示する
パドルの画像は以下を利用します。
Akashic Engine で画像を表示するための手順は大きく分けて以下になります。
- 画像をアセットとして登録する
- 登録したアセットをシーンで読み込む
- アセットを表示するエンティティを生成する
まず、あらかじめ assets
ディレクトリ内に images
ディレクトリを作成しておきます。 上記を右クリック等で保存した後、 breakout_paddle.png
を assets/images
に保存してください。
assets
├── game.json
└── images
└── breakout_paddle.png
breakout_paddle.png
をゲームに登録するために akashic scan
コマンドを実行します。
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!
元々あったアセットの定義が削除され、新規に追加したパドル画像のアセットが登録されました。
続いて画像アセットをシーンで読み込ませるための設定を追加します。 g.Scene
の生成部分を以下のように修正します。
const scene = new g.Scene({
game,
assetPaths: ["/assets/images/breakout_paddle.png"]
});
assetPaths
に先ほど追加した画像アセットのパスを指定します。
TIP
パスが /assets/images/...
のように絶対パス (/
で始まるパス) で指定されている点に注意してください。 Akashic Engine では各アセットファイルへのアクセス時に game.json が存在するディレクトリをルート (/
) から始まるように指定する必要があります。
それでは実際にパドルを表示してみましょう。 ゲーム内で画像を表示するには g.Sprite
を利用します。
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% とします。
パドルの生成前に以下のような背景エンティティを作成します。
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.FilledRect
や g.Sprite
も g.E
を継承していることになります。 エンティティにはその他にもテキストを描画するための g.Label
やコマ送りのフレームアニメーションを描画する g.FrameSprite
などがあります。
ゲームの起動
ここまで完了したら、一度ゲームを起動してみましょう。 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
http://localhost:3000/game/ をウェブブラウザで表示してください。 画面下部にパドルが表示されていれば成功です。
ボールの追加
次にボールを表示してみましょう。 以下の画像ファイルをダウンロードして assets/images
に配置します。
assets
├── game.json
└── images
├── breakout_ball.png
└── breakout_paddle.png
akashic scan
コマンドを実行します。
akashic scan asset
assetPaths
にボールの画像ファイルを登録します。
const scene = new g.Scene({
game,
assetPaths: ["/assets/images/breakout_paddle.png"],
assetPaths: [
"/assets/images/breakout_paddle.png",
"/assets/images/breakout_ball.png"
]
});
パドルを作成した直後にボールを作成します。
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
が確定してから算出しています。
ゲームを表示しているブラウザをリロードしてみましょう。 パドルの上部にボールが表示されていれば成功です。
以上がゲーム作成の導入になります。 次章以降では、実際にゲームとして遊べるようにコードを修正していきます。