2017-02-21 3 views
0

J'ai écrit du code juste pour comprendre comment calculer la différence d'angle pour une IA en 2D. J'ai ajouté une image (exemple de problème), la fonction que j'écris prend l'entrée de l'angle A et B, et devrait retourner une direction! La valeur de retour doit être comprise entre -pi et + pi, ou en degrés -180 à 180.Fonction JS pour calculer la différence d'angle Jeu 2D

le code fonctionne principalement par: | mais à certains points, il échoue. code peut être copié entièrement dans un fichier .html et exécuté pour tester.

example problem pic

Code

:

<!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> 

Répondre

0

Pour calculer la différence entre les 2 angles en utilisant degrés, vous pouvez utiliser ceci:

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

ceci est pour le jeu et il faut valeur flottante de haute précision –

+0

si 'targetA' et' sourceA' sont des flottants, alors vous devriez être bon. –

+0

Je viens d'essayer, le problème existe toujours, essayez d'amener la ligne à environ 10 heures, puis déplacez la souris de 7 à 5 heures –