(C)WorldWideSoftware

<!DOCTYPE html>
<html lang="ja">
 <head>
  <meta charset="utf-8">
  <title>触手の動き</title>
 </head>
 <body>
  <a href="http://www.wwsft.com">(C)WorldWideSoftware</a><br>
  <canvas id="bg" width="640" height="320"></canvas><br>
タップした方に触手が向くプログラムです。整数値だけで計算しています<br>
  <a href="ten00src.html">ソースコードの確認</a>

  <script>
  //描画面(キャンバス)の準備
  var cvs = document.getElementById("bg");
  var ctx = cvs.getContext("2d");

  //マウスとタップの判定
  var tapX = 120, tapY = 60;
  cvs.addEventListener("touchstart", touchStart);
  function touchStart(ev) {
   ev.preventDefault();
   var rect = ev.target.getBoundingClientRect();
   tapX = ev.touches[0].clientX-rect.left;
   tapY = ev.touches[0].clientY-rect.top;
  }

  cvs.addEventListener("mousedown", mouseDown);
  function mouseDown(ev) {
   var rect = ev.target.getBoundingClientRect();
   tapX = ev.clientX-rect.left;
   tapY = ev.clientY-rect.top;
  }

  //三角関数
  var SINDAT = [ //SINの値を定義する(1000倍した値)
  //0~89度
     0,  17,  34,  52,  69,  87, 104, 121, 139, 156, 173, 190, 207, 224, 241, 258, 275, 292, 309, 325, 342, 358, 374, 390, 406, 422, 438, 453, 469, 484,
   499, 515, 529, 544, 559, 573, 587, 601, 615, 629, 642, 656, 669, 681, 694, 707, 719, 731, 743, 754, 766, 777, 788, 798, 809, 819, 829, 838, 848, 857,
   866, 874, 882, 891, 898, 906, 913, 920, 927, 933, 939, 945, 951, 956, 961, 965, 970, 974, 978, 981, 984, 987, 990, 992, 994, 996, 997, 998, 999, 999,

  //90~179度
  1000, 999, 999, 998, 997, 996, 994, 992, 990, 987, 984, 981, 978, 974, 970, 965, 961, 956, 951, 945, 939, 933, 927, 920, 913, 906, 898, 891, 882, 874,
   866, 857, 848, 838, 829, 819, 809, 798, 788, 777, 766, 754, 743, 731, 719, 707, 694, 681, 669, 656, 642, 629, 615, 601, 587, 573, 559, 544, 529, 515,
   500, 484, 469, 453, 438, 422, 406, 390, 374, 358, 342, 325, 309, 292, 275, 258, 241, 224, 207, 190, 173, 156, 139, 121, 104,  87,  69,  52,  34,  17
  ];

  function _sin(deg) {
   deg = deg%360;
   if(deg < 180)
    return SINDAT[deg];
   else
    return -SINDAT[deg-180];
  }

  function _cos(deg) {
   deg = (deg+90)%360;
   if(deg < 180)
    return SINDAT[deg];
   else
    return -SINDAT[deg-180];
  }

  //触手用の変数
  var tenX = [  0,  0,  0,  0,  0,  0,  0];//座標
  var tenY = [  0,  0,  0,  0,  0,  0,  0];//
  var tenA = [180,190,200,210,220,230,240];//角度
  var tenL = [ 90, 80, 70, 60, 50, 40, 30];//曲がる角度の限界

  //触手の座標を求める
  function calcTenXY(n) {
   tenX[n] = 320+parseInt(36*(6-n)*_cos(tenA[n])/1000);
   tenY[n] = 240+parseInt(36*(6-n)*_sin(tenA[n])/1000);
  }
  for(var i=0; i<7; i++) calcTenXY(i);//初期座標

  //線を描く関数
  function line(x1, y1, x2, y2, wi, col) {
   ctx.lineCap = "round";
   ctx.lineWidth = wi;
   ctx.strokeStyle = col;
   ctx.beginPath();
   ctx.moveTo(x1, y1);
   ctx.lineTo(x2, y2);
   ctx.stroke();
  }

  //円を描く関数
  function circle(x, y, r, col) {
   ctx.fillStyle = col;
   ctx.beginPath();
   ctx.arc(x, y, r, 0, Math.PI*2);
   ctx.fill();
  }

  //メイン処理
  function mainProc() {

   ctx.fillStyle = "black";
   ctx.fillRect(0, 0, 640, 320);

   //矢印(タップ位置)
   line(tapX-30,tapY,tapX+30,tapY,12,"#0cf");
   if(tapX < 320) {//左向き
    line(tapX-30,tapY,tapX,tapY-20,12,"#0cf");
    line(tapX-30,tapY,tapX,tapY+20,12,"#0cf");
   } else {//右向き
    line(tapX+30,tapY,tapX,tapY-20,12,"#0cf");
    line(tapX+30,tapY,tapX,tapY+20,12,"#0cf");
   }

   //触手の先端が矢印を追う
   if(tapX < tenX[0]) tenA[0]-=3; else tenA[0]+=3;
   if(tenA[0]<180)tenA[0]=180;//┬これ以上は曲がらない
   if(tenA[0]>360)tenA[0]=360;//┘

   //触手のパーツの位置計算&描画
   circle(320, 320, 64, "#f08");
   for(var i=0; i<7; i++) {
    if(i > 0) {//先端から下のパーツの角度を計算
     tenA[i] = parseInt((tenA[i]+tenA[i-1])/2);
     if(tenA[i]<270-tenL[i]) tenA[i]=270-tenL[i];//┬これ以上は曲がらない
     if(tenA[i]>270+tenL[i]) tenA[i]=270+tenL[i];//┘
    }
    calcTenXY(i);
    if(i==0) circle(tenX[i], tenY[i], 24, "#eaf");//先端
    circle(tenX[i], tenY[i], 18, "#80f");
   }
  }

  setInterval(mainProc, 1000/20);//リアルタイム処理
  </script>
 </body>
</html>

←動作確認に戻る