que hace ejemplo javascript collision-detection

hace - Javascript: detección de colisión



javascript>:< void 0 (10)

¿Podría alguien ayudarme a entender cómo funciona la detección de colisiones en JS? No puedo usar jQuery o gameQuery, ya estoy usando un prototipo, entonces, estoy buscando algo muy simple. No solicitando una solución completa, solo apúntame en la dirección correcta.

Digamos que hay:

<div id="ball"></div> and <div id="someobject0"></div>

Ahora la pelota se está moviendo (en cualquier dirección). "Someobject" (0-X) ya está predefinido y hay 20-60 de ellos colocados al azar de esta manera:

#someobject {position: absolute; top: RNDpx; left: RNDpx;}

Puedo crear una matriz con posiciones "someobject (X)" y probar la colisión mientras la "bola" se mueve ... Algo como:

for(var c=0; c<objposArray.length; c++){ ........ and code to check ball''s current position vs all objects one by one.... }

Pero creo que esta sería una solución "novato" y parece bastante lenta. ¿Hay algo mejor?


Aquí hay una rutina rectángula muy simple. Espera que tanto a como b sean objetos con propiedades de x , y , width y height :

function isCollide(a, b) { return !( ((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width)) ); }

Para ver esta función en acción, aquí hay un codepen gentilmente creado por @MixerOID .


Esta es una forma simple que es ineficiente, pero es bastante razonable cuando no necesitas nada demasiado complejo o no tienes muchos objetos.

De lo contrario, hay muchos algoritmos diferentes, pero la mayoría de ellos son bastante complejos de implementar.

Por ejemplo, puede usar un enfoque de divide e impera en el que agrupa los objetos jerárquicamente de acuerdo con su distancia y le da a cada grupo un cuadro delimitador que contiene todos los elementos del grupo. Luego, puede verificar qué clústeres colisionan y evitar el control de pares de objeto que pertenece a los clústeres que no están colisionando / superpuestos.

De lo contrario, puede encontrar un algoritmo de partición de espacio genérico para dividir de manera similar los objetos para evitar verificaciones inútiles. Este tipo de algoritmos divide la detección de colisión en dos fases: una gruesa en la que se ve qué objetos pueden colisionar y otra en la que se comprueban efectivamente objetos individuales. Por ejemplo, puedes usar una wikipedia QuadTree para entrenar una solución fácil.

Eche un vistazo a la page wikipedia, puede darle algunas pistas.


Esta es una solución liviana que he encontrado -

function E() { // check collision S = X - x; D = Y - y; F = w + W; return (S * S + D * D <= F * F) }

Las variables grandes y pequeñas son de 2 objetos, (x coord, y coord, y ancho w)

De here


La respuesta de "bcm''s", que tiene 0 votos en este momento, es en realidad una gran respuesta, menos apreciada. Utiliza el buen viejo Pitágoras para detectar cuándo los objetos están más cerca que sus círculos delimitados combinados. La detección de colisión simple a menudo utiliza la detección de colisión rectangular, que está bien si tus sprites tienden a ser, bueno, rectangulares. Si son circulares (o menos rectangulares), como una pelota, un asteroide o cualquier otra forma donde las esquinas extremas usualmente son transparentes, puede encontrar que esta rutina eficiente es la más precisa.

Pero para mayor claridad, aquí hay una versión más completa del código:

function doCollide(x1, y1, w1, x2, y2, w2) { var xd = x1 - x2; var yd = y1 - y2; var wt = w2 + w1; return (xd * xd + yd * yd <= wt * wt); }

Donde los parámetros a pasar son los valores x, y y ancho de dos objetos sprites diferentes


Lo primero que debe tener es la función real que detectará si tiene una colisión entre la pelota y el objeto.

En aras del rendimiento, será genial implementar alguna técnica de detección de colisiones brutas, por ejemplo, rectángulos de delimitación , y una más precisa si es necesario en caso de que se haya detectado una colisión, de modo que su función se ejecutará un poco más rápido pero utilizando exactamente el mismo bucle

Otra opción que puede ayudar a aumentar el rendimiento es hacer un preprocesamiento con los objetos que tiene. Por ejemplo, puede dividir toda el área en celdas como una tabla genérica y almacenar el objeto apropiado que se encuentra dentro de las celdas particulares. Por lo tanto, para detectar la colisión, está detectando las celdas ocupadas por la bola, obtenga los objetos de esas celdas y use su función de detección de colisiones.

Para acelerarlo aún más puedes implementar 2d-tree , quadtree o R-tree .


Mozilla tiene un buen artículo sobre esto, con el código que se muestra a continuación

https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

Colisión de rectángulo

if (rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.height + rect1.y > rect2.y) { // collision detected! }

Colisión de círculo

if (distance < circle1.radius + circle2.radius) { // collision detected! }


Puedes probar jquery-collision . Divulgación completa: acabo de escribir esto y lo lancé. No encontré una solución, así que lo escribí yo mismo.

Te permite hacer:

var hit_list = $("#ball").collision("#someobject0");

que devolverá todos los "# someobject0" ''s que se superponen con "#ball".


Una versión sin jQuery, con HTMLElements como entradas

Este es un mejor enfoque que verifica la posición real de los elementos tal como se muestran en la ventana gráfica, incluso si son absolutos, relativos o han sido manipulados mediante transformaciones:

function isCollide(a, b) { var aRect = a.getBoundingClientRect(); var bRect = b.getBoundingClientRect(); return !( ((aRect.top + aRect.height) < (bRect.top)) || (aRect.top > (bRect.top + bRect.height)) || ((aRect.left + aRect.width) < bRect.left) || (aRect.left > (bRect.left + bRect.width)) ); }


hittest.js; detectar dos colisiones transparentes de imagen png (píxel). Enlace de demostración y descarga

Código HTML;

<img id="png-object-1" src="images/object1.png" /> <img id="png-object-2" src="images/object2.png" />

Función de inicio;

var pngObject1Element = document.getElementById( "png-object-1" ); var pngObject2Element = document.getElementById( "png-object-2" ); var object1HitTest = new HitTest( pngObject1Element );

Uso básico;

if( object1HitTest.toObject( pngObject2Element ) ) { //Collision detected }


//Off the cuff, Prototype style. //Note, this is not optimal; there should be some basic partitioning and caching going on. (function () { var elements = []; Element.register = function (element) { for (var i=0; i<elements.length; i++) { if (elements[i]==element) break; } elements.push(element); if (arguments.length>1) for (var i=0; i<arguments.length; i++) Element.register(arguments[i]); }; Element.collide = function () { for (var outer=0; outer < elements.length; outer++) { var e1 = Object.extend( $(elements[outer]).positionedOffset(), $(elements[outer]).getDimensions() ); for (var inner=outer; inner<elements.length; innter++) { var e2 = Object.extend( $(elements[inner]).positionedOffset(), $(elements[inner]).getDimensions() ); if ( (e1.left+e1.width)>=e2.left && e1.left<=(e2.left+e2.width) && (e1.top+e1.height)>=e2.top && e1.top<=(e2.top+e2.height) ) { $(elements[inner]).fire('':collision'', {element: $(elements[outer])}); $(elements[outer]).fire('':collision'', {element: $(elements[inner])}); } } } }; })(); //Usage: Element.register(myElementA); Element.register(myElementB); $(myElementA).observe('':collision'', function (ev) { console.log(''Damn, ''+ev.memo.element+'', that hurt!''); }); //detect collisions every 100ms setInterval(Element.collide, 100);