我写了一些代码,只是为了弄清楚如何计算2D游戏AI的角度差。我添加了一张图片(示例问题),我正在编写的函数接受角度A和B的输入,并且应该返回一个方向!返回值应该在-pi到+pi之间,或者在-180到180度之间。
代码的工作方式主要是:|,但在某些情况下它会失败。可以将代码完全复制到.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>发布于 2017-02-22 05:34:37
要使用度数计算两个角度之间的差,可以使用以下命令:
var diffA = targetA - sourceA;
diffA = (a + 180) % 360 - 180;https://stackoverflow.com/questions/42378378
复制相似问题