5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>Snake Shoot!</title>
13 box-sizing: border-box;
26 background: rgb(185, 128, 4);
33 flex-direction: column;
47 border: 3rem solid black;
48 border-width: 1.5rem 1.5rem 3rem 1.5rem;
49 background-color: rgb(57, 60, 61);
53 .contenedor-gameboy span {
60 margin: 0 auto 5vh auto;
62 inset: calc(100vh - 25vh) 0 0 0;
90 display: inline-block;
97 background-color: rgb(119, 112, 5);
103 .lbl-control::after {
111 border-radius: 15rem;
112 background-color: rgb(45, 49, 7);
117 display: inline-block;
123 border-radius: 15rem;
124 background-color: rgb(119, 112, 5);
130 .lbl-controlSelect::after {
138 border-radius: 15rem;
139 background-color: rgb(45, 49, 7);
142 #controlStart:checked~ .lbl-control::after{
143 inset: 0.4rem 2.6rem;
146 #controlSelect:checked~ .lbl-controlSelect::after{
147 inset: 0.4rem 2.6rem;
152 .A, .B, .ArrowUp, .ArrowDown, .ArrowLeft, .ArrowRight {
158 background-color: rgb(165, 16, 65);
170 border-left: 2.5rem solid transparent;
171 border-right: 2.5rem solid transparent;
173 border-bottom: 2.5rem solid rgb(36, 1, 33);
184 border-left: 2.5rem solid transparent;
185 border-right: 2.5rem solid transparent;
187 border-top: 2.5rem solid rgb(36, 1, 33);
190 inset: 35% calc(25% - 6.5rem);
198 border-top: 2.5rem solid transparent;
199 border-bottom: 2.5rem solid transparent;
201 border-right:2.5rem solid rgb(36, 1, 33);
204 inset: 35% calc(25% + 6.5rem);
212 border-top: 2.5rem solid transparent;
213 border-bottom: 2.5rem solid transparent;
215 border-left: 2.5rem solid rgb(36, 1, 33);
218 inset: 25% calc(90% - 6.5rem);
222 color: rgb(36, 1, 33);
230 inset: 40% calc(60% - 6.5rem);
234 color: rgb(36, 1, 33);
242 @media (max-width: 55vh) {
250 background-color: rgb(57, 60, 61);
261 inset: 25% calc(80% - 6.5rem);
264 inset: 40% calc(40% - 6.5rem);
275 inset: 35% calc(35% - 6.5rem);
279 inset: 35% calc(35% + 6.5rem);
284 @media (min-width: calc(75vh + 60vh)){
286 background: rgb(185, 128, 4);
289 .contenedor-gameboy {
308 .contenedor-gameboy span {
312 align-items: stretch;
316 inset: calc(100vh - 25vh) 0 0 0;
334 <span class="contenedor-gameboy">
340 <div class="ArrowUp"></div>
341 <div class="ArrowDown"></div>
342 <div class="ArrowLeft"></div>
343 <div class="ArrowRight"></div>
344 <input type="checkbox" id="controlSelect"><label for="controlSelect" class="lbl-controlSelect" title="On/Off de menú"><br>Select</label>
347 <div class="actionAB">
348 <div class="A"></div>
349 <div class="B"></div>
350 <input type="checkbox" id="controlStart"><label for="controlStart" class="lbl-control" title="On/Off de animación"><br> Start</label>
360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0,
362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
363 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 73, 73, 73, 0, 0, 0, 0, 0,
364 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
366 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
367 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
368 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
369 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
372 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 73, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377 0, 0, 0, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
379 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
383 let mapaColisiones = [];
385 while (i < colisiones.length){
387 mapaColisiones.push(colisiones.slice(i, i + 20)); // Se modifica el corte dependiendo del ancho del ancho
391 const controlAnim = document.querySelector('#controlStart');
392 const controlMenu = document.querySelector('#controlSelect');
393 const canvas = document.querySelector('canvas');
394 const CANVAS_WIDTH = canvas.width = 320;
395 const CANVAS_HEIGHT = canvas.height = 320;
396 const ctx = canvas.getContext('2d');
398 const mapa = new Image();
399 mapa.src = './map2.png';
400 const foreground = new Image();
401 foreground.src = './foreground.png';
404 const coin = new Audio('./Pickup_coin 10.wav');
406 const pain = new Audio('./Hit_hurt 192 (2).wav');
408 const shoot = new Audio('./Explosion 69 (2).wav');
410 const hithurt = new Audio('./Hit_hurt 176 (1).wav');
411 hithurt.volume = 0.2;
415 constructor(start = 0, width, height, path = '', frames = 7, x = 0, y= 0, slowmo = 6, resolution = 1, velocidad = 2, life = 100, pain=2){
416 this.npcImage = new Image();
417 this.src = this.npcImage.src = path;
418 this.lifeImge = new Image();
419 this.lifeSrc = this.lifeImge.src = './lifebar.png';
421 this.height = height;
422 this.resolution = resolution; // Este valor sólo puede ser entero o un entero con 0.5 de decimal
426 this.slowmotion = slowmo;
427 this.controlF = frames;
434 this.movimiento = false;
442 this.collision = false;
443 this.velocidad = velocidad;
449 if(player.frameX === 6 || player.frameX === 1 || player.direction.Last === 'ArrowUp') {
450 this.life -= this.pain;
451 return this.y -= empuje;
455 if(player.frameX === 4 || player.frameX === 0 || player.direction.Last === 'ArrowDown') {
456 this.life -= this.pain;
457 return this.y += empuje;
461 if(player.frameX === 8 || player.frameX === 3 || player.direction.Last === 'ArrowLeft') {
462 this.life -= this.pain;
463 return this.x -= empuje;
467 if(player.frameX === 7 || player.frameX === 2 || player.direction.Last === 'ArrowRight') {
468 this.life -= this.pain;
469 return this.x += empuje;
472 'undefined': ()=> {return;},
482 if(player.x - 24 < this.x + 16 && player.y + 88 > this.y && player.x + 88 > this.x && player.y - 20 < this.y + 16){
484 if(this.life && !player.efecto.activo){
485 this.velocidad = vel;
486 player.reload = true;
487 this.hit[this.frameX](empuje);
488 return setTimeout(() => {
489 player.reload = false;
493 } else {return setTimeout(() => {
494 player.fx = undefined
495 player.reload = false;
499 enfrente(lineaMedia = 32){ // Para renderizar adelante o atrás de un sprite
500 if(this.y >= player.y + lineaMedia) return true;
504 colision(x = player.x, y = player.y, objetivo = player){ // Esto es para los sprites que no atacan y puedan pararse ante colisiones.
507 if(this.x <= x + (objetivo.width * objetivo.resolution - 16) && this.x + (this.width * this.resolution ) >= x + 16 && this.y <= y + (objetivo.height * objetivo.resolution - 24) && this.y + (this.height * this.resolution) >= y + 32) {
515 if(this.colision()) {return;}
516 // Acá es donde los sprites se quedan quietos si se encuentran con el jugador.
519 if(this.gameFrame % 30 === 0){
520 switch (Math.trunc(Math.random() * 10 / 2)) {
524 if(player.frameX === 1) this.y -= 2;
530 if(player.frameX === 0) this.y += 2;
536 if(player.frameX === 3) this.x += 2;
542 if(player.frameX === 2) this.x -= 2
546 // this.frameX = 4; // Falta hacer el estado de espera
558 Img - Imagen para renderizar
559 Posición en X de la imagen
560 Posición en Y de la imagen
561 Ancho de la imagen que se utilizará
562 Largo de la imagen que se utilizará
563 Posición en X del canvas que se renderizará
564 Posición en Y del canvas que se renderizará
569 if(this.life <= 0 && this.life !== null){ // Bloque que se encarga de no renderizar más el sprite cuando no tiene vida
570 this.x, this.y = undefined;
574 controlAnim.checked = false;
575 ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
576 return ctx.fillText(`Score: ${contador}`, CANVAS_WIDTH / 2 - 48, CANVAS_WIDTH / 2 - 16);
579 if(this !== player) { // Se le agrega vida extra al jugador una vez que ha matado al sprite
581 contador += this.velocidad * 10;
582 if(player.life > 100) player.life = 100;
585 this.x = Math.trunc(Math.random() * (canvas.width - 16));
586 this.y = Math.trunc(Math.random() * (canvas.height - 16));
587 }, this.pain * 1000);
588 // player.fx = renderFx.bind(corazon);
590 return setTimeout(() => {
593 } else if (this.life !== null){
594 ctx.font = '12px serif';
595 ctx.strokeText(this.life, this.x + this.width - this.offsetMapX, this.y - this.offsetMapY);
598 if(this.efecto.activo){ // Bloque para renderizar los efectos de un estado provocado por slime (fuego, electrico, empuje normal)
600 switch (this.efecto.estado) {
613 // Bloque para visualizar la barra de vida
615 if(this.life === 100) ctx.drawImage(this.lifeImge, 0, 0, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
616 if(this.life <100 && this.life >= 90) ctx.drawImage(this.lifeImge, 0, 8, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
617 if(this.life <90 && this.life >= 80) ctx.drawImage(this.lifeImge, 0, 16, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
618 if(this.life <80 && this.life >= 70) ctx.drawImage(this.lifeImge, 0, 24, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
619 if(this.life <70 && this.life >= 60) ctx.drawImage(this.lifeImge, 0, 32, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
620 if(this.life <60 && this.life >= 50) ctx.drawImage(this.lifeImge, 0, 40, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
621 if(this.life <50 && this.life >= 40) ctx.drawImage(this.lifeImge, 0, 48, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
622 if(this.life <40 && this.life >= 30) ctx.drawImage(this.lifeImge, 0, 56, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
623 if(this.life <30 && this.life >= 20) ctx.drawImage(this.lifeImge, 0, 64, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
624 if(this.life <20 && this.life >= 1) ctx.drawImage(this.lifeImge, 0, 72, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
627 ctx.drawImage(this.npcImage, this.frameX * this.width, this.frameY * this.height, this.width, this.height, this.x - this.offsetMapX, this.y - this.offsetMapY, this.width * this.resolution, this.height * this.resolution);
629 // Renderizar la estrella.
633 // Acá es donde se renderiza la imagen, se renderiza después porque estos efectos están pensados para ir encima del sprite al cual están unidos.
634 if(this.fx !== undefined) {
639 if (this.gameFrame % this.slowmotion === 0) {
640 if (this.frameY < this.controlF) { // Control de los frames
655 if(player.life === null) return;
656 player.slowmotion = 6;
657 if(player.direction.ArrowUp) {
658 // Acá es donde debo poner la colisión con algún sprite
661 if(player.y + 8 <= estrella.y + 16 && player.y + 8 > estrella.y && (player.x + 16 > estrella.x && player.x < estrella.x + 16)){
663 // Haz que la gema pase a otro lado.
668 if(player.y + 8 <= 0) {return player.y = canvas.height - 16;}
669 if(mapaColisiones[Math.trunc((player.y) / 16)][Math.trunc((player.x + 8) / 16)] === 73){return player.movimiento = false;}
673 if(player.direction.ArrowDown){
676 if(player.y + 16 >= estrella.y && player.y < estrella.y && (player.x + 16 > estrella.x && player.x < estrella.x + 16)){
682 if(player.y + 16 >= canvas.height) {return player.y = -8;}
683 if(mapaColisiones[Math.trunc((player.y + 16 ) / 16)][Math.trunc((player.x + 8) / 16)] === 73){return player.movimiento = false;}
687 if(player.direction.ArrowLeft){
690 if(player.x + 8 <= estrella.x + 16 && player.x + 8 > estrella.x && (player.y + 16 > estrella.y && player.y < estrella.y + 16)){
695 if(player.x + 8 <= 0) {return player.x = canvas.width - 16;}
696 if(mapaColisiones[Math.trunc((player.y + 8) / 16)][Math.trunc((player.x) / 16)] === 73){return player.movimiento = false;}
700 if(player.direction.ArrowRight){
703 if(player.x + 8 >= estrella.x && player.x < estrella.x && (player.y + 16 > estrella.y && player.y < estrella.y + 16)){
708 if(player.x + 16 >= canvas.width) {return player.x = -8;}
709 if(mapaColisiones[Math.trunc((player.y + 8) / 16)][Math.trunc((player.x + 16) / 16)] === 73){return player.movimiento = false;}
715 let [x,y,contador, puntos] = [0,0,0,1];
718 // const marcador = (function () {
719 // let contador = 0; // private variable
721 // set setCount(valida){
731 const player = new NPC(undefined, 16, 16, './Snake2.png', 3, 4 * 25, 4 * 25, 8, 1, 1, 100, 10);
732 const estrella = new NPC(undefined, 16, 16, './gema.png', 3, 4 * 57, 4 * 70, 10, 1, 0, null, undefined);
734 const randEstrella = ()=>{
737 estrella.npcImage.src = './gema2.png';
742 estrella.npcImage.src = './gema3.png';
747 estrella.npcImage.src = './gema4.png';
751 return estrella.x = Math.trunc(Math.random() * (canvas.width - 16)), estrella.y = Math.trunc(Math.random() * (canvas.height - 16));
756 const bala = new NPC(undefined, 8, 8, './disparo.png', 3, 0, 0, 5, 1, 3, null);
760 if(player.life === null || bala.movimiento === true) return;
761 bala.movimiento = true;
762 if(player.direction.ArrowUp) {
763 // Acá es donde debo poner la colisión con algún sprite
766 bala.x = player.x + 4; // Bala centrada
767 bala.y = player.y - 4;
771 if(player.direction.ArrowDown){
774 bala.x = player.x + 2;
775 bala.y = player.y + 12;
779 if(player.direction.ArrowLeft){
783 bala.y = player.y + 4;
787 if(player.direction.ArrowRight){
790 bala.x = player.x + 12;
791 bala.y = player.y + 4;
800 if(npcActivos.length !== 0) {
801 npcActivos.forEach(sprite => {
803 switch (bala.frameX) {
805 if((bala.y <= sprite.y + sprite.height && bala.y > sprite.y) && (bala.x + bala.width > sprite.x && bala.x < sprite.x + sprite.width)){
807 bala.movimiento = false;
809 shoot.currentTime = 0;
810 sprite.life -= sprite.pain;
812 hithurt.play();// Reproducir un sonido de golpe.
813 // console.log('le pegaste');
818 bala.movimiento = false;
819 // console.log('murio la bala')
821 shoot.currentTime = 0;
823 bala.y -= bala.velocidad;
827 if((bala.y + bala.height >= sprite.y && bala.y + bala.height < sprite.y + sprite.height) && (bala.x + bala.width > sprite.x && bala.x < sprite.x + sprite.width)){
829 bala.movimiento = false;
831 shoot.currentTime = 0;
832 sprite.life -= sprite.pain;
835 // console.log('le pegaste');
838 if(bala.y >= canvas.height){
840 bala.movimiento = false;
841 // console.log('murio la bala')
843 shoot.currentTime = 0;
845 bala.y += bala.velocidad;
849 if((bala.x + bala.width >= sprite.x && bala.x + bala.width < sprite.x + sprite.width) && (bala.y + bala.height > sprite.y && bala.y < sprite.y + sprite.height)){
851 bala.movimiento = false;
853 shoot.currentTime = 0;
854 sprite.life -= sprite.pain;
857 // console.log('le pegaste');
860 if(bala.x >= canvas.width){
862 bala.movimiento = false;
863 // console.log('murio la bala')
865 shoot.currentTime = 0;
867 bala.x += bala.velocidad;
871 if((bala.x <= sprite.x + sprite.width && bala.x > sprite.x) && (bala.y + bala.height > sprite.y && bala.y < sprite.y + sprite.height)){
873 bala.movimiento = false;
875 shoot.currentTime = 0;
876 sprite.life -= sprite.pain;
879 // console.log('le pegaste');
884 bala.movimiento = false;
885 // console.log('murio la bala')
887 shoot.currentTime = 5;
889 bala.x -= bala.velocidad;
896 switch (bala.frameX) {
901 bala.movimiento = false;
902 // console.log('murio la bala')
904 shoot.currentTime = 0;
906 bala.y -= bala.velocidad;
911 if(bala.y >= canvas.height){
913 bala.movimiento = false;
914 // console.log('murio la bala')
916 shoot.currentTime = 0;
918 bala.y += bala.velocidad;
923 if(bala.x >= canvas.width){
925 bala.movimiento = false;
926 // console.log('murio la bala')
928 shoot.currentTime = 0;
930 bala.x += bala.velocidad;
937 bala.movimiento = false;
938 // console.log('murio la bala')
940 shoot.currentTime = 5;
942 bala.x -= bala.velocidad;
952 const blueSlime = new NPC(undefined, 32, 32,'./Slime.png', 3, 4*12, 4*30, 7, 1, 0.4, undefined, 8);
953 const skull = new NPC(undefined, 32, 32, './Skull.png', 3, 4 * 10, 4 * 20, 6, 1, 0.6, undefined, 2);
954 // const owl = new NPC(undefined, 32, 32, './Slimes/Owl.png', 3, 4 * 50, 4 * 10, 15, 0.5, 0.2, null);
955 const mouse = new NPC(undefined, 16, 16, './Mouse.png', 3, 4 * 25, 4 * 25, 6, 1, 0.8, 100, 5);
957 /* Comportamiento de los slimes */
960 '': ()=>{player.life -= 2},
961 'fuego': ()=>{player.life -= 5},
962 'electrico': ()=>{player.life -= 10}
965 // Ataque de los slimes
967 const attack = (sprite, efecto='', empujeS = 8, empujeP = 4)=>{
968 // if( // Si se encuentra cerca del jugador.
969 // (player.x < sprite.x + (sprite.width * sprite.resolution) + 96) &&
970 // (player.x + (player.width * player.resolution) > sprite.x - 96) &&
971 // (player.y < sprite.y + (sprite.height * sprite.resolution) + 96) &&
972 // (player.y + (player.height * player.resolution) > sprite.y - 96)
975 if(player.life <= 0) return;
977 if (player.x + (player.width * player.resolution) / 2 < sprite.x + (sprite.width * sprite.resolution) / 2){
978 sprite.x -= sprite.velocidad;
982 if (player.x + (player.width * player.resolution) / 2 > sprite.x + (sprite.width * sprite.resolution) / 2){
983 sprite.x += sprite.velocidad;
987 if(player.y + (player.height * player.resolution) / 2 > sprite.y + (sprite.height * sprite.resolution) / 2 && (player.x + (player.width * player.resolution) / 2 < (sprite.x + (sprite.width * sprite.resolution)/2)+72) && (player.x + (player.width * player.resolution) / 2 > (sprite.x + (sprite.width * sprite.resolution)/2)-72)){
988 sprite.y += sprite.velocidad;
992 if((player.y + (player.height * player.resolution) / 2) + 12 < sprite.y + (sprite.height * sprite.resolution) / 2 && (player.x + (player.width * player.resolution) / 2 < (sprite.x + (sprite.width * sprite.resolution)/2)+72) && (player.x + (player.width * player.resolution) / 2 > (sprite.x + (sprite.width * sprite.resolution)/2)-72)){
993 sprite.y -= sprite.velocidad;
997 if ((player.y + 16 >= sprite.y && player.y + 8 < (sprite.y)) && (player.x + 8 < sprite.x + sprite.width * sprite.resolution && (player.x + player.width * player.resolution) -8 > sprite.x)) { // Hacia arriba
999 if(player.y - empujeP <= 0) {
1000 player.y = canvas.height - 16;
1001 return damage[efecto]();
1004 player.y -= empujeP;
1008 if ((player.y + 8 <= (sprite.y + sprite.height * sprite.resolution) && player.y + 16 > (sprite.y)) && (player.x + 8 < sprite.x + sprite.width * sprite.resolution && (player.x + player.width * player.resolution) -8 > sprite.x)) { // Hacia abajo
1010 if(player.y + 16 + empujeP >= canvas.height) {
1012 return damage[efecto]();
1015 player.y += empujeP;
1020 if ((player.x + 16 >= (sprite.x) && player.x + 8 <= (sprite.x + sprite.width * sprite.resolution)) && (player.y + 32 < sprite.y + sprite.width * sprite.resolution && (player.y + player.width * player.resolution) -8 > sprite.y)) { // Hacia izquierda
1022 if(player.x - empujeP <= 0) {
1023 player.x = canvas.width - 16;
1024 return damage[efecto]();
1027 player.x -= empujeP;
1031 if ((player.x + 8 <= (sprite.x + sprite.width * sprite.resolution) && player.x + 16 > (sprite.x)) && (player.y + 8 < sprite.y + sprite.width * sprite.resolution && (player.y + player.width * player.resolution) -8 > sprite.y)) { // Hacia derecha
1033 if(player.x + empujeP + 16 >= canvas.width) {
1035 return damage[efecto]();
1038 player.x += empujeP;
1046 // Movimiento libre de un sprite
1048 const freeMove = (sprite)=>{
1049 if( // Si se encuentra cerca del jugador.
1050 (player.x < sprite.x + (sprite.width * sprite.resolution) + 128) &&
1051 (player.x + (player.width * player.resolution) > sprite.x - 128) &&
1052 (player.y < sprite.y + (sprite.height * sprite.resolution) + 128) &&
1053 (player.y + (player.height * player.resolution) > sprite.y - 128)
1055 // Llamar una función que haga movimiento aleatorio.
1060 // if(player.x + (player.width * player.resolution) > owl.x - 32 && owl.x >= player.x + (player.width * player.resolution)){
1061 // owl.x -= owl.velocidad;
1064 // if((player.y < owl.y + (owl.height * owl.resolution) + 32 && owl.y + (owl.height * owl.resolution) <= player.y)){
1065 // // Llamar una función que haga movimiento aleatorio.
1066 // owl.y += owl.velocidad;
1069 // if(player.y + (player.height * player.resolution) > owl.y - 32 && owl.y >= player.y + (player.height * player.resolution)){
1070 // owl.y -= owl.velocidad;
1074 function animacion(){
1076 if (controlAnim.checked){
1077 ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
1078 ctx.drawImage(mapa, x, y, mapa.width, mapa.height, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
1080 // Acciones de los sprites
1081 // attack(blueSlime);
1082 // attack(skull, 'fuego', 0, 32, 16);
1083 // attack(mouse, undefined, 8, 4);
1085 if(player.movimiento && player.life !== 0) {
1089 if(bala.movimiento){ // Refactorizar para que la funcionalidad sea para cualquier npc.
1095 // if(!blueSlime.enfrente()) blueSlime.render();
1096 // if(!mouse.enfrente(48)) mouse.render();
1097 // if(!skull.enfrente()) skull.render();
1099 if(player.life === null){return;}
1100 ctx.drawImage(foreground, x, y, mapa.width, mapa.height, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
1102 // if(blueSlime.enfrente()) blueSlime.render();
1103 // if(mouse.enfrente(48)) mouse.render();
1104 // if(skull.enfrente()) skull.render();
1107 attack(blueSlime, undefined, undefined, 10);
1108 if(!npcActivos.includes(blueSlime)) npcActivos.push(blueSlime);
1113 attack(skull, 'fuego', 0, 20);
1114 if(!npcActivos.includes(skull)) npcActivos.push(skull);
1120 if(!npcActivos.includes(mouse)) npcActivos.push(mouse);
1124 ctx.font = '32px serif';
1126 ctx.fillStyle = 'black';
1128 ctx.fillText(contador, 16, 32);
1130 requestAnimationFrame(animacion); // El orden en que aparecen acá es lo que importa para que uno esté por encima del otro
1138 controlMenu.addEventListener('click', ()=>{
1140 if(controlMenu.checked){
1141 canvas.style = 'image-rendering: crisp-edges;';
1142 ctx.imageSmoothingEnabled = false;
1145 canvas.style = 'image-rendering: none;';
1146 ctx.imageSmoothingEnabled = true;
1151 controlAnim.addEventListener('click', ()=>{
1152 if (controlAnim.checked){
1159 document.addEventListener('keydown', (e)=>{
1161 // console.log(e.key)
1162 if (!controlAnim.checked){return;}
1169 if(e.key !== 'ArrowUp' && e.key !== 'ArrowDown' && e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' && e.key){
1172 player.direction['ArrowLeft'] = false;
1173 player.direction['ArrowUp'] = false;
1174 player.direction['ArrowRight'] = false;
1175 player.direction['ArrowDown'] = false;
1177 player.movimiento = true;
1178 player.direction[e.key] = true;
1183 'ArrowUp': ()=>player.frameX = 1,
1184 'ArrowDown': ()=>player.frameX = 0,
1185 'ArrowLeft': ()=>player.frameX = 2,
1186 'ArrowRight': ()=>player.frameX = 3,
1187 'undefined' : ()=>player.frameX = 0,
1193 window.mobileCheck = function() {
1195 (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
1199 let [keyDown, keyMove, keyUp] = window.mobileCheck() ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup'];
1202 const [a, b, up, down, left, right] = [document.querySelector('.A'), document.querySelector('.B'), document.querySelector('.ArrowUp'), document.querySelector('.ArrowDown'), document.querySelector('.ArrowLeft'), document.querySelector('.ArrowRight'),];
1204 a.addEventListener(keyDown, (e)=>{
1208 const pad = document.querySelector('.pad');
1209 pad.addEventListener(keyDown, (e)=>{
1210 if (!controlAnim.checked){return;}
1213 if(e.target !== up && e.target !== down && e.target !== left && e.target !== right){
1217 // console.log(e.target.className)
1218 player.direction['ArrowLeft'] = false;
1219 player.direction['ArrowUp'] = false;
1220 player.direction['ArrowRight'] = false;
1221 player.direction['ArrowDown'] = false;
1223 player.movimiento = true;
1224 player.direction[e.target.className] = true;