まずは、ゲームの土台となるhtmlを作成します
- canvas: ゲーム画面となる場所
- main.js: プログラミングを書く場所
- フィールド(field): ゲームを描画している仮想の場所(見えない)
- スクリーン(screen): フィールドの一部を抜き取った仮想の画面(見えない)
- キャンバス(canvas): スクリーンをコピーして実際に映した場所(見える) ※スクリーンとキャンバスのアスペクト比を合わせないと映像が引き伸ばされるので注意
main.jsからhtmlのキャンバスに描画できるように必要な設定をしていく
- getElementByIdでhtmlの要素をmain.jsの変数で扱えるようにする
- キャンバスの幅と高さを設定する
- getContext("2d")で平面として扱うことを宣言します
最小値と最大値を入力すると、その範囲の値を整数としてランダムに返す
- Math.random()は 0 ~ 1 の範囲で小数値を返す
- Math.floor(x)は x の小数部切り捨てる
クラスを作成して、オブジェクトとして扱えるようにする
- コンストラクター
- オブジェクトが生成されたときに最初に実行する
- x,y: 位置、8bitシフト(256倍)した精度で管理する
- size: 星の大きさ(単なる四角形の1辺)
- 描画
- フレーム毎にキャンバスに描画する
- 色: ランダムにすることで瞬きを表現
- 描画: 位置と大きさを指定した四角形
星オブジェクトをたくさん生成して、キャンバスに描画する
- 星の数を決めて、その分、生成処理をする
- 背景をブラックにしてキャンバスに描画する
- 生成した星をキャンバスに描画する
フレームとは一秒間に何回描画するかを表す数字
一般的なゲームは60FPS(frames per second)で、一秒間に60回描画している
- gameLoop: フレーム毎に呼ばれる関数を作成する
- GAME_SPEED: 1フレームのms(milliseconds)を定義する
- setInterval: gameLoopを1フレーム時間毎に呼び出す
星が流れてくるように、移動情報と1フレーム毎の処理を実装する
- コンストラクター
- vx, vy: 速度、フレーム毎に加算位置に加算する(8bitシフト)
- 情報更新
- フレーム毎に処理する内容、移動や判定処理を記載する
- 移動: 位置に速度を加算する
- 再配置: 画面下まで移動したら、上に移動させる
フレーム毎の処理
- キャンバスに背景を描画する
- 情報更新: 移動などの数値の変化処理をする
- 描画処理: 更新後の状態をキャンバスに描画する
カメラワークの動きをつけることで、立体感を出す(後ほど、プレイヤーの動きに合わせてカメラワークさせる)
そのために、仮想キャンバスにフィールド全体を描画し、その一部をスクリーンとして切り抜き、それをキャンバスに描画する
- 仮想キャンバス = フィールド: 新しくキャンバスを作成し、vContextとする
- カメラ = スクリーン: フィールドからの一部をスクリーンとして切り抜く
- キャンバス: スクリーンの描画情報をキャンバスにコピーする
仮想キャンバスへの描画と、キャンバスへのコピー
- 星クラスの描画処理は vContext に変更する
- 背景描画処理も vContext に変更する
- カメラ位置を定義して、スクリーンを切り抜く
- キャンバスにスクリーンをコピーして描画させる
- imageフォルダを作成する
- こちらから画像ファイルを取得してフォルダに配置する
- 画像ファイルをmain.jsで読み込む
- imageInfo: 画像の必要な部分を抜き出す情報を管理するクラス
- x, y: 画像を抜き出す左上の位置
- width, height: 画像を抜き出す幅と高さ
- imageinfos: 複数のimageInfoを管理する配列
プレイヤークラスを実装する
- コンストラクター
- imageIndex: imageInfos配列から要素を取り出すための番号
- x,y: 位置、8bitシフト(256倍)した精度で管理する
- 描画
- imageInfoから座標と幅、高さを取得する
- x,y座標を8bitシフトさせてピクセル座標にする
- 画像の幅、高さの半分を減算し中心座標にする
- 仮想キャンバスに画像を描画する
gameLoopに、プレイヤーを描画する処理を追加する
描画する画像番号と座標を指定して、player.drawを呼び出す
キーを押しっぱなしにするとわかりますが、ある程度時間が経過しないと連続入力にならない、またその連続も早くはない
そこで、毎フレームキーが押されているかで判断できるようにする必要がある
- onkeydown: キーが押された時
- onkeyup: キーが離された時
- keycode別に状態管理することで、今どのキーが押されているのかが判定できる
プレイヤークラスで押されているキーに対する移動を実装する
- static #: プレイヤークラスに画像情報を静的に保持する
- コンストラクター
- speed: 1フレーム単位の移動距離、8bitシフト(256倍)
- imageIndex: 初期値は 2 にしておく
- 情報更新
- 方向キーが押されている場合、その方向の座標にspeed分の値を加算、減算する
- 描画
- プレイヤーが保持している座標を使うように修正する
- Playerクラスの静的なimageInfosを参照するように修正する
- gameLoop内のplayer.drawの呼び出しも修正する
左右に移動するときに、機体を傾く画像に切り替える
- コンストラクター
- count: 数フレーム単位の処理のために使う生存時間
- 情報更新
- count: インクリメントする
- 左右キーが押下されている場合、4フレーム単位で傾き画像に変化させる
- 左右キーが離されてる場合は、正面画像に変化させる
プレイヤーの移動に対応してカメラワークを実装する
gameLoop内のキャンバスの描画の直前で、カメラのx,y(左上の位置)を算出する
- cameraX: フィールド幅に対するプレイヤーのx位置(ピクセル)の割合を、カメラの可動範囲(フィールド幅 - カメラ幅)に適用する
- cameraY: フィールド高さに対するプレイヤーのy位置(ピクセル)の割合を、カメラの可動範囲(フィールド高さ - カメラ高さ)に適用する
フィールド外には移動できないようにする
- コンストラクター
- x,y: 初期位置が画面の真ん中になるようにする
- 情報更新
- 左右上下キーが押下された処理は、座標がフィールド範囲内の場合のみ実行するようにする