--- /dev/null
+<!DOCTYPE html>
+ <html lang="es">
+ <head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Snake Shoot!</title>
+ <style>
+
+ * {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ }
+
+ html {
+ width: 100%;
+ height: 100%;
+ font-size: 1vh;
+ }
+
+ body {
+ width: 100%;
+ height: 100%;
+
+ background: rgb(185, 128, 4);
+
+ overflow: hidden;
+ }
+
+ .contenedor-gameboy {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ position: relative;
+ }
+
+ canvas {
+ display: block;
+ width: 100vw;
+ height: 100vw;
+ max-height: 70vh;
+ max-width: 70vh;
+ margin: 0 auto;
+
+ border: 3rem solid black;
+ border-width: 1.5rem 1.5rem 3rem 1.5rem;
+ background-color: rgb(57, 60, 61);
+
+ }
+
+ .contenedor-gameboy span {
+ display: flex;
+ width: 100%;
+ flex-direction: row;
+ gap: 2vh;
+ align-items: center;
+
+ margin: 0 auto 5vh auto;
+ position: absolute;
+ inset: calc(100vh - 25vh) 0 0 0;
+
+ max-width: 75vh;
+ }
+
+ .pad {
+ position: relative;
+ width: 50%;
+ height: 25vh;
+ font-size: 2.5rem;
+ }
+
+ .actionAB {
+ position: relative;
+ width: 50%;
+ height: 25vh;
+ font-size: 2.5rem;
+ }
+
+ #controlStart {
+ display: none;
+ }
+
+ #controlSelect {
+ display: none;
+ }
+
+ .lbl-control {
+ display: inline-block;
+ position: relative;
+ width: 6.5rem;
+ height: 2.5rem;
+ inset: 55% 0%;
+
+ border-radius: 15rem;
+ background-color: rgb(119, 112, 5);
+
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .lbl-control::after {
+ position: absolute;
+ content: '';
+ inset: 0.4rem 1rem;
+
+ width: 3rem;
+ height: 1.5rem;
+
+ border-radius: 15rem;
+ background-color: rgb(45, 49, 7);
+
+ }
+
+ .lbl-controlSelect {
+ display: inline-block;
+ position: relative;
+ width: 6.5rem;
+ height: 2.5rem;
+ inset: 55% 85%;
+
+ border-radius: 15rem;
+ background-color: rgb(119, 112, 5);
+
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .lbl-controlSelect::after {
+ position: absolute;
+ content: '';
+ inset: 0.4rem 1rem;
+
+ width: 3rem;
+ height: 1.5rem;
+
+ border-radius: 15rem;
+ background-color: rgb(45, 49, 7);
+ }
+
+ #controlStart:checked~ .lbl-control::after{
+ inset: 0.4rem 2.6rem;
+ }
+
+ #controlSelect:checked~ .lbl-controlSelect::after{
+ inset: 0.4rem 2.6rem;
+ }
+
+ /* Controles */
+
+ .A, .B, .ArrowUp, .ArrowDown, .ArrowLeft, .ArrowRight {
+ position: absolute;
+ width: 8rem;
+ height: 8rem;
+
+ border-radius: 50%;
+ background-color: rgb(165, 16, 65);
+ }
+
+ .ArrowUp {
+ inset: 10% 25%;
+ }
+ .ArrowUp::after{
+ content: '';
+ position: absolute;
+ inset: 20% 13%;
+ width: 0;
+ height: 0;
+ border-left: 2.5rem solid transparent;
+ border-right: 2.5rem solid transparent;
+
+ border-bottom: 2.5rem solid rgb(36, 1, 33);
+ }
+ .ArrowDown {
+ inset: 60% 25%;
+ }
+ .ArrowDown::after{
+ content: '';
+ position: absolute;
+ inset: 35% 13%;
+ width: 0;
+ height: 0;
+ border-left: 2.5rem solid transparent;
+ border-right: 2.5rem solid transparent;
+
+ border-top: 2.5rem solid rgb(36, 1, 33);
+ }
+ .ArrowLeft {
+ inset: 35% calc(25% - 6.5rem);
+ }
+ .ArrowLeft::after{
+ content: '';
+ position: absolute;
+ inset: 15% 25%;
+ width: 0;
+ height: 0;
+ border-top: 2.5rem solid transparent;
+ border-bottom: 2.5rem solid transparent;
+
+ border-right:2.5rem solid rgb(36, 1, 33);
+ }
+ .ArrowRight {
+ inset: 35% calc(25% + 6.5rem);
+ }
+ .ArrowRight::after{
+ content: '';
+ position: absolute;
+ inset: 15% 35%;
+ width: 0;
+ height: 0;
+ border-top: 2.5rem solid transparent;
+ border-bottom: 2.5rem solid transparent;
+
+ border-left: 2.5rem solid rgb(36, 1, 33);
+ }
+ .A {
+ inset: 25% calc(90% - 6.5rem);
+ }
+ .A::after {
+ content: 'A';
+ color: rgb(36, 1, 33);
+ position: absolute;
+ inset:0 14%;
+ font-weight: 700;
+ font-size: 4.4rem;
+
+ }
+ .B {
+ inset: 40% calc(60% - 6.5rem);
+ }
+ .B::after {
+ content: 'B';
+ color: rgb(36, 1, 33);
+ position: absolute;
+ inset: 0 18%;
+ font-weight: 700;
+ font-size: 4.4rem;
+
+ }
+
+ @media (max-width: 55vh) {
+
+ canvas {
+ min-width: 45vh;
+ min-height: 45vh;
+ margin: 0 auto;
+
+ border: none;
+ background-color: rgb(57, 60, 61);
+
+ }
+
+ .lbl-controlSelect {
+ inset: -35% 55%;
+ }
+ .lbl-control {
+ inset: -35% -20%;
+ }
+ .A {
+ inset: 25% calc(80% - 6.5rem);
+ }
+ .B {
+ inset: 40% calc(40% - 6.5rem);
+ }
+ .ArrowUp {
+ inset: 10% 35%;
+ }
+
+ .ArrowDown {
+ inset: 60% 35%;
+ }
+
+ .ArrowLeft {
+ inset: 35% calc(35% - 6.5rem);
+ }
+
+ .ArrowRight {
+ inset: 35% calc(35% + 6.5rem);
+ }
+
+ }
+
+ @media (min-width: calc(75vh + 60vh)){
+ body {
+ background: rgb(185, 128, 4);
+ }
+
+ .contenedor-gameboy {
+ flex-direction: row;
+ gap: 1rem;
+ }
+
+ canvas {
+ display: block;
+ position: relative;
+ width: 100vw;
+ height: 100vw;
+ max-height: 75vh;
+ max-width: 75vh;
+ min-width: 45vh;
+ min-height: 45vh;
+ margin: 0 auto;
+
+ inset: 10vh 0 0 0;
+ }
+
+ .contenedor-gameboy span {
+ display: flex;
+ flex-direction: row;
+ gap: 2vh;
+ align-items: stretch;
+
+ margin: 0;
+ position: absolute;
+ inset: calc(100vh - 25vh) 0 0 0;
+
+ min-width: 55vh;
+ max-width: 100vw;
+ }
+ .A {
+ inset: 35% 80%;
+ }
+ .B {
+ inset: 50% 65%;
+ }
+
+ }
+ </style>
+
+ </head>
+ <body>
+
+ <span class="contenedor-gameboy">
+
+
+ <canvas></canvas>
+ <span>
+ <div class="pad">
+ <div class="ArrowUp"></div>
+ <div class="ArrowDown"></div>
+ <div class="ArrowLeft"></div>
+ <div class="ArrowRight"></div>
+ <input type="checkbox" id="controlSelect"><label for="controlSelect" class="lbl-controlSelect" title="On/Off de menú"><br>Select</label>
+ </div>
+
+ <div class="actionAB">
+ <div class="A"></div>
+ <div class="B"></div>
+ <input type="checkbox" id="controlStart"><label for="controlStart" class="lbl-control" title="On/Off de animación"><br> Start</label>
+ </div>
+ </span>
+
+ </span>
+
+ <script>
+ 'use strict';
+ (function(){
+ const colisiones = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 73, 73, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 73, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ];
+
+ let i = 0;
+ let mapaColisiones = [];
+
+ while (i < colisiones.length){
+
+ mapaColisiones.push(colisiones.slice(i, i + 20)); // Se modifica el corte dependiendo del ancho del ancho
+ i += 20;
+ }
+
+ const controlAnim = document.querySelector('#controlStart');
+ const controlMenu = document.querySelector('#controlSelect');
+ const canvas = document.querySelector('canvas');
+ const CANVAS_WIDTH = canvas.width = 320;
+ const CANVAS_HEIGHT = canvas.height = 320;
+ const ctx = canvas.getContext('2d');
+
+ const mapa = new Image();
+ mapa.src = './map2.png';
+ const foreground = new Image();
+ foreground.src = './foreground.png';
+
+ // SFX
+ const coin = new Audio('./Pickup_coin 10.wav');
+ coin.volume = 0.08;
+ const pain = new Audio('./Hit_hurt 192 (2).wav');
+ pain.volume = 0.05;
+ const shoot = new Audio('./Explosion 69 (2).wav');
+ shoot.volume = 0.1;
+ const hithurt = new Audio('./Hit_hurt 176 (1).wav');
+ hithurt.volume = 0.2;
+ // NPC
+
+ class NPC{
+ constructor(start = 0, width, height, path = '', frames = 7, x = 0, y= 0, slowmo = 6, resolution = 1, velocidad = 2, life = 100, pain=2){
+ this.npcImage = new Image();
+ this.src = this.npcImage.src = path;
+ this.lifeImge = new Image();
+ this.lifeSrc = this.lifeImge.src = './lifebar.png';
+ this.width = width;
+ this.height = height;
+ this.resolution = resolution; // Este valor sólo puede ser entero o un entero con 0.5 de decimal
+ this.frameX = start;
+ this.frameY = 0;
+ this.gameFrame = 0;
+ this.slowmotion = slowmo;
+ this.controlF = frames;
+ this.x = x;
+ this.y = y;
+ this.efecto = {
+ activo: false,
+ estado: ''
+ };
+ this.movimiento = false;
+ this.direction = {
+ 'Last': undefined,
+ 'ArrowUp': false,
+ 'ArrowDown': false,
+ 'ArrowLeft': false,
+ 'ArrowRight': false
+ };
+ this.collision = false;
+ this.velocidad = velocidad;
+ this.life = life;
+ this.reload = false;
+ this.pain = pain;
+ this.hit = {
+ '0': (empuje)=>{
+ if(player.frameX === 6 || player.frameX === 1 || player.direction.Last === 'ArrowUp') {
+ this.life -= this.pain;
+ return this.y -= empuje;
+ }
+ },
+ '1': (empuje)=>{
+ if(player.frameX === 4 || player.frameX === 0 || player.direction.Last === 'ArrowDown') {
+ this.life -= this.pain;
+ return this.y += empuje;
+ }
+ },
+ '3': (empuje)=>{
+ if(player.frameX === 8 || player.frameX === 3 || player.direction.Last === 'ArrowLeft') {
+ this.life -= this.pain;
+ return this.x -= empuje;
+ }
+ },
+ '2': (empuje)=>{
+ if(player.frameX === 7 || player.frameX === 2 || player.direction.Last === 'ArrowRight') {
+ this.life -= this.pain;
+ return this.x += empuje;
+ }
+ },
+ 'undefined': ()=> {return;},
+ ' ': ()=>{return;}
+ };
+ this.fx = undefined;
+ this.offsetMapX = 0;
+ this.offsetMapY = 0;
+ }
+
+ hitbox(vel, empuje){
+
+ if(player.x - 24 < this.x + 16 && player.y + 88 > this.y && player.x + 88 > this.x && player.y - 20 < this.y + 16){
+
+ if(this.life && !player.efecto.activo){
+ this.velocidad = vel;
+ player.reload = true;
+ this.hit[this.frameX](empuje);
+ return setTimeout(() => {
+ player.reload = false;
+ }, 400);
+ };
+ return;
+ } else {return setTimeout(() => {
+ player.fx = undefined
+ player.reload = false;
+ }, 700)};
+ }
+
+ enfrente(lineaMedia = 32){ // Para renderizar adelante o atrás de un sprite
+ if(this.y >= player.y + lineaMedia) return true;
+ else return false;
+ }
+
+ colision(x = player.x, y = player.y, objetivo = player){ // Esto es para los sprites que no atacan y puedan pararse ante colisiones.
+
+
+ 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) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ random(){
+ if(this.colision()) {return;}
+ // Acá es donde los sprites se quedan quietos si se encuentran con el jugador.
+
+ this.slowmotion = 7;
+ if(this.gameFrame % 30 === 0){
+ switch (Math.trunc(Math.random() * 10 / 2)) {
+ case 0:
+ this.frameX = 2;
+ this.x -= 2;
+ if(player.frameX === 1) this.y -= 2;
+
+ break;
+ case 1:
+ this.frameX = 3;
+ this.x += 2;
+ if(player.frameX === 0) this.y += 2;
+
+ break;
+ case 2:
+ this.frameX = 0;
+ this.y += 2;
+ if(player.frameX === 3) this.x += 2;
+
+ break;
+ case 3:
+ this.frameX = 1;
+ this.y -= 2;
+ if(player.frameX === 2) this.x -= 2
+
+ break;
+ case 4:
+ // this.frameX = 4; // Falta hacer el estado de espera
+ break;
+ default:
+ break;
+ }
+ }
+
+ };
+
+ render() {
+
+ /*
+ Img - Imagen para renderizar
+ Posición en X de la imagen
+ Posición en Y de la imagen
+ Ancho de la imagen que se utilizará
+ Largo de la imagen que se utilizará
+ Posición en X del canvas que se renderizará
+ Posición en Y del canvas que se renderizará
+ Ancho que ocupará
+ Largo que ocupará
+ */
+
+ if(this.life <= 0 && this.life !== null){ // Bloque que se encarga de no renderizar más el sprite cuando no tiene vida
+ this.x, this.y = undefined;
+ this.life = null;
+
+ if(this === player){
+ controlAnim.checked = false;
+ ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+ return ctx.fillText(`Score: ${contador}`, CANVAS_WIDTH / 2 - 48, CANVAS_WIDTH / 2 - 16);
+ }
+
+ if(this !== player) { // Se le agrega vida extra al jugador una vez que ha matado al sprite
+ player.life += 5;
+ contador += this.velocidad * 10;
+ if(player.life > 100) player.life = 100;
+ setTimeout(()=>{
+ this.life = 100;
+ this.x = Math.trunc(Math.random() * (canvas.width - 16));
+ this.y = Math.trunc(Math.random() * (canvas.height - 16));
+ }, this.pain * 1000);
+ // player.fx = renderFx.bind(corazon);
+ };
+ return setTimeout(() => {
+ this.fx = undefined;
+ }, 2000);
+ } else if (this.life !== null){
+ ctx.font = '12px serif';
+ ctx.strokeText(this.life, this.x + this.width - this.offsetMapX, this.y - this.offsetMapY);
+ };
+
+ if(this.efecto.activo){ // Bloque para renderizar los efectos de un estado provocado por slime (fuego, electrico, empuje normal)
+ this.slowmotion = 4;
+ switch (this.efecto.estado) {
+ case 'electrico':
+ this.frameX = 9;
+ break;
+ case 'fuego':
+ this.frameX = 5;
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ // Bloque para visualizar la barra de vida
+
+ if(this.life === 100) ctx.drawImage(this.lifeImge, 0, 0, 106, 8, this.x - this.offsetMapX, this.y - 6 - this.offsetMapY, this.width, 4);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+
+
+ 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);
+
+ // Renderizar la estrella.
+
+
+
+ // 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.
+ if(this.fx !== undefined) {
+ this.fx();
+ };
+
+
+ if (this.gameFrame % this.slowmotion === 0) {
+ if (this.frameY < this.controlF) { // Control de los frames
+ this.frameY++;
+ } else {
+ this.frameY = 0;
+ };
+ };
+
+ this.gameFrame++;
+
+
+
+ };
+ };
+
+ const move = ()=>{
+ if(player.life === null) return;
+ player.slowmotion = 6;
+ if(player.direction.ArrowUp) {
+ // Acá es donde debo poner la colisión con algún sprite
+
+ player.frameX = 1;
+ if(player.y + 8 <= estrella.y + 16 && player.y + 8 > estrella.y && (player.x + 16 > estrella.x && player.x < estrella.x + 16)){
+ coin.play();
+ // Haz que la gema pase a otro lado.
+ contador += puntos;
+ randEstrella();
+ }
+
+ if(player.y + 8 <= 0) {return player.y = canvas.height - 16;}
+ if(mapaColisiones[Math.trunc((player.y) / 16)][Math.trunc((player.x + 8) / 16)] === 73){return player.movimiento = false;}
+ player.y -= paso;
+ }
+
+ if(player.direction.ArrowDown){
+
+ player.frameX = 0;
+ if(player.y + 16 >= estrella.y && player.y < estrella.y && (player.x + 16 > estrella.x && player.x < estrella.x + 16)){
+ coin.play();
+ contador += puntos;
+ randEstrella();
+ }
+
+ if(player.y + 16 >= canvas.height) {return player.y = -8;}
+ if(mapaColisiones[Math.trunc((player.y + 16 ) / 16)][Math.trunc((player.x + 8) / 16)] === 73){return player.movimiento = false;}
+ player.y += paso;
+ }
+
+ if(player.direction.ArrowLeft){
+
+ player.frameX = 2;
+ if(player.x + 8 <= estrella.x + 16 && player.x + 8 > estrella.x && (player.y + 16 > estrella.y && player.y < estrella.y + 16)){
+ coin.play();
+ contador += puntos;
+ randEstrella();
+ }
+ if(player.x + 8 <= 0) {return player.x = canvas.width - 16;}
+ if(mapaColisiones[Math.trunc((player.y + 8) / 16)][Math.trunc((player.x) / 16)] === 73){return player.movimiento = false;}
+ player.x -= paso;
+ }
+
+ if(player.direction.ArrowRight){
+
+ player.frameX = 3;
+ if(player.x + 8 >= estrella.x && player.x < estrella.x && (player.y + 16 > estrella.y && player.y < estrella.y + 16)){
+ coin.play();
+ contador += puntos;
+ randEstrella();
+ }
+ if(player.x + 16 >= canvas.width) {return player.x = -8;}
+ if(mapaColisiones[Math.trunc((player.y + 8) / 16)][Math.trunc((player.x + 16) / 16)] === 73){return player.movimiento = false;}
+ player.x += paso;
+ }
+ };
+
+
+ let [x,y,contador, puntos] = [0,0,0,1];
+ let paso = 1;
+
+ // const marcador = (function () {
+ // let contador = 0; // private variable
+ // return {
+ // set setCount(valida){
+ // contador++;
+ // },
+ // get getCount(){
+ // return contador;
+ // }
+ // };
+ // }());
+
+ // Jugador principal
+ const player = new NPC(undefined, 16, 16, './Snake2.png', 3, 4 * 25, 4 * 25, 8, 1, 1, 100, 10);
+ const estrella = new NPC(undefined, 16, 16, './gema.png', 3, 4 * 57, 4 * 70, 10, 1, 0, null, undefined);
+
+ const randEstrella = ()=>{
+ if(contador >= 20){
+ puntos = 2;
+ estrella.npcImage.src = './gema2.png';
+ };
+
+ if(contador >= 50){
+ puntos = 5;
+ estrella.npcImage.src = './gema3.png';
+ };
+
+ if(contador >= 100){
+ puntos = 10;
+ estrella.npcImage.src = './gema4.png';
+
+ };
+
+ return estrella.x = Math.trunc(Math.random() * (canvas.width - 16)), estrella.y = Math.trunc(Math.random() * (canvas.height - 16));
+ };
+
+ // Objetcs
+
+ const bala = new NPC(undefined, 8, 8, './disparo.png', 3, 0, 0, 5, 1, 3, null);
+
+ function disparo(){
+
+ if(player.life === null || bala.movimiento === true) return;
+ bala.movimiento = true;
+ if(player.direction.ArrowUp) {
+ // Acá es donde debo poner la colisión con algún sprite
+
+ bala.frameX = 0;
+ bala.x = player.x + 4; // Bala centrada
+ bala.y = player.y - 4;
+ shoot.play();
+ }
+
+ if(player.direction.ArrowDown){
+
+ bala.frameX = 1;
+ bala.x = player.x + 2;
+ bala.y = player.y + 12;
+ shoot.play();
+ }
+
+ if(player.direction.ArrowLeft){
+
+ bala.frameX = 3;
+ bala.x = player.x;
+ bala.y = player.y + 4;
+ shoot.play();
+ }
+
+ if(player.direction.ArrowRight){
+
+ bala.frameX = 2;
+ bala.x = player.x + 12;
+ bala.y = player.y + 4;
+ shoot.play();
+ }
+
+ }
+
+ let npcActivos = [];
+
+ function shootHit(){
+ if(npcActivos.length !== 0) {
+ npcActivos.forEach(sprite => {
+
+ switch (bala.frameX) {
+ case 0: // Arriba
+ if((bala.y <= sprite.y + sprite.height && bala.y > sprite.y) && (bala.x + bala.width > sprite.x && bala.x < sprite.x + sprite.width)){
+ bala.y = player.y
+ bala.movimiento = false;
+ shoot.pause();
+ shoot.currentTime = 0;
+ sprite.life -= sprite.pain;
+ sprite.y -= 24;
+ hithurt.play();// Reproducir un sonido de golpe.
+ // console.log('le pegaste');
+ }
+
+ if(bala.y <= 0){
+ bala.y = player.y
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.y -= bala.velocidad;
+ break;
+
+ case 1: // Abajo
+ 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)){
+ bala.y = player.y
+ bala.movimiento = false;
+ shoot.pause();
+ shoot.currentTime = 0;
+ sprite.life -= sprite.pain;
+ sprite.y += 24;
+ hithurt.play();
+ // console.log('le pegaste');
+ }
+
+ if(bala.y >= canvas.height){
+ bala.y = player.y
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.y += bala.velocidad;
+ break;
+
+ case 2: // Derecha
+ 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)){
+ bala.y = player.y
+ bala.movimiento = false;
+ shoot.pause();
+ shoot.currentTime = 0;
+ sprite.life -= sprite.pain;
+ sprite.x += 24;
+ hithurt.play();
+ // console.log('le pegaste');
+ }
+
+ if(bala.x >= canvas.width){
+ bala.y = player.x
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.x += bala.velocidad;
+ break;
+
+ case 3: // Izquierda
+ if((bala.x <= sprite.x + sprite.width && bala.x > sprite.x) && (bala.y + bala.height > sprite.y && bala.y < sprite.y + sprite.height)){
+ bala.y = player.y
+ bala.movimiento = false;
+ shoot.pause();
+ shoot.currentTime = 0;
+ sprite.life -= sprite.pain;
+ sprite.x -= 24;
+ hithurt.play();
+ // console.log('le pegaste');
+ }
+
+ if(bala.x <= 0){
+ bala.y = player.x
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 5;
+ }
+ bala.x -= bala.velocidad;
+ break;
+ default:
+ break;
+ };
+ });
+ } else {
+ switch (bala.frameX) {
+ case 0: // Arriba
+
+ if(bala.y <= 0){
+ bala.y = player.y
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.y -= bala.velocidad;
+ break;
+
+ case 1: // Abajo
+
+ if(bala.y >= canvas.height){
+ bala.y = player.y
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.y += bala.velocidad;
+ break;
+
+ case 2: // Derecha
+
+ if(bala.x >= canvas.width){
+ bala.y = player.x
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 0;
+ }
+ bala.x += bala.velocidad;
+ break;
+
+ case 3: // Izquierda
+
+ if(bala.x <= 0){
+ bala.y = player.x
+ bala.movimiento = false;
+ // console.log('murio la bala')
+ shoot.pause();
+ shoot.currentTime = 5;
+ }
+ bala.x -= bala.velocidad;
+ break;
+ default:
+ break;
+ };
+ }
+ }
+
+ // Slimes
+
+ const blueSlime = new NPC(undefined, 32, 32,'./Slime.png', 3, 4*12, 4*30, 7, 1, 0.4, undefined, 8);
+ const skull = new NPC(undefined, 32, 32, './Skull.png', 3, 4 * 10, 4 * 20, 6, 1, 0.6, undefined, 2);
+ // const owl = new NPC(undefined, 32, 32, './Slimes/Owl.png', 3, 4 * 50, 4 * 10, 15, 0.5, 0.2, null);
+ const mouse = new NPC(undefined, 16, 16, './Mouse.png', 3, 4 * 25, 4 * 25, 6, 1, 0.8, 100, 5);
+
+ /* Comportamiento de los slimes */
+
+ const damage = {
+ '': ()=>{player.life -= 2},
+ 'fuego': ()=>{player.life -= 5},
+ 'electrico': ()=>{player.life -= 10}
+ }
+
+ // Ataque de los slimes
+
+ const attack = (sprite, efecto='', empujeS = 8, empujeP = 4)=>{
+ // if( // Si se encuentra cerca del jugador.
+ // (player.x < sprite.x + (sprite.width * sprite.resolution) + 96) &&
+ // (player.x + (player.width * player.resolution) > sprite.x - 96) &&
+ // (player.y < sprite.y + (sprite.height * sprite.resolution) + 96) &&
+ // (player.y + (player.height * player.resolution) > sprite.y - 96)
+ // ){
+ sprite.slowmo = 5;
+ if(player.life <= 0) return;
+
+ if (player.x + (player.width * player.resolution) / 2 < sprite.x + (sprite.width * sprite.resolution) / 2){
+ sprite.x -= sprite.velocidad;
+ sprite.frameX = 2;
+ };
+
+ if (player.x + (player.width * player.resolution) / 2 > sprite.x + (sprite.width * sprite.resolution) / 2){
+ sprite.x += sprite.velocidad;
+ sprite.frameX = 3;
+ };
+
+ 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)){
+ sprite.y += sprite.velocidad;
+ sprite.frameX = 0;
+ };
+
+ 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)){
+ sprite.y -= sprite.velocidad;
+ sprite.frameX = 1;
+ };
+
+ 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
+ pain.play();
+ if(player.y - empujeP <= 0) {
+ player.y = canvas.height - 16;
+ return damage[efecto]();
+ }
+ damage[efecto]();
+ player.y -= empujeP;
+
+ };
+
+ 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
+ pain.play();
+ if(player.y + 16 + empujeP >= canvas.height) {
+ player.y = -8;
+ return damage[efecto]();
+ }
+ damage[efecto]();
+ player.y += empujeP;
+
+ };
+
+
+ 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
+ pain.play();
+ if(player.x - empujeP <= 0) {
+ player.x = canvas.width - 16;
+ return damage[efecto]();
+ }
+ damage[efecto]();
+ player.x -= empujeP;
+
+ };
+
+ 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
+ pain.play();
+ if(player.x + empujeP + 16 >= canvas.width) {
+ player.x = -8;
+ return damage[efecto]();
+ }
+ damage[efecto]();
+ player.x += empujeP;
+ };
+ // } else {
+ // sprite.random();
+ // }
+
+ };
+
+ // Movimiento libre de un sprite
+
+ const freeMove = (sprite)=>{
+ if( // Si se encuentra cerca del jugador.
+ (player.x < sprite.x + (sprite.width * sprite.resolution) + 128) &&
+ (player.x + (player.width * player.resolution) > sprite.x - 128) &&
+ (player.y < sprite.y + (sprite.height * sprite.resolution) + 128) &&
+ (player.y + (player.height * player.resolution) > sprite.y - 128)
+ ){
+ // Llamar una función que haga movimiento aleatorio.
+ sprite.random();
+ };
+ return;
+
+ // if(player.x + (player.width * player.resolution) > owl.x - 32 && owl.x >= player.x + (player.width * player.resolution)){
+ // owl.x -= owl.velocidad;
+ // }
+
+ // if((player.y < owl.y + (owl.height * owl.resolution) + 32 && owl.y + (owl.height * owl.resolution) <= player.y)){
+ // // Llamar una función que haga movimiento aleatorio.
+ // owl.y += owl.velocidad;
+ // }
+
+ // if(player.y + (player.height * player.resolution) > owl.y - 32 && owl.y >= player.y + (player.height * player.resolution)){
+ // owl.y -= owl.velocidad;
+ // }
+ };
+
+ function animacion(){
+
+ if (controlAnim.checked){
+ ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+ ctx.drawImage(mapa, x, y, mapa.width, mapa.height, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+
+ // Acciones de los sprites
+ // attack(blueSlime);
+ // attack(skull, 'fuego', 0, 32, 16);
+ // attack(mouse, undefined, 8, 4);
+ // freeMove(owl);
+ if(player.movimiento && player.life !== 0) {
+ move();
+ };
+
+ if(bala.movimiento){ // Refactorizar para que la funcionalidad sea para cualquier npc.
+ bala.render();
+ shootHit();
+ }
+
+
+ // if(!blueSlime.enfrente()) blueSlime.render();
+ // if(!mouse.enfrente(48)) mouse.render();
+ // if(!skull.enfrente()) skull.render();
+ player.render();
+ if(player.life === null){return;}
+ ctx.drawImage(foreground, x, y, mapa.width, mapa.height, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+ // owl.render();
+ // if(blueSlime.enfrente()) blueSlime.render();
+ // if(mouse.enfrente(48)) mouse.render();
+ // if(skull.enfrente()) skull.render();
+ if(contador >= 5){
+ blueSlime.render();
+ attack(blueSlime, undefined, undefined, 10);
+ if(!npcActivos.includes(blueSlime)) npcActivos.push(blueSlime);
+ };
+
+ if(contador >= 30){
+ skull.render();
+ attack(skull, 'fuego', 0, 20);
+ if(!npcActivos.includes(skull)) npcActivos.push(skull);
+ };
+
+ if(contador >= 50){
+ mouse.render();
+ attack(mouse);
+ if(!npcActivos.includes(mouse)) npcActivos.push(mouse);
+ };
+
+ estrella.render();
+ ctx.font = '32px serif';
+
+ ctx.fillStyle = 'black';
+ ctx.lineWidth = 1;
+ ctx.fillText(contador, 16, 32);
+
+ requestAnimationFrame(animacion); // El orden en que aparecen acá es lo que importa para que uno esté por encima del otro
+
+ } else {
+ return;
+ }
+
+ }
+
+ controlMenu.addEventListener('click', ()=>{
+
+ if(controlMenu.checked){
+ canvas.style = 'image-rendering: crisp-edges;';
+ ctx.imageSmoothingEnabled = false;
+
+ } else {
+ canvas.style = 'image-rendering: none;';
+ ctx.imageSmoothingEnabled = true;
+
+ };
+ })
+
+ controlAnim.addEventListener('click', ()=>{
+ if (controlAnim.checked){
+ animacion();
+ } else {
+ return;
+ };
+ })
+
+ document.addEventListener('keydown', (e)=>{
+
+ // console.log(e.key)
+ if (!controlAnim.checked){return;}
+ e.preventDefault();
+
+ if(e.key === ' '){
+ disparo();
+ };
+
+ if(e.key !== 'ArrowUp' && e.key !== 'ArrowDown' && e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' && e.key){
+ return;
+ }
+ player.direction['ArrowLeft'] = false;
+ player.direction['ArrowUp'] = false;
+ player.direction['ArrowRight'] = false;
+ player.direction['ArrowDown'] = false;
+
+ player.movimiento = true;
+ player.direction[e.key] = true;
+
+ });
+
+ const dir = {
+ 'ArrowUp': ()=>player.frameX = 1,
+ 'ArrowDown': ()=>player.frameX = 0,
+ 'ArrowLeft': ()=>player.frameX = 2,
+ 'ArrowRight': ()=>player.frameX = 3,
+ 'undefined' : ()=>player.frameX = 0,
+ }
+
+
+ // Controles
+
+ window.mobileCheck = function() {
+ let check = false;
+ (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);
+ return check;
+ };
+
+ let [keyDown, keyMove, keyUp] = window.mobileCheck() ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup'];
+
+
+ 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'),];
+
+ a.addEventListener(keyDown, (e)=>{
+ disparo();
+ })
+
+ const pad = document.querySelector('.pad');
+ pad.addEventListener(keyDown, (e)=>{
+ if (!controlAnim.checked){return;}
+ e.preventDefault();
+
+ if(e.target !== up && e.target !== down && e.target !== left && e.target !== right){
+ return;
+ }
+
+ // console.log(e.target.className)
+ player.direction['ArrowLeft'] = false;
+ player.direction['ArrowUp'] = false;
+ player.direction['ArrowRight'] = false;
+ player.direction['ArrowDown'] = false;
+
+ player.movimiento = true;
+ player.direction[e.target.className] = true;
+ });
+
+ }());
+
+ </script>
+ </body>
+</html>
\ No newline at end of file