Это для игры, которую я рассматриваю.
У меня есть точка, которая отмечается как движущаяся внутри (2D) круга из произвольной точки, в произвольном направлении и в определенное время. Точка отскочит от внутренней стены круга, когда она пересекается.
В этом примере предположим, что круг имеет диаметр 100 километров с центром в точке (0,0), а 10 часов назад точка находилась в точке (20,30) с курсом 40 градусов со скоростью 50 км / ч.
Как лучше всего определить, где в данный момент находится эта точка и в каком направлении она движется?
Я буду реализовывать это в PHP с данными о точках и окружностях, хранящихся в MySQL. Поскольку это веб-страница, не будет постоянно запущенного хост-процесса, который будет обновлять данные, и данные должны будут обновляться при загрузке страницы.
Я, конечно, не ищу, чтобы кто-нибудь написал код для меня, но я надеюсь, что кто-то может помочь мне с несколько более эффективным способом приблизиться к этому.
Ваш точечный объект будет путешествовать по тому, что называется аккорды в геометрии.
Когда объект достигает границы круга, он будет отражаться от касательной к окружности в этой точке и идти вдоль следующего аккорда с такой же длиной. Следующее попадание будет происходить под тем же углом (с касательной в этой точке попадания), что и предыдущее попадание, и поэтому оно будет продолжено. На постоянной скорости время между попаданиями будет постоянным.
Учитывая время начала и текущее время, можно рассчитать количество аккордов, которые были завершены, и сколько текущего аккорда было завершено. Вычислить позицию из этого легко, если вы знаете предыдущую и следующую позиции удара. Поскольку эти позиции попадания находятся на равных расстояниях вдоль границы круга, это вопрос преобразования полярных координат (угол и расстояние в 1 радиан) в декартовы координаты.
Я продемонстрирую это с помощью кода JavaScript. Это не будет большим усилием, чтобы обернуть это в PHP:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var radius = canvas.height / 2 - 5;
var pixel = 1/radius;
// transform the canvas so that 0,0 is in the center of the canvas,
// and a unit circle would cover most of the height of the canvas:
context.setTransform(radius, 0, 0, radius, radius+2, radius+2);
// draw unit circle
context.beginPath();
context.arc(0, 0, 1, 0, 2 * Math.PI, false);
context.lineWidth = pixel;
context.strokeStyle = 'black';
context.stroke();
function drawPoint(point) {
// use a different color every 30 seconds:
context.fillStyle = Date.now() % 60000 > 30000 ? 'red' : 'blue';
context.fillRect(point.x-2*pixel, point.y-2*pixel, 4*pixel, 4*pixel);
}
function polarToCartesian(rad, dist) {
return {
x: Math.cos(rad) * dist,
y: Math.sin(rad) * dist
}
}
function pointBetween(a, b, fractionTravelled) {
return {
x: a.x + (b.x-a.x)*fractionTravelled,
y: a.y + (b.y-a.y)*fractionTravelled
}
}
// 4 parameters are needed:
var startRadians = 0; // distance along circle boundary from (0,1)
var hitAngle = Math.PI/2.931; // PI/2 would be head-on impact along diagonal
var speed = 0.4; // radians per second
var startTime = Date.now()/1000; // seconds
//
// Calculate some derived values which remain constant:
// - theta as used on https://en.wikipedia.org/wiki/Chord_%28geometry%29
// - chordSize formula comes from that wiki article.
var theta = 2 * hitAngle;
var chordSize = 2 * Math.sin(theta/2); // in radians
function drawCurrentPosition() {
// Note that this calculation does not look at the previous result,
// but uses the original parameters and time passed to calculate
// the objects current position.
var elapsedTime = Date.now()/1000 - startTime; // in secs
var distanceTravelled = speed * elapsedTime; // in radians
var chordsTravelled = distanceTravelled / chordSize; // in number of chords
var chordsTravelledComplete = Math.floor(chordsTravelled);
var fractionOnChord = chordsTravelled - chordsTravelledComplete; // 0<=f<1
var lastHitRadians = startRadians + chordsTravelledComplete * theta; // rad
var nextHitRadians = lastHitRadians + theta;
var lastHitPos = polarToCartesian(lastHitRadians, 1); // (x,y)
var nextHitPos = polarToCartesian(nextHitRadians, 1);
var currentPos = pointBetween(lastHitPos, nextHitPos, fractionOnChord);
drawPoint(currentPos);
}
// Demo: keep drawing the object's position every 0.1 second:
setInterval(drawCurrentPosition, 100);
<canvas id="myCanvas" width="200" height="200"></canvas>
Других решений пока нет …