--- title: 2D collision detection slug: Games/Techniques/2D_collision_detection tags: - 2D - Deteccion de colision - JavaScript - juegos translation_of: Games/Techniques/2D_collision_detection ---
{{IncludeSubnav("/en-US/docs/Games")}}
Algoritmos para detectar la colision en juegos de 2D depende del tipo de formas con las que queramos colisionar (Ej.: Rectangulo, Circulo). Generalmente tendras una forma simple que cubre la "hitbox" (caja de colision), por lo tanto la colision no sera perfecta pixel a pixel, pero ira bien, en rendimiento. Este articulo cubre la mayoria de las tecnicas utilizadas para la colision para juegos en 2D.
Una de las formas mas sencillas es entre dos rectangulos que esten alineados con las cordenas, es decir, sin rotacion. El algoritmo funciona de manera que detecta si hay un agujero en alguno de los 4 lados del rectangulo. Si en un lado no hay un agujero, significa de que hay una colision.
var rect1 = {x: 5, y: 5, width: 50, height: 50} var rect2 = {x: 20, y: 10, width: 10, height: 10} 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) { // ¡colision detectada! } // reemplazando los valores => if (5 < 30 && 55 > 20 && 5 < 20 && 55 > 10) { // ¡colision detecteda! }
<div id="cr-stage"></div> <p>Mueve los rectangulos. Azul = no colision. Verde = colision</p> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crafty/0.5.4/crafty-min.js"></script>
Crafty.init(200, 200); var dim1 = {x: 5, y: 5, w: 50, h: 50} var dim2 = {x: 20, y: 10, w: 60, h: 40} var rect1 = Crafty.e("2D, Canvas, Color").attr(dim1).color("red"); var rect2 = Crafty.e("2D, Canvas, Color, Keyboard, Fourway").fourway(2).attr(dim2).color("blue"); rect2.bind("EnterFrame", function () { if (rect1.x < rect2.x + rect2.w && rect1.x + rect1.w > rect2.x && rect1.y < rect2.y + rect2.h && rect1.h + rect1.y > rect2.y) { // collision detected! this.color("green"); } else { // no collision this.color("blue"); } });
{{ EmbedLiveSample('Rect_code', '700', '300', '', 'Games/Techniques/2D_collision_detection') }}
Otra colision simple es entre dos circulos. Funciona con los centros de los dos circulos y calculando la distancia entre los dos.
<div id="cr-stage"></div> <p>Mueve el circulo con las flechas. Verde = colision. Azul = no colision</p> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crafty/0.5.4/crafty-min.js"></script>
#cr-stage { position: static !important; height: 200px !important; }
Crafty.init(200, 200); var dim1 = {x: 5, y: 5} var dim2 = {x: 20, y: 20} Crafty.c("Circle", { circle: function(radius, color) { this.radius = radius; this.w = this.h = radius * 2; this.color = color || "#000000"; this.bind("Move", Crafty.DrawManager.drawAll) return this; }, draw: function() { var ctx = Crafty.canvas.context; ctx.save(); ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc( this.x + this.radius, this.y + this.radius, this.radius, 0, Math.PI * 2 ); ctx.closePath(); ctx.fill(); ctx.restore(); } }); var circle1 = Crafty.e("2D, Canvas, Circle").attr(dim1).circle(15, "red"); var circle2 = Crafty.e("2D, Canvas, Circle, Fourway").fourway(2).attr(dim2).circle(20, "blue"); circle2.bind("EnterFrame", function () { var dx = (circle1.x + circle1.radius) - (circle2.x + circle2.radius); var dy = (circle1.y + circle1.radius) - (circle2.y + circle2.radius); var distance = Math.sqrt(dx * dx + dy * dy); if (distance < circle1.radius + circle2.radius) { // collision detected! this.color = "green"; } else { // no collision this.color = "blue"; } });
var circle1 = {radius: 20, x: 5, y: 5};
var circle2 = {radius: 12, x: 10, y: 5};
var dx = circle1.x - circle2.x;
var dy = circle1.y - circle2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < circle1.radius + circle2.radius) {
// collision detected!
}
{{ EmbedLiveSample('Playable_code', '700', '300', '', 'Games/Techniques/2D_collision_detection') }}
Note: Here is another example without Canvas or external libraries.
Esto es un algoritmo que detecta la colision entre dos poligonos convexos. Ya que es complejo, se necesitara mejorar el rendimiento (explicado en la siguiente seccion).
Algunos algoritmos son sencillos de calcular, en cambio otros no. Normalmente los juegos, se dividen en dos fases: "Broad" y "Narrow".
Esta fase consiste en conseguir una lista de todas las cosas con las que se puede colisionar. Puede ser implementado con una estructura de datos que recoge que objetos hay alrededor de nuestro objeto.
Cuando tienes una lista pequeña, ya puedes detectar colision con un algoritmo.