キー等でCanvasに描いたオブジェクトを動かす時、等速ではなく加速度をつけるスクリプト。マウスでクリックした後に矢印キーで縦横に動かせる。
移動に加速度をつける
まず、猫画像を表示するCatクラス(cat.js)。
/** * 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._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.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; } }
次に、移動処理を行うVelosityクラス(velosity.js)。
import { Cat } from "./cat.js"; /** * 画像の移動に加速度をつける(velosity.js) */ export class Velosity { constructor() { this._cvs = document.getElementById('canvas'); this._ctx = this._cvs.getContext('2d'); this._cat; this._vx = 0; this._vy = 0; this._ax = 0; // accelerationのa this._ay = 0; this._cvs.setAttribute('tabindex', 0); // ①tabindexの指定でキーイベントを受け取れるようにする 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; 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) { // ④矢印キーが離されたら加速度を0に this._ax = this._ay = 0; } }
requestAnimationFrameを使ったゲームループの実装は、「【JavaScript】requestAnimationFrameでゲームループを作る」を参照。
①Canvasにキーイベントを設定するには、Canvas要素にtabindexを付与しなければならない。HTML側で指定してもよいが、ここではJavaScript側で設定している。
②速度を表す変数this._vx、this._vyに、加速度を表すthis._ax、this._ayをフレーム毎に加減。その値を猫画像のX、Y座標に代入し再描画。
③矢印キーが押されると_onKeydownイベントハンドラが呼び出され、押された矢印キーを判別して対応する向きの値を変数に代入。
④矢印キーが離されたらthis._ax、this._ayを0にリセット。
移動に加速度と角度もつける
イラスト:カクレノ(https://kotonohaworks.com/free-icons/)
上のスクリプトは左右キーを角度の変更に使い、上キーでのみ進むように変えたもの。向きが判別しやすいよう、画像を猫から飛行機に変更した。
import { Plane } from "./plane.js"; /** * 画像の移動に角度と加速度をつける(velosity2.js) */ export class Velosity2 { constructor() { this._cvs = document.getElementById('canvas'); this._ctx = this._cvs.getContext('2d'); this._plane; this._vx = 0; this._vy = 0; this._vr = 0; // 回転させる角度量 this._thrust = 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._plane = new Plane(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._plane.rotation += this._vr; let angle = this._plane.rotation; let ax = Math.cos(angle) * this._thrust; let ay = Math.sin(angle) * this._thrust; // ②加速度を以前の速度に加算 this._vx += ax; this._vy += ay; this._plane.x += this._vx; this._plane.y += this._vy; this._plane.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._vr = -0.05; break; case 39: // 右矢印キー this._vr = 0.05; break; case 38: // 上矢印キー this._thrust = 0.05; break; } } _onKeyUp(e) { this._vr = 0; this._thrust = 0; } }
スクリプトの基本は「【JavaScript】マウスカーソルを追いかけるマウスストーカーを作る」で作ったカーソルを追いかけてくる矢印。そのスクリプトに加速度を導入し、自分で動かせるように改変したもの。
①角度(this._vr)を元に画像を回転させている。②加速度を画像のX、Y座標に代入。上キーを押し続けるほど推進力(this._thrust)は増加し、どんどん加速していく。
Plane.jsは読み込む画像を猫から飛行機に変えただけで同じもの。
コメント