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.
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>
ceci est pour le jeu et il faut valeur flottante de haute précision –
si 'targetA' et' sourceA' sont des flottants, alors vous devriez être bon. –
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 –