Формула для расстояния между двумя точками (javascript):
var xDiff = ( point1x - point2x ),
yDiff = ( point1y - point2y ),
distance = Math.sqrt( ( xDiff * xDiff ) + ( yDiff * yDiff ) );
Обведите «предложенную новую точку», начиная с единицы x-1, y-1 to x+1, y+1
.В каждой точке проверяйте, чтобы убедиться, что это не запрещенная точка, не точка, из которой вы только что пришли, и не за пределами карты.Если он соответствует всем этим критериям, используйте приведенную выше формулу для измерения расстояния и добавьте его в массив.В конце цикла «1-point out» проверьте, есть ли какие-либо расстояния в этом массиве.Если так, возьмите самый маленький и все готово.Если их нет, перейдите на x-2, y-2 to x+2, y+2
(2 балла).
Это будет очень быстро для небольшой области, на которую вы ссылаетесь.
Демонстрация: http://jsfiddle.net/ThinkingStiff/V7Bqm/
var X = 0,
Y = 1,
currentPoint = [5,5],
proposedPoint = [5,6],
forbiddenPoints = [[5,6],[6,6],[4,7],[5,7],[6,7],[4,8],[5,8]],
map = { left:1, top:1, right:10, bottom:10 };
function closestSafePoint( point ) {
var x = point[X], y = point[Y], safePoints = [];
for( var left = x - 1, top = y - 1, right = x + 1, bottom = y + 1;
left <= map.left || top <= map.top || right <= map.right || bottom <= map.bottom;
left--, top--, right++, bottom++) {
checkHorizontalPoints( safePoints, point, left, right, top );
checkHorizontalPoints( safePoints, point, left, right, bottom );
checkVerticalPoints( safePoints, point, top + 1, bottom - 1, left );
checkVerticalPoints( safePoints, point, top + 1, bottom - 1, right );
safePoints.sort( function( a, b ){ return a[1] - b[1] } );
return safePoints.length ? safePoints[0] : point;
};
};
function checkHorizontalPoints( points, fromPoint, startX, endX, y ) {
for( var x = startX; x <= endX ; x++ ) {
var toPoint = [x, y];
if( !isForbidden( toPoint ) && !isCurrent( toPoint) && onMap( toPoint ) ) {
points.push( [toPoint, distance( fromPoint, toPoint )] );
};
};
};
function checkVerticalPoints( points, fromPoint, startY, endY, x ) {
for( var y = startY; y <= endY ; y++ ) {
var toPoint = [x, y];
if( !isForbidden( toPoint ) && !isCurrent( toPoint) && onMap( toPoint ) ) {
points.push( [toPoint, distance( fromPoint, toPoint )] );
};
};
};
function isForbidden( point ) {
for( var index = 0; index < forbiddenPoints.length; index++ ) {
if( forbiddenPoints[index].toString() == point.toString() ) return true;
};
};
function isCurrent( point ) {
return currentPoint.toString() == point.toString() ? true : false;
};
function onMap( point ) {
var x = point[X], y = point[Y];
return x >= map.left && y >= map.top && x <= map.right && y <= map.bottom;
};
function distance( pointA, pointB ) {
var xDiff = ( pointA[X] - pointB[X] ),
yDiff = ( pointA[Y] - pointB[Y] );
return Math.sqrt( ( xDiff * xDiff ) + ( yDiff * yDiff ) );
};
console.log(
'current: ' + currentPoint + ', '
+ 'proposed: ' + proposedPoint + ', '
+ 'closest: ' + closestSafePoint( proposedPoint )[0]
);
Одна оптимизация, которую вы могли бы сделать, если выВы точно уверены, что большинство ваших безопасных мест будут на расстоянии одной или двух точек - это пробиться, как только вы достигнете точки, расстояние которой совпадает с уровнем, на котором вы находитесь.Так что, если вы находитесь на первом цикле, и вы получаете точку, которая является расстоянием = 1, остановитесь, поскольку вы никогда не станете ближе, чем это.
ОБНОВЛЕНИЕ: я заметил, что вы добавили "ту же траекторию" к вашемувопрос.Но в одном из комментариев вы также говорите, что он не может перепрыгнуть через запрещенную область.Эти утверждения, кажется, противоречат друг другу.
Та же траектория немного сложнее и требует некоторого триггера.Посмотрите мою демонстрацию круговых дел в http://jsfiddle.net/ThinkingStiff/uLu7v/. На полпути вниз есть функция «точка на луче»:
$this.siblings( ".circle" ).each( function()
Это вычисляет расстояние для перемещения окружающих кругов на луч отвыбранный круг.Это может быть использовано для расчета точки на вашей траектории.Но я думаю, что моя первоначальная функция - это то, что вы ищете, и вы не имели в виду ту же траекторию.