1 | <!DOCTYPE html> |
2 | <html> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Jueguito 2</title> |
9 | <style> |
10 | body { |
11 | position: fixed; |
12 | top: 0px; |
13 | left: 0px; |
14 | width: 100%; |
15 | height: 100%; |
16 | margin: 0; |
17 | overflow: hidden; |
18 | } |
19 | |
20 | .sprite { |
21 | position: fixed; |
22 | } |
23 | </style> |
24 | <script> |
25 | |
26 | |
27 | class Jugador |
28 | extends HTMLElement { |
29 | izquierda() { |
30 | throw new Error("abstract") |
31 | } |
32 | derecha() { |
33 | throw new Error("abstract") |
34 | } |
35 | sube() { |
36 | throw new Error("abstract") |
37 | } |
38 | baja() { |
39 | throw new Error("abstract") |
40 | } |
41 | } |
42 | |
43 | |
44 | class Figura |
45 | extends HTMLElement { |
46 | |
47 | |
48 | |
49 | |
50 | muevete(jugador) { |
51 | throw new Error("abstract"); |
52 | } |
53 | } |
54 | |
55 | class Juego2 { |
56 | constructor() { |
57 | |
58 | this.jugador = document. |
59 | querySelector(".jugador") |
60 | |
61 | this.figuras = Array.from( |
62 | document.querySelectorAll( |
63 | ".figura")) |
64 | this.iniciaX = null |
65 | this.iniciaY = null |
66 | this.interval = null |
67 | this.activo = true |
68 | } |
69 | |
70 | inicia() { |
71 | document.addEventListener( |
72 | "keydown", |
73 | evt => this.teclas(evt)) |
74 | document.addEventListener( |
75 | "touchstart", |
76 | evt => this.iniciaTouch(evt)) |
77 | document.addEventListener( |
78 | "touchmove", |
79 | evt => |
80 | this.desplazaTouch(evt)) |
81 | this.interval = setInterval( |
82 | () => this.mueveFiguras(), 60) |
83 | } |
84 | |
85 | mueveFiguras() { |
86 | for (const f of this.figuras) { |
87 | f.muevete(this.jugador) |
88 | } |
89 | this.detectaColisiones() |
90 | } |
91 | |
92 | detectaColisiones() { |
93 | for (const f of this.figuras) { |
94 | if (colisiona( |
95 | this.jugador, f)) { |
96 | this.termina() |
97 | break |
98 | } |
99 | } |
100 | } |
101 | |
102 | termina() { |
103 | this.activo = false |
104 | clearInterval(this.interval) |
105 | alert("Jueguito 2 terminado.") |
106 | } |
107 | |
108 | |
109 | teclas(evt) { |
110 | if (this.activo) { |
111 | switch (evt.key) { |
112 | case "ArrowLeft": |
113 | this.jugador.izquierda() |
114 | break |
115 | case "ArrowRight": |
116 | this.jugador.derecha() |
117 | break |
118 | case "ArrowUp": |
119 | this.jugador.sube() |
120 | break |
121 | case "ArrowDown": |
122 | this.jugador.baja() |
123 | break |
124 | } |
125 | this.detectaColisiones() |
126 | } |
127 | } |
128 | |
129 | |
130 | iniciaTouch(evt) { |
131 | if (this.activo) { |
132 | const toqueInicial = |
133 | evt.touches[0] |
134 | this.iniciaX = |
135 | toqueInicial.clientX |
136 | this.iniciaY = |
137 | toqueInicial.clientY |
138 | } |
139 | } |
140 | |
141 | |
142 | desplazaTouch(evt) { |
143 | if (this.activo |
144 | && this.iniciaX |
145 | && this.iniciaY) { |
146 | const desplazamiento = |
147 | evt.touches[0] |
148 | var desplazamientoX = |
149 | desplazamiento.clientX |
150 | var desplazamientoY = |
151 | desplazamiento.clientY |
152 | var difX = desplazamientoX - |
153 | this.iniciaX |
154 | var difY = desplazamientoY - |
155 | this.iniciaY |
156 | |
157 | |
158 | if (Math.abs(difX) |
159 | + Math.abs(difY) |
160 | > 150) { |
161 | if (Math.abs(difX) |
162 | > Math.abs(difY)) { |
163 | if (difX > 70) { |
164 | this.jugador.derecha() |
165 | } else { |
166 | this.jugador.izquierda() |
167 | } |
168 | } else if (difY > 70) { |
169 | this.jugador.baja() |
170 | } else { |
171 | this.jugador.sube() |
172 | } |
173 | this.detectaColisiones() |
174 | |
175 | this.iniciaX = null; |
176 | this.iniciaY = null; |
177 | } |
178 | } |
179 | } |
180 | } |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | function colisiona(e1, e2) { |
189 | const rE1 = |
190 | e1.getBoundingClientRect() |
191 | const rE2 = |
192 | e2.getBoundingClientRect() |
193 | return (rE1.right >= rE2.left |
194 | && rE1.left <= rE2.right |
195 | && rE1.top <= rE2.bottom |
196 | && rE1.bottom >= rE2.top) |
197 | } |
198 | |
199 | customElements.define( |
200 | "jugador-paloma", |
201 | class extends Jugador { |
202 | connectedCallback() { |
203 | this.classList.add("sprite") |
204 | this.classList.add("jugador") |
205 | this.innerHTML += "🕊" |
206 | this.style.fontSize = "60px" |
207 | const raiz = |
208 | document.documentElement |
209 | const r = |
210 | this.getBoundingClientRect() |
211 | const left = |
212 | (raiz.clientWidth |
213 | - r.width) / |
214 | 2 |
215 | const top = |
216 | (raiz.clientHeight - |
217 | r.height) / |
218 | 2 |
219 | this.style.left = `${left}px` |
220 | this.style.top = `${top}px` |
221 | } |
222 | |
223 | |
224 | sube() { |
225 | const top = |
226 | this.getBoundingClientRect(). |
227 | top - |
228 | 20 |
229 | this.style.top = `${top}px` |
230 | } |
231 | |
232 | |
233 | baja() { |
234 | const top = |
235 | this.getBoundingClientRect(). |
236 | top + |
237 | 20 |
238 | this.style.top = `${top}px` |
239 | } |
240 | |
241 | izquierda() { |
242 | const left = |
243 | this.getBoundingClientRect(). |
244 | left - |
245 | 20 |
246 | this.style.left = `${left}px` |
247 | } |
248 | |
249 | derecha() { |
250 | const left = |
251 | this.getBoundingClientRect(). |
252 | left + |
253 | 20 |
254 | this.style.left = `${left}px` |
255 | } |
256 | }) |
257 | |
258 | customElements.define( |
259 | "figura-aguila", |
260 | class extends Figura { |
261 | connectedCallback() { |
262 | this.classList.add("sprite") |
263 | this.classList.add("figura") |
264 | this.innerHTML = "🦅" |
265 | this.style.fontSize = "40px" |
266 | const r = |
267 | this.getBoundingClientRect() |
268 | this.style.left = |
269 | `${r.left}px` |
270 | this.style.top = `${r.top}px` |
271 | this.style.bottom = "auto" |
272 | this.style.right = "auto" |
273 | } |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | muevete(jugador) { |
282 | const r = |
283 | this.getBoundingClientRect() |
284 | const rJ = jugador. |
285 | getBoundingClientRect() |
286 | const y2 = rJ.top |
287 | const y1 = r.top |
288 | const x2 = rJ.left |
289 | const x1 = r.left |
290 | const pendiente = x2 === x1 ? |
291 | 0 : |
292 | (y2 - y1) / (x2 - x1) |
293 | const dirección = |
294 | x2 > x1 ? 1 : -1 |
295 | const x = x1 + dirección * 5 |
296 | const y = |
297 | pendiente * (x - x1) + y1 |
298 | |
299 | |
300 | |
301 | this.style.left = |
302 | `${desvía(x)}px` |
303 | this.style.top = |
304 | `${desvía(y)}px` |
305 | } |
306 | }) |
307 | |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | function desvía(i) { |
315 | return i + 10 - |
316 | 20 * Math.random() |
317 | } |
318 | </script> |
319 | </head> |
320 | |
321 | <body> |
322 | <jugador-paloma></jugador-paloma> |
323 | <figura-aguila |
324 | style="right: 0; top: 0;"> |
325 | </figura-aguila> |
326 | <figura-aguila |
327 | style="right: 0; bottom: 0;"> |
328 | </figura-aguila> |
329 | <script> |
330 | |
331 | const juego2 = new Juego2() |
332 | juego2.inicia() |
333 | </script> |
334 | </body> |
335 | |
336 | </html> |