#javascript #html5-canvas #collision-detection #game-physics
#javascript #html5-canvas #обнаружение столкновений #игра-физика
Вопрос:
Я работаю над аркадной игрой, похожей на астероиды, используя canvas HTML и JavaScript. В настоящее время у меня есть куча случайно сгенерированных фигур («астероидов») со случайным количеством точек (3, 4 или 5) и случайным размером в случайных местах.
Я пытаюсь настроить систему обнаружения столкновений с этими полигонами. Я использовал SAT.js (https://github.com/jriecken/sat-js ) для этого. Тем не менее, я не могу точно нарисовать невидимые полигоны столкновений вокруг реальных полигонов, отображаемых на экране.
Вот что у меня есть в моем классе asteroid, где я визуализирую астероиды. В настоящее время я тестирую только с 3 точками в фигурах (треугольниках). Я отключил 4- и 5-точечные астероиды.
ctx.moveTo(0, 0);
ctx.lineTo(10 size, 20);
ctx.lineTo(10 size, 20 size);
ctx.closePath();
Вот соответствующий SAT.js код.
/**
* @function createCollisionPolygon
* Traces the outline of the asteroid to allow it to detect collisions
* based on the number of points the shape has (3, 4, or 5)
* @param {asteroid} The asteroid to make collision detectable
* @return The traced polygon
*/
function createCollisionPolygon(asteroid)
{
var V = SAT.Vector;
var P = SAT.Polygon;
var polygon;
switch(asteroid.randomNumPoints)
{
// 3 point polygon
case 3:
polygon = new P(new V(asteroid.position.x, asteroid.position.y), [
new V(10 asteroid.size, 0),
new V(asteroid.position.x,asteroid.position.y),
new V(10 asteroid.size, 20 asteroid.size)
]);
break;
}
return polygon;
}
/**
* @function checkCollision
* Checks for collisions between any two asteroids
* @param {polygon1} The first asteroid
* @param {polygon2} The next asteroid
* @return True if there was a collision, false otherwise
*/
function checkCollision(polygon1, polygon2)
{
var response = new SAT.Response();
var collided = SAT.testPolygonPolygon(polygon1, polygon2, response);
return collided;
}
Который позже вызывается здесь:
for(var i = 0; i < asteroids.length - 1; i )
{
var asteroid1 = asteroids[i];
var asteroid2 = asteroids[i 1];
// Trace an invisible outline around each asteroid
var polygon1 = createCollisionPolygon(asteroid1);
var polygon2 = createCollisionPolygon(asteroid2);
// console.log("Polygon 1: " console.log(polygon1.points[0]
// console.log(polygon1.points[1]) console.log(polygon1.points[2])));
// console.log("Polygon 2: " console.log(polygon2.points[0]
// console.log(polygon2.points[1]) console.log(polygon2.points[2])));
// Check if there is a collision
if(checkCollision(polygon1, polygon2))
{
asteroid1.color = 'red';
asteroid2.color = 'red';
console.log("Collision detected.");
}
}
Буду признателен за любую помощь — я пытался разобраться в этом в течение нескольких дней. Спасибо!
Ответ №1:
Поскольку нет свойств клипа canvas для получения области пересечения. Я бы предложил следующее решение. Используйте одну из библиотек js для вычисления пересечения полигонов, например, Greiner-Hormann. Используя эту библиотеку, вы можете легко пересекать фигуры и обнаруживать столкновения (если результат пересечения не равен нулю, то столкновение существует).
пример:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
function drawTriangle(trianglePoints, color)
{
ctx.beginPath();
ctx.moveTo(trianglePoints[0].x, trianglePoints[0].y);
ctx.lineTo(trianglePoints[1].x, trianglePoints[1].y);
ctx.lineTo(trianglePoints[2].x, trianglePoints[2].y);
ctx.closePath();
ctx.fillStyle = color;
ctx.fill();
}
function getTriangle(size, startPointX, startPointY)
{
return [{x:startPointX,y:startPointY},
{x:startPointX size,y:startPointY},
{x:startPointX,y:startPointY size},
{x:startPointX,y:startPointY}];
}
//sample triangles
var triangle1 = getTriangle(50,100,100);
var triangle2 = getTriangle(50,100,90);
var triangle3 = getTriangle(50,200,100);
var triangle4 = getTriangle(50,280,90);
//draw all triangles
drawTriangle(triangle1,'#d3d3d3');
drawTriangle(triangle2,'#e3e3e3');
drawTriangle(triangle3,'red');
drawTriangle(triangle4,'blue');
//intersaction results
console.log("intersection exists");
console.log(greinerHormann.intersection( triangle1 , triangle2));
console.log("intersection not exists result of intersaction - null");
console.log(greinerHormann.intersection( triangle3 , triangle2));
<script src="https://cdn.rawgit.com/w8r/GreinerHormann/master/dist/greiner-hormann.min.js"></script>
<canvas id="myCanvas" width="578" height="200"></canvas>
Комментарии:
1. если мы используем библиотеки, почему бы не использовать полную физическую среду blwon?
2. cdn.rawgit.com/w8r/GreinerHormann/master/dist/… является 404 🙁