ドラゴンレーダー風ナビ ~エンジン編~(3/4)

距離に合わせてスケールを変更

距離感をよりわかりやすくするために、長距離・中距離・短距離・近距離と切り替わるタイミングで、スケールを切り替えましょう。
スケールの大小は、マス目の大きさで表現します。
 
 
円の中に引いた枠線シェイプを変数で記憶しておいて、切り替え時には既存の枠線シェイプを消してから、新しい枠線シェイプを作成し直します。

留意点としては、枠線を作成し直した時にシェイプの重なり順が変わってしまいます。
枠線の上に中心点を表す三角形のシェイプを表示したいので、枠線を作成し直した後に、中心点シェイプの深度を変更して前面表示させておきましょう。
ステージからシェイプを削除
stage.removeChild(shape);
シェイプの深度を変更して前面表示
stage.setChildIndex(shape,(stage.getNumChildren())-1);
<canvas id="myCanvas3" width="260" height="300"></canvas>

<input type="radio" name="scaleType" id="scaleType1" onclick="scaleChange(1)"> <label for="scaleType1">長距離</label> 
<input type="radio" name="scaleType" id="scaleType2" onclick="scaleChange(2)" checked="checked"> <label for="scaleType2">中距離</label><br />
<input type="radio" name="scaleType" id="scaleType3" onclick="scaleChange(3)"> <label for="scaleType3">短距離</label> 
<input type="radio" name="scaleType" id="scaleType4" onclick="scaleChange(4)"> <label for="scaleType4">近距離</label>

<script type="text/javascript">
var stage;  //Stageオブジェクト
var shpCenter; //中心点Shape
var shpLine = new Array();  //枠線Shape配列
var currentScaleType; //現在のスケール種類
var circleX = 130;  //円の中央点X座標
var circleY = 170;  //円の中央点Y座標
var radius = 100;  //円の半径

