2017-02-21 30 views
0

Я написал код, чтобы выяснить, как вычислить разницу в углах для двумерного игрового AI. Я добавил изображение (пример проблемы), функция, которую я пишу, берет входной сигнал с углами А и В и должна возвращать направление! возвращаемое значение должно быть от -pi до + pi или в градусах от -180 до 180.Функция JS для вычисления разницы в углах 2D-игра

код работает, в основном: | но в некоторых случаях он терпит неудачу. код можно полностью скопировать в файл .html и запустить для тестирования.

example problem pic

код:

<!DOCTYPE html> 
<html style="width:100%;"> 
    <head> 
     <meta charset="utf-8"> 
     <title>Angle</title> 
     <style type="text/css"> 
      body { 
       height: 600px; 
       background-color: #EEEEEE; 
      } 
      #main { 
       text-align: center; 
       /*border: 1px solid #000000;*/ 
      } 
     </style> 
    </head> 
    <body> 

     <center> 
      <h3>Canvas</h3> 
      <canvas id="main" width="640" height="480"> 
       Your browser does not support the HTML5 canvas tag. 
      </canvas> 
     </center> 

     <script type="text/javascript"> 

window.onload=function(){ 
    "use strict"; 


    var canvas = document.getElementById('main'); 
    var ctx = canvas.getContext('2d'); 
    var font_size = 18; 
    ctx.font = font_size + 'px Courier New'; // Courier New/Lucida Console 
    var clearCanvas = function(c){ 
     if (c){ 
      c.updateFill(); 
      ctx.fillRect(0, 0, canvas.width, canvas.height); 
     }else{ 
      ctx.clearRect(0, 0, canvas.width, canvas.height); 
     } 
    }; 


    // math extras 
    Math.M_PI_DB_180 = 0.01745329251994; 
    Math.M_180_DB_PI = 57.2957795130823; 
    Math.M_2PI = 6.28318530717959; 
    Math.M_PI = 3.14159265358979; 
    Math.M_PI_DB_2 = 1.57079632679489; 

    Math.DEG2RAD = function(d){ return (d * Math.M_PI_DB_180); }; 
    Math.RAD2DEG = function(r){ return (r * Math.M_180_DB_PI); }; 


    Math._fmod_precesion = 1000000; 
    Math.fmod = function(a, b){ 
     return (Math.round(a * Math._fmod_precesion) % Math.round(b * Math._fmod_precesion))/Math._fmod_precesion; 
    }; 

    Math.roundp = function(value, precision){ 
     var p = Math.pow(10, precision); 
     return Math.round(value * p)/p; 
    }; 


    Math.wrapDegree = function(value){ 
     if (value > 360) value = Math.fmod(value, 360); 
     if (value < -360) value = Math.fmod(value, 360); 
     if (value < 0) value += 360; 
     return value; 
    }; 
    Math.wrapRadian = function(value){ 
     if (value > Math.M_2PI) value = Math.fmod(value, Math.M_2PI); 
     if (value < -Math.M_2PI) value = Math.fmod(value, Math.M_2PI); 
     if (value < 0) value += Math.M_2PI; 
     return value; 
    }; 

    // gives -179.9 to 179.9 
    Math.angleDifference = function(a1, a2){ 
     var diff = a1 - a2; 
     if (diff > Math.M_PI) diff = -(Math.M_2PI - diff); 
     if (diff < -Math.M_PI) diff = (Math.M_2PI + diff); 
     if (diff > -0.01 && diff < 0.01) diff = 0; // fix 
     return diff; 
    }; 

    Math.angleWithinFOV = function(angle, fov){ 
     var half = fov/2; 
     return angle < half && angle > -half; 
    }; 



    // vector 2D class 
    var vec2 = function(x, y){ 
     this.x = function(){ return this._x; }; 
     this.y = function(){ return this._y; }; 
     this.set = function(x, y){ 
      this._x = typeof x == 'number' ? x : 0; 
      this._y = typeof y == 'number' ? y : 0; 
     }; 
     this.set(x, y); 

     // extras 

     this.add = function(v){ this._x += v.x(); this._y += v.y(); }; 
     this.sub = function(v){ this._x -= v.x(); this._y -= v.y(); }; 
     this.mul = function(v){ this._x *= v.x(); this._y *= v.y(); }; 

     this.lengthMath = function(){ 
      return Math.sqrt(Math.pow(this._x, 2) + Math.pow(this._y, 2)); 
     }; 

     this.normalizedCopy = function(){ 
      var len = this.lengthMath(); 
      return len != 0 ? new vec2(this._x/len, this._y/len) : null; 
     }; 


     this.clone = function(){ return new vec2(this._x, this._y); }; 

     this.next = function(angle, distance){ 
      return new vec2(this._x + (distance * Math.sin(angle)), this._y + (distance * Math.cos(angle))); 
     }; 


     this.slopeAngle = function(v){ 
      return Math.wrapRadian(Math.atan2(this._x - v.x(), this._y - v.y()) + Math.M_PI); 
     }; 

    }; 

    // color class (updateFill, updateStroke) (colorFill, colorStroke) 
    var ccolor = function(c){ 
     this._color = c||'#000000'; 
     this.updateFill = function(draw){ 
      ctx.fillStyle = this._color; 
      if(draw)ctx.fill(); 
     }; 
     this.updateStroke = function(draw){ 
      ctx.strokeStyle = this._color; 
      if(draw)ctx.stroke(); 
     }; 
    }; 


    // draw fuunctions 
    var _text = function(v, t, c){ 
     c.updateFill(); 
     ctx.fillText(t, v.x(), v.y() + font_size - (font_size * 0.4)); 
    }; 
    var _line = function(v1, v2, c){ 
     ctx.moveTo(v1.x(), v1.y()); 
     ctx.lineTo(v2.x(), v2.y()); 
     c.updateStroke(true); 
    }; 
    var _circle = function(v, radius, c, shouldFill){ 
     ctx.beginPath(); 
     ctx.arc(v.x(), v.y(), radius, 0, Math.M_2PI); 
     if (shouldFill) 
      c.updateFill(true); 
     else 
      c.updateStroke(true); 
    }; 

    var _viewcone = function(v, radius, c, r1, r2){ 
     ctx.beginPath(); 
     ctx.arc(v.x(), v.y(), radius, r1, r2); 
     c.updateStroke(true); 
    }; 


    // mouse move store 
    var _mousePos = new vec2(); 
    canvas.addEventListener('mousemove', function(e){ 
     var rect = canvas.getBoundingClientRect(); 
     _mousePos.set(e.clientX - rect.left, e.clientY - rect.top); 
    }); 



    // colors 
    var _red = new ccolor('#FF0000'); 
    var _green = new ccolor('#00FF00'); 
    var _blue = new ccolor('#0000FF'); 
    var _black = new ccolor('#000000'); 
    var _white = new ccolor('#FFFFFF'); 

    // game vars 
    var LOOP_INT = 1000/60; // 16.6666 
    var AI_BODY_RADIUS = 50; 
    var TEST_SPEED = LOOP_INT/800; 
    var timer_id = 0; 

    var text_position = new vec2(5, 5); 

    var AI_VIEW_CONE = Math.DEG2RAD(120); 

    var ai_position = new vec2(300, 260); 

    var ai_angle = Math.DEG2RAD(225); 

    //var test_angle = 0; // rad 

    // main loop 
    var MAIN_LOOP = function(){ 

     clearCanvas(_white); 


     // test 
     //test_angle += LOOP_INT/300; 
     //test_angle = Math.wrapRadian(test_angle + (LOOP_INT/300)); 
     //_text(text_position, 'ANGLE: ' + (Math.round(test_angle * 100)/100), _blue); 

     var target_angle = ai_position.slopeAngle(_mousePos); 


     var angle_diff = Math.angleDifference(target_angle, ai_angle); 

     // within FOV 
     //if (Math.angleWithinFOV(angle_diff, AI_VIEW_CONE)){ 
      if (angle_diff > 0) ai_angle += TEST_SPEED; 
      if (angle_diff < 0) ai_angle -= TEST_SPEED; 
     //} 



     var txt = 'ANGLE DIFF: ' + Math.roundp(Math.RAD2DEG(angle_diff), 2); 
     _text(text_position, txt, _blue); 



     // AI 
     _line(ai_position, ai_position.next(ai_angle, AI_BODY_RADIUS), _red); 


     // cone 
     var aa = Math.M_PI_DB_2 - ai_angle; 
     var vc = AI_VIEW_CONE/2; 
     _viewcone(ai_position, AI_BODY_RADIUS, _red, aa - vc, aa + vc); 
     _line(ai_position, ai_position.next(ai_angle - vc, AI_BODY_RADIUS), _red); 
     _line(ai_position, ai_position.next(ai_angle + vc, AI_BODY_RADIUS), _red); 



     // target angle 
     _line(ai_position, ai_position.next(target_angle, AI_BODY_RADIUS), _blue); 


     // cursor 
     _circle(_mousePos, 5, _green, true); 

     //requestAnimationFrame(MAIN_LOOP); 
    }; 

    // srart up 
    timer_id = setInterval(MAIN_LOOP, LOOP_INT); 


}; 

     </script> 

    </body> 
</html> 

ответ

0

Чтобы вычислить разницу между 2 углами с использованием градусов, вы можете использовать это:

var diffA = targetA - sourceA; 
diffA = (a + 180) % 360 - 180; 
+0

это для игр, и это требует поплавка значение высокой точности –

+0

, если 'targetA' и' sourceA' являются поплавками, тогда вы должны быть хорошими. –

+0

Я только что попытался, проблема все еще существует, постарайтесь привести строку примерно к 10 часам, затем переместите мышь с 7 до 5 oclock –