「【JavaScript】加速度を使った移動」では、猫画像を矢印キーで操作したが、画面端を過ぎると猫が見えなくなっていた。今回は猫が画面端に達したら、反対側から現れるように手を加えた。
まず、猫画像を表示するCatクラス。以前と異なるのは幅と高さを取得できるよう、width、heightゲッターを追加しているところ。
/** * cat.js * 猫画像を表示 */ export class Cat { constructor(parent = undefined, x = 0, y = 0) { if (parent !== undefined) { this._parent = parent; } this._x = x; this._y = y; this._rotation = 0; this._img; this._init(); } ////////////////////////////////// // Private and protected ////////////////////////////////// _init() { if (this._parent !== undefined) { this._ctx = this._parent; } this._img = new Image(); this._img.src = "./cat.png"; this.draw(); } ////////////////////////////////// // Public ////////////////////////////////// draw() { // 現在の描画状態を保存 this._ctx.save(); // コンテキストの座標を変更し、キャンバス中央に移動 this._ctx.translate(this._x, this._y); // コンテキストの角度をラジアン値で指定 this._ctx.rotate(this._rotation); this._ctx.drawImage(this._img, -(this._img.width / 2), -(this._img.height / 2)); // save()で保存した描画状態を復元 this._ctx.restore(); } ////////////////////////////////// // Getters/Setters ////////////////////////////////// get x() { return this._x; } set x(x) { this._x = x; } get y() { return this._y; } set y(y) { this._y = y; } get width() { return this._img.width; } get height() { return this._img.height; } get rotation() { return this._rotation; } set rotation(rotation) { this._rotation = rotation; } }
次に、猫を移動処理を行うBoundaryクラス。
import { Cat } from "./cat.js"; /** * 画像の移動に加速度をつける(boundary.js) */ export class Boundary { constructor() { this._cvs = document.getElementById('canvas'); this._ctx = this._cvs.getContext('2d'); // ①キャンバスの端を表す変数を宣言 this._leftEnd = 0; // キャンバス左端 this._rightEnd = this._cvs.width; // キャンバス右端 this._topEnd = 0; // キャンバス上端 this._bottomEnd = this._cvs.height; // キャンバス下端 this._cat; this._vx = 0; this._vy = 0; this._ax = 0; this._ay = 0; this._cvs.setAttribute('tabindex', 0); this._cvs.addEventListener('keydown', this._onKeydown.bind(this)); this._cvs.addEventListener('keyup', this._onKeyUp.bind(this)); // タイマー関連 this._animID; this._isAnim = 0; this._FPS = 60; this._frame = 0; this._startTime; this._nowTime; this._init(); } ////////////////////////////////// // Private and protected ////////////////////////////////// _init() { this._cvs.style.backgroundColor = "#eeeeee"; this._cat = new Cat(this._ctx, this._cvs.width / 2, this._cvs.height / 2); this._startTime = performance.now(); this._mainLoop(); } _mainLoop() { this._nowTime = performance.now(); let elapsedTime = this._nowTime - this._startTime; let idealTime = this._frame * (1000 / this._FPS); if (idealTime < elapsedTime) { this._ctx.clearRect(0, 0, this._cvs.width, this._cvs.height); this._vx += this._ax; this._vy += this._ay; this._cat.x += this._vx; this._cat.y += this._vy; // ②画面端から反対側に出現させる処理 if (this._cat.x - this._cat.width / 2 > this._rightEnd) { this._cat.x = this._leftEnd - this._cat.width / 2; } else if (this._cat.x + this._cat.width / 2 < this._leftEnd) { this._cat.x = this._rightEnd + this._cat.width / 2; } if (this._cat.y - this._cat.height / 2 > this._bottomEnd) { this._cat.y = this._topEnd - this._cat.height / 2; } else if (this._cat.y < this._topEnd - this._cat.height / 2) { this._cat.y = this._bottomEnd + this._cat.height / 2; } this._cat.draw(); this._frame++; if (elapsedTime >= 1000) { this._startTime = this._nowTime; this._frame = 0; } } this._animID = requestAnimationFrame(this._mainLoop.bind(this)); } ////////////////////////////////// // Handlers ////////////////////////////////// _onKeydown(e) { switch (e.keyCode) { case 37: // 左矢印キー this._ax = -0.2; break; case 39: // 右矢印キー this._ax = 0.2; break; case 38: // 上矢印キー this._ay = -0.2; break; case 40: // 下矢印キー this._ay = 0.2; break; } } _onKeyUp(e) { this._ax = this._ay = 0; } }
requestAnimationFrameを使ったゲームループの実装は、「【JavaScript】requestAnimationFrameでゲームループを作る」を参照。
前回のスクリプトと異なるのは①と②の部分のみ。
①でキャンバスの上、右、下、左端の値を格納する変数を宣言し、値を代入。
②1つ目のif文は左右の端の判定をしている。画像のX座標に画像の幅の1/2を引いて、左端の位置を計算。画像幅1/2を引く理由は、猫画像はCatクラス側でコンテキストの座標を変更し、画像の中央を描画の中心にしているため。画像の左端の位置が、右端を超えれば位置を変更し、反対側から現れるようにしている。
2つ目のif文は同じことを上下で行っている。
リンク
リンク
コメント