Я написал код, чтобы выяснить, как вычислить разницу в углах для двумерного игрового AI. Я добавил изображение (пример проблемы), функция, которую я пишу, берет входной сигнал с углами А и В и должна возвращать направление! возвращаемое значение должно быть от -pi до + pi или в градусах от -180 до 180.Функция JS для вычисления разницы в углах 2D-игра
код работает, в основном: | но в некоторых случаях он терпит неудачу. код можно полностью скопировать в файл .html и запустить для тестирования.
код:
<!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>
это для игр, и это требует поплавка значение высокой точности –
, если 'targetA' и' sourceA' являются поплавками, тогда вы должны быть хорошими. –
Я только что попытался, проблема все еще существует, постарайтесь привести строку примерно к 10 часам, затем переместите мышь с 7 до 5 oclock –