関数move内で進行方向が変わったときにオブジェクトの軌跡を辿る線を描きます。と言っても始点に想定される壁の位置から終点と想定される反対側の壁の位置を結ぶ線です。壁に当たる以外にもオブジェクト同士が接触した時にも描くのでちょっと面白く描かれる時もあります。(オブジェクト接触時は想定外の振る舞いもありますがこれも偶然の産物ということで。)
まずは関数setFromToです。
進行方向と逆に向かって壁に接触するところを始点として設定して
進行方向に向かって壁に接触するところを終点とします。
1 2 3 4 5 6 7 8 9 |
// 始点と終点を取得 setFromTo() { var angle = this.angle >= 0 ? this.angle -180 : this.angle + 180; console.log(angle); // 始点 this.xyFrom = this.getXYPoint(angle); // 終点 this.xyTo = this.getXYTo(this.angle); } |
続いて実際に始点と終点を算出する関数getCanvasEdgeです。
現時点のXY座標と角度から壁に接触する座標を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// キャンバスに接触するXY座標 getCanvasEdge(angle) { // XY座標 var x, y; // 対辺初期値 var yLength = this.y; // 底辺初期値 var xLength = this.x; // X加算値 var xPlus = 1; // Y加算値 var yPlus = 1; if (0 <= angle) { // 角度が正数の場合 // 下に向かうのでY=縦幅 y = this.height; // 高さは縦幅-Y yLength = this.height - this.y; if (angle < 90) { // 角度が90未満は横幅-X xLength = this.width - this.x; } } else { // 角度が負数の場合 // 上に向かうのでY=0 y = 0; // 減算するで-1 yPlus = -1; xPlus = -1; if (-90 <= angle) { // 角度が-90以上の場合は横幅-X xLength = this.width - this.x; } } // X座標算出 x = this.x + (this.calcAdjacent(yLength, angle) * xPlus); // 0より小さい場合は0, 横幅より大きい場合は横幅を設定する x = x < 0 ? 0 : this.width < x ? this.width : x; // X座標が0または横幅(横の壁からスタートする)場合はYを再度算出する if (!(x != 0 && x != this.width)) { y = this.y + (Math.abs(this.calcOpposite(xLength, angle)) * yPlus); } // 設定したXY座標を返す return {'x':x, 'y':y}; } |
動作するプログラムはこちらです。
ちょっと図解もしておきます。
って、これじゃわからないっすかね。。。
この関数は初めはもっとわかりやすいコーディングをしていたのですが、重複箇所が多かったのでかなりの作り変えました。コード自体は当初より1/3くらいになったと思います。始点と終点も別にしていたのですが、よくよく考えたら始点を求めるには進行方向と逆に進んだことにすればいいことが判明したのでそれだけでもかなりすっきりした気分です。図を何度も書いててひっくり返して見てたら「あれぇ~~!」と思った次第です。。
関数calcAdjacentでは対辺と角度から底辺を求めます。
まずは斜辺の長さを求めてから底辺を算出しています。
1 2 3 4 5 6 |
calcAdjacent(y, angle) { // 斜辺 = 対辺 / Sinθ var h = y / Math.sin(Math.PI / (180 / angle)); // 底辺 = 斜辺 * Cosθ return h * Math.cos(Math.PI / (180 / angle)); } |
関数calcOppositeでは底辺と角度から対辺を求めます。
まずは斜辺の長さを求めてから対辺を算出しています。
1 2 3 4 5 6 |
calcOpposite(x, angle) { // 対辺: 底辺 / Cosθ var h = x / Math.cos(Math.PI / (180 / angle)); // 斜辺 * Sinθ return h * Math.sin(Math.PI / (180 / angle)); } |
求めた始点と終点から線を描画します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 線を描画する drawLine() { // this.context.globalCompositeOperation = "destination-atop"; // パスを初期化 this.context.beginPath(); // 起点を設定 this.context.moveTo(this.xyFrom['x'], this.xyFrom['y']); // 終点を設定 this.context.lineTo(this.xyTo['x'], this.xyTo['y']); // パスを閉じる this.context.closePath(); // 線描画色 this.context.strokeStyle = this.strokeStyle; // 線を書く this.context.stroke(); // 起点と終点から角度をを求める var xLength = this.xyTo['x'] - this.xyFrom['x']; var yLength = this.xyTo['y'] - this.xyFrom['y']; var radian = Math.atan2(yLength, xLength); var angle = radian * 180 / Math.PI; } |
という感じです。
線を描くのはなんとなく思いついたのですが、三角関数とプログラミングを改めてエライ真剣に学習する羽目になりました。
しかしながら偶然の産物もあって面白い動きをしてくれるようになりました。