1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
---
title: 2D collision detection
slug: Games/Techniques/2D_collision_detection
tags:
- 2D
- Deteccion de colision
- JavaScript
- juegos
translation_of: Games/Techniques/2D_collision_detection
---
<div>{{GamesSidebar}}</div><p>{{IncludeSubnav("/en-US/docs/Games")}}</p>
<div class="summary">
<p>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.</p>
</div>
<h2 id="Hitbox_alineada_con_las_cordenadas">Hitbox alineada con las cordenadas</h2>
<p>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.</p>
<pre class="brush: js">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!
}
</pre>
<div class="hidden">
<h5 id="Rect_code">Rect code</h5>
<pre class="brush: html"><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>
</pre>
<pre class="brush: js">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");
}
});
</pre>
</div>
<p> </p>
<p>{{ EmbedLiveSample('Rect_code', '700', '300', '', 'Games/Techniques/2D_collision_detection') }}</p>
<h2 id="Colision_circular">Colision circular</h2>
<p>Otra colision simple es entre dos circulos. Funciona con los centros de los dos circulos y calculando la distancia entre los dos.</p>
<div class="hidden">
<h6 id="Playable_code">Playable code</h6>
<pre class="brush: html"><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>
</pre>
<pre class="brush: css">#cr-stage {
position: static !important;
height: 200px !important;
}
</pre>
<pre class="brush: js">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";
}
});
</pre>
</div>
<pre class="brush: js"><code>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!
}</code>
</pre>
<p>{{ EmbedLiveSample('Playable_code', '700', '300', '', 'Games/Techniques/2D_collision_detection') }}</p>
<p><strong>Note</strong>: <a href="https://jsfiddle.net/jlr7245/teb4znk0/20/">Here is another example without Canvas or external libraries.</a></p>
<h2 id="El_teorema_de_separar_los_ejes">El teorema de separar los ejes</h2>
<p>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). </p>
<h2 id="Mejorar_el_rendimiento_de_las_colisiones">Mejorar el rendimiento de las colisiones</h2>
<p>Algunos algoritmos son sencillos de calcular, en cambio otros no. Normalmente los juegos, se dividen en dos fases: "Broad" y "Narrow".</p>
<h3 id="Broad_Phase">Broad Phase</h3>
<p>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.</p>
<h3 id="Narrow_Phase">Narrow Phase</h3>
<p>Cuando tienes una lista pequeña, ya puedes detectar colision con un algoritmo.</p>
|