window.addEventListener("load", sample3);
function sample3() {
  //Stageオブジェクトを作成
  stage = new createjs.Stage("myCanvas3");
  
  //ベースのデザインを作成
  createBaseDesign();
  //円の中の枠線を作成
  currentScaleType = 2;
  drawLineInCircle();
  
  //中心点Shapeを作成
  shpCenter = new createjs.Shape();
  shpCenter.graphics.beginFill("red");
  shpCenter.graphics.moveTo(130, 160);
  shpCenter.graphics.lineTo(120, 180);
  shpCenter.graphics.lineTo(140,  180);
  shpCenter.graphics.lineTo(130, 160);
  stage.addChild(shpCenter);
  
  //Stageの描画を更新
  stage.update();
}
/*
 ベースのデザインを作成
*/
function createBaseDesign() {
  var shape1 = new createjs.Shape();
  shape1.graphics.beginLinearGradientFill(["#008500","#003500"], [0.1,1.0], 130, 70, 200, 270);
  shape1.graphics.drawCircle(130, 170, 100);
  stage.addChild(shape1);
  var shape2 = new createjs.Shape();
  shape2.graphics.beginStroke("gray");
  shape2.graphics.setStrokeStyle(3);
  shape2.graphics.arc(130, 170, 115, Math.PI*1.58, Math.PI*1.42, false);
  stage.addChild(shape2);
  shape3 = new createjs.Shape();
  shape3.graphics.beginStroke("gray");
  shape3.graphics.setStrokeStyle(1);
  shape3.graphics.drawCircle(130, 170, 100);
  stage.addChild(shape3);
  var shape4 = new createjs.Shape();
  shape4.graphics.beginStroke("gray");
  shape4.graphics.setStrokeStyle(1);
  shape4.graphics.drawCircle(130, 170, 105);
  stage.addChild(shape4);
  var shape5 = new createjs.Shape();
  shape5.graphics.beginStroke("gray");
  shape5.graphics.setStrokeStyle(3);
  shape5.graphics.moveTo(100, 60);
  shape5.graphics.lineTo(110, 35);
  shape5.graphics.lineTo(150, 35);
  shape5.graphics.lineTo(160, 60);
  stage.addChild(shape5);
  var shape6 = new createjs.Shape();
  shape6.graphics.beginStroke("gray");
  shape6.graphics.setStrokeStyle(2);
  shape6.graphics.arc(130, 30, 22, Math.PI*0.0, Math.PI, true);
  stage.addChild(shape6);
  var shape7 = new createjs.Shape();
  shape7.graphics.beginStroke("gray");
  shape7.graphics.setStrokeStyle(2);
  shape7.graphics.moveTo(108, 30);
  shape7.graphics.lineTo(152, 30);
  stage.addChild(shape7);
  var shape8 = new createjs.Shape();
  shape8.graphics.beginStroke("gray");
  shape8.graphics.beginFill("#dcdcdc");
  shape8.graphics.setStrokeStyle(2);
  shape8.graphics.drawRect(115, 30, 30, 5);
  stage.addChild(shape8);
}
/*
 円の中に枠線を引く
*/
function drawLineInCircle(){
  //円の中に垂直線を引く
  verticalLineInCircle();
  //円の中に水平線を引く
  horizonLineInCircle();
}
/*
 円の中に垂直線を引く
*/
function verticalLineInCircle()
{
  var startX = 0;  //垂直線の開始X座標
  var increment = 20;  //垂直線の間隔
  
  switch (currentScaleType) {
    case 1:
    //長距離
      startX = 40;
      increment = 10;
      break;
    case 2:
    //中距離
      startX = 40;
      increment = 20;
      break;
    case 3:
    //近距離
      startX = 40;
      increment = 30;
      break;
    case 4:
    //短距離
      startX = 50;
      increment = 40;
      break;
  }
  
  var n = 0;
  while (true)
  {
    //X座標を決める
    var x = startX + increment * n;
    //X座標が円の外側の場合ループ終了
    if (x >= circleX + radius) break;
    //直角三角形の底辺aと斜辺cから、垂直線bの長さを求める
    //底辺aの長さを求める
    var a = Math.abs(circleX - x);
    //斜辺cは円の半径とイコール
    var c = radius;
    //三平方の定理「c^2 = a^2 + b^2」より
    //⇒ b = √(c^2 - a^2)
    var b = Math.sqrt(c * c - a * a);
    //Y座標を求める(上と下の2点)
    var y1 = circleY - b;
    var y2 = circleY + b;
    //垂直線を引く
    var shp = new createjs.Shape();
    shp.graphics.beginStroke("forestgreen");
    shp.graphics.setStrokeStyle(2);
    shp.graphics.moveTo(x, y1);
    shp.graphics.lineTo(x, y2);
    stage.addChild(shp);
    //枠線Shape配列に記憶
    shpLine.push(shp);
    //次の垂直線のために、変数nをカウントアップ
    n++;
  }
}
/*
 円の中に水平線を引く
*/
function horizonLineInCircle()
{
  var startY = 0;  //水平線の開始Y座標
  var increment = 20;  //水平線の間隔
  
  switch (currentScaleType) {
    case 1:
    //長距離
      startY = 80;
      increment = 10;
      break;
    case 2:
    //中距離
      startY = 80;
      increment = 20;
      break;
    case 3:
    //短距離
      startY = 80;
      increment = 30;
      break;
    case 4:
    //近距離
      startY = 90;
      increment = 40;
      break;
  }
  
  var n = 0;
  while (true)
  {
    //Y座標を決める
    var y = startY + increment * n;
    //Y座標が円の外側の場合ループ終了
    if (y >= circleY + radius) break;
    //直角三角形の底辺aと斜辺cから、水平線bの長さを求める
    //底辺aの長さを求める
    var a = Math.abs(circleY - y);
    //斜辺cは円の半径とイコール
    var c = radius;
    //三平方の定理「c^2 = a^2 + b^2」より
    //⇒ b = √(c^2 - a^2)
    var b = Math.sqrt(c * c - a * a);
    //X座標を求める(左と右の2点)
    var x1 = circleX - b;
    var x2 = circleX + b;
    //水平線を引く
    var shp = new createjs.Shape();
    shp.graphics.beginStroke("forestgreen");
    shp.graphics.setStrokeStyle(2);
    shp.graphics.moveTo(x1, y);
    shp.graphics.lineTo(x2, y);
    stage.addChild(shp);
    //枠線Shape配列に記憶
    shpLine.push(shp);
    //次の水平線のために、変数nをカウントアップ
    n++;
  }
}
/*
 スケールの切り替え
*/
function scaleChange(scaleType){
  //円の中の枠線をクリア
    for (var i = 0; i < shpLine.length; i++) {
      var shp = shpLine[i];
      stage.removeChild(shp);
  }
  shpLine.length = 0;
  
  //円の中に枠線を引く
  currentScaleType = scaleType;
  drawLineInCircle();
  
  //中心点Shapeを前面に表示
  stage.setChildIndex(shpCenter,(stage.getNumChildren())-1);
  
  //Stageの描画を更新
  stage.update();
}
</script>

目的地ポイントの座標を計算しよう

ドラゴンレーダー風ナビ ~デザイン編~」では、円と直線の交点を求めるのに「三平方の定理」を使いました。
今回も数学を使って、目的地ポイントの座標を求めます。

計算に使える情報は、Google Maps APIから取得した
  • 距離(長さ)
  • 方角(角度)
です。

長さ・角度から目的地のX座標・Y座標を求めるには、「三角関数」が使えそうです。
中学数学から高校数学へ。少しステップアップですね!

三角関数を使って座標を計算

斜面c、角度θ(単位はラジアン)とすると、点AのX座標・Y座標は
x = c * cosθ
y = c * sinθ
で求めることができます。

あなたへのおすすめ記事