N. Jueguito 2

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

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 //@ts-check
26 /** @abstract */
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 /** @abstract */
44 class Figura
45 extends HTMLElement {
46 /**
47 * @param {HTMLElement} jugador
48 * el jugador que persigue.
49 */
50 muevete(jugador) {
51 throw new Error("abstract");
52 }
53 }
54
55 class Juego2 {
56 constructor() {
57 /** @type {Jugador} */
58 this.jugador = document.
59 querySelector(".jugador")
60 /** @type {Figura[]} */
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 /** @param {KeyboardEvent} evt*/
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 /** @param {TouchEvent} evt */
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 /** @param {TouchEvent} evt */
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 /* Checa que el movimiento no
157 * sea muy corto. */
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 // Reinicia valores.
175 this.iniciaX = null;
176 this.iniciaY = null;
177 }
178 }
179 }
180 }
181
182 /**
183 * @param {HTMLElement} e1
184 * @param {HTMLElement} e2
185 * @returns {boolean} true si los
186 * element colisionan.
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 /** @override */
224 sube() {
225 const top =
226 this.getBoundingClientRect().
227 top -
228 20
229 this.style.top = `${top}px`
230 }
231
232 /** @override */
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 * @param {HTMLElement} jugador
277 * el jugador que es
278 * perseguido.
279 * @override
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 /* Evita que las figuras se
299 * peguen, añadiendo un
300 * movimiento aleatorio. */
301 this.style.left =
302 `${desvía(x)}px`
303 this.style.top =
304 `${desvía(y)}px`
305 }
306 })
307
308 /**
309 * Obtiene una desviación
310 * aleatoria de 10 alrededor del
311 * valor i.
312 * @param {number} i valor base
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 //@ts-check
331 const juego2 = new Juego2()
332 juego2.inicia()
333 </script>
334</body>
335
336</html>
skip_previous skip_next