--- /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</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
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg
+ version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ x="0%" y="0%"
+ width="100%" height="100%"
+ viewBox="0 0 64.0 64.0"
+ enable-background="new 0 0 64.0 64.0"
+ xml:space="preserve">
+<defs>
+ <linearGradient id="fillGrad0" x1="0.000%" y1="50.000%" x2="100.000%" y2="50.000%">
+ <stop offset="0.000%" style="stop-color:rgb(204,122,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(122,73,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <radialGradient id="fillGrad11" cx="20.213%" cy="49.154%" fx="20.213%" fy="49.154%" r="54.863%">
+ <stop offset="0.000%" style="stop-color:rgb(6,49,0);stop-opacity:1.000" />
+ <stop offset="63.876%" style="stop-color:rgb(255,250,221);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(224,185,0);stop-opacity:1.000" />
+ </radialGradient>
+
+ <linearGradient id="fillGrad12" x1="50.000%" y1="42.308%" x2="50.000%" y2="88.462%">
+ <stop offset="0.000%" style="stop-color:rgb(84,45,0);stop-opacity:1.000" />
+ <stop offset="58.621%" style="stop-color:rgb(177,110,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(192,150,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad15" x1="35.457%" y1="76.350%" x2="42.670%" y2="15.270%">
+ <stop offset="0.000%" style="stop-color:rgb(150,102,0);stop-opacity:1.000" />
+ <stop offset="62.642%" style="stop-color:rgb(255,236,212);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(255,254,253);stop-opacity:1.000" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad16" x1="36.098%" y1="53.460%" x2="72.987%" y2="75.228%">
+ <stop offset="0.000%" style="stop-color:rgb(255,210,97);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(237,141,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <radialGradient id="fillGrad19" cx="20.755%" cy="3.192%" fx="20.755%" fy="3.192%" r="68.726%">
+ <stop offset="0.000%" style="stop-color:rgb(166,255,111);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(33,63,0);stop-opacity:1.000" />
+ </radialGradient>
+
+ <linearGradient id="fillGrad20" x1="65.756%" y1="45.405%" x2="34.034%" y2="41.765%">
+ <stop offset="0.000%" style="stop-color:rgb(90,86,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(76,26,0);stop-opacity:1.000" />
+ </linearGradient>
+
+<filter id="glow20" x="-200%" y="-200%" width="600%" height="600%" >
+ <feOffset result="offOut" in="SourceGraphic" dx="0.09601528" dy="0.0" />
+ <feGaussianBlur result="blurOut" in="offOut" stdDeviation="0.06000955" />
+ <feFlood flood-color="#007315" flood-opacity="0.902" result="flood"/>
+ <feComposite in="flood" in2="blurOut" operator="in" result="blendOut0"/>
+ <feBlend in="blendOut0" in2="blendOut0" result="blendOut1" mode="normal" />
+ <feBlend in="blendOut1" in2="blendOut0" result="blendOut2" mode="normal" />
+ <feBlend in="blendOut2" in2="blendOut0" result="blendOut3" mode="normal" />
+ <feBlend in="blendOut3" in2="blendOut0" result="blendOut4" mode="normal" />
+ <feBlend in="blendOut4" in2="blendOut0" result="blendOut5" mode="normal" />
+ <feBlend in="blendOut5" in2="blendOut0" result="blendOut6" mode="normal" />
+ <feBlend in="blendOut6" in2="blendOut0" result="blendOut7" mode="normal" />
+ <feBlend in="blendOut7" in2="blendOut0" result="blendOut8" mode="normal" />
+ <feBlend in="SourceGraphic" in2="blendOut8" mode="normal" />
+</filter>
+
+ <radialGradient id="fillGrad21" cx="26.137%" cy="13.083%" fx="26.137%" fy="13.083%" r="74.887%">
+ <stop offset="0.000%" style="stop-color:rgb(248,199,0);stop-opacity:0.796" />
+ <stop offset="100.000%" style="stop-color:rgb(84,47,0);stop-opacity:1.000" />
+ </radialGradient>
+
+<filter id="glow21" x="-200%" y="-200%" width="600%" height="600%" >
+ <feOffset result="offOut" in="SourceGraphic" dx="0.09227241" dy="0.03075747" />
+ <feGaussianBlur result="blurOut" in="offOut" stdDeviation="0.0076893675" />
+ <feFlood flood-color="#594100" flood-opacity="0.741" result="flood"/>
+ <feComposite in="flood" in2="blurOut" operator="in" result="blendOut0"/>
+ <feBlend in="blendOut0" in2="blendOut0" result="blendOut1" mode="normal" />
+ <feBlend in="SourceGraphic" in2="blendOut1" mode="normal" />
+</filter>
+
+ <linearGradient id="fillGrad22" x1="0.000%" y1="50.000%" x2="100.000%" y2="50.000%">
+ <stop offset="0.000%" style="stop-color:rgb(48,127,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(43,50,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad23" x1="32.529%" y1="59.084%" x2="111.590%" y2="16.041%">
+ <stop offset="0.000%" style="stop-color:rgb(236,130,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(30,13,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad24" x1="54.417%" y1="56.958%" x2="49.470%" y2="15.907%">
+ <stop offset="0.000%" style="stop-color:rgb(255,250,234);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(140,87,0);stop-opacity:1.000" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad106" x1="31.579%" y1="21.576%" x2="36.842%" y2="81.902%">
+ <stop offset="0.000%" style="stop-color:rgb(167,143,0);stop-opacity:0.275" />
+ <stop offset="47.212%" style="stop-color:rgb(255,232,199);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(158,84,0);stop-opacity:0.808" />
+ </linearGradient>
+
+ <linearGradient id="fillGrad107" x1="64.144%" y1="50.355%" x2="23.418%" y2="72.735%">
+ <stop offset="0.000%" style="stop-color:rgb(64,128,0);stop-opacity:1.000" />
+ <stop offset="100.000%" style="stop-color:rgb(255,250,217);stop-opacity:1.000" />
+ </linearGradient>
+
+</defs>
+ <path
+ transform = "rotate(-0.00 14.05 23.08)"
+ fill="url(#fillGrad0)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.3247997"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M5.68,21.97C6.44,23.32,7.20,24.67,10.70,24.49C14.20,24.31,20.43,22.60,22.00,21.97C23.57,21.34,20.48,21.79,16.98,21.97C13.48,22.15,9.58,22.06,5.68,21.97z"/>
+ <path
+ fill="#FFEFB7"
+ stroke="#4C2F00"
+ fill-opacity="1.000"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.45806697"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M61.22,44.14L53.82,44.75L54.23,39.25L60.29,40.68Q63.52,42.71,61.22,44.14z"/>
+ <path
+ fill="#B9A100"
+ stroke="#4C2F00"
+ fill-opacity="1.000"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.29333276"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M53.65,44.50L61.25,44.00L53.88,42.84"/>
+ <path
+ transform = "rotate(-265.19 26.54 30.00)"
+ fill="url(#fillGrad11)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.25682724"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M19.57,39.14C22.16,37.61,24.74,36.08,27.25,38.50C29.77,40.92,32.21,47.30,33.10,42.43C33.99,37.55,33.33,21.43,32.08,17.11C30.83,12.78,29.01,20.25,27.00,23.48C24.98,26.72,22.77,25.71,20.57,24.70"/>
+ <path
+ transform = "rotate(-0.00 30.11 55.50)"
+ fill="url(#fillGrad12)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.256"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M23.00,47.00L37.22,47.00L37.22,64.00L23.00,64.00z"/>
+ <path
+ transform = "rotate(-0.00 31.36 41.99)"
+ fill="url(#fillGrad15)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.37145984"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M16.09,35.25A4.42 4.45 190.10 0 1 20.87,33.05C20.35,31.37,19.83,29.69,17.57,30.00C15.31,30.31,11.31,32.60,9.30,36.84C7.29,41.08,7.26,47.26,11.66,50.53C16.06,53.81,24.89,54.18,32.92,53.95C40.94,53.72,48.17,52.89,51.81,49.39C55.45,45.90,55.50,39.75,52.99,35.70C50.48,31.66,45.40,29.72,38.82,30.00C32.24,30.27,24.17,32.76,16.09,35.25z"/>
+ <path
+ transform = "rotate(-0.00 12.76 18.51)"
+ fill="url(#fillGrad16)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.29604602"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M5.22,20.00C5.17,20.88,5.13,21.75,8.10,22.88C11.06,24.02,17.05,25.41,19.22,23.00C21.39,20.59,19.76,14.37,19.22,13.00C18.68,11.63,19.24,15.11,17.22,17.00C15.20,18.90,10.62,19.21,8.19,19.45C5.76,19.68,5.49,19.84,5.22,20.00z"/>
+ <path
+ transform = "rotate(-0.00 27.08 18.49)"
+ fill="url(#fillGrad19)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.31519932"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M34.00,22.00C32.69,25.13,31.39,28.26,29.00,29.00C26.61,29.74,23.15,28.08,21.16,26.40C19.16,24.73,18.64,23.03,18.12,21.34C17.97,17.44,17.83,13.54,20.00,11.00C22.17,8.46,26.66,7.28,30.00,8.00C33.34,8.72,35.53,11.35,36.00,14.00C36.47,16.65,35.24,19.33,34.00,22.00z"/>
+ <path
+ transform = "rotate(-100.97 22.53 14.95)"
+ fill="url(#fillGrad20)"
+ stroke="#BABF00"
+ fill-opacity="1.0"
+ stroke-opacity="0.671"
+ fill-rule="nonzero"
+ stroke-width="0.056699134"
+ filter="url(#glow20)"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M22.22,16.55C21.96,16.09,21.70,15.63,21.64,15.11C21.59,14.60,21.75,14.02,22.01,13.68C22.27,13.35,22.62,13.26,22.92,13.43C23.22,13.59,23.45,14.02,23.43,14.41C23.41,14.79,23.13,15.14,22.88,15.49C22.64,15.84,22.43,16.19,22.22,16.55z"/>
+ <path
+ transform = "rotate(-0.00 22.00 15.01)"
+ fill="url(#fillGrad21)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.0"
+ filter="url(#glow21)"
+ stroke-linejoin="round"
+ stroke-linecap="square"
+ d="M22.00,14.23C22.42,14.23,22.76,14.58,22.76,15.01C22.76,15.44,22.42,15.79,22.00,15.79C21.58,15.79,21.24,15.44,21.24,15.01C21.24,14.58,21.58,14.23,22.00,14.23z"/>
+ <path
+ transform = "rotate(-0.00 18.92 21.22)"
+ fill="url(#fillGrad22)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.256"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M20.22,25.59C19.33,24.70,18.44,23.81,18.00,23.00C17.56,22.19,17.58,21.45,17.67,20.67C17.76,19.88,17.92,19.05,18.00,18.67C18.08,18.28,18.07,18.34,18.08,18.11C18.09,17.88,18.11,17.36,18.14,16.84"/>
+ <path
+ transform = "rotate(-340.81 16.22 19.00)"
+ fill="url(#fillGrad23)"
+ stroke="#5E3A00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.192"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M16.22,18.62C16.55,18.62,16.82,18.79,16.82,19.00C16.82,19.21,16.55,19.38,16.22,19.38C15.89,19.38,15.62,19.21,15.62,19.00C15.62,18.79,15.89,18.62,16.22,18.62z"/>
+ <path
+ transform = "rotate(-176.23 38.08 42.15)"
+ fill="url(#fillGrad24)"
+ stroke="#5E3A00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M25.72,46.57C23.07,44.33,20.42,42.09,25.20,38.72C29.98,35.35,42.19,30.85,48.46,32.68C54.72,34.52,55.06,42.69,50.54,47.19C46.02,51.69,36.64,52.52,31.70,51.81C26.75,51.10,26.24,48.83,25.72,46.57z"/>
+ <path
+ fill="#854900"
+ stroke="#5E3A00"
+ fill-opacity="0.180"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M27.27,35.49L29.20,37.09L26.76,37.68L28.70,39.28L26.25,39.86L28.19,41.47L25.74,42.05L27.68,43.66L25.23,44.24L27.17,45.85L24.73,46.43L26.66,48.04L24.22,48.62"/>
+ <path
+ fill="#854900"
+ stroke="#5E3A00"
+ fill-opacity="0.180"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M34.31,33.11L36.50,34.34L34.20,35.35L36.39,36.58L34.09,37.60L36.28,38.83L33.98,39.84"/>
+ <path
+ fill="#854900"
+ stroke="#5E3A00"
+ fill-opacity="0.180"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M38.41,33.44L40.54,34.78L38.19,35.67L40.32,37.01L37.97,37.91L40.10,39.25L37.75,40.15"/>
+ <path
+ fill="#854900"
+ stroke="#5E3A00"
+ fill-opacity="0.180"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M45.20,35.16L47.31,36.53L44.95,37.39L47.06,38.76L44.70,39.63L46.81,40.99L44.45,41.86"/>
+ <path
+ fill="#854900"
+ stroke="#5E3A00"
+ fill-opacity="0.180"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M41.68,34.21L43.84,35.49L41.53,36.46L43.69,37.73L41.37,38.70L43.54,39.97L41.22,40.94"/>
+ <path
+ transform = "rotate(-0.00 37.51 41.45)"
+ fill="url(#fillGrad106)"
+ stroke="#5E3A00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M27.96,47.77Q35.83,52.26,47.07,43.27Q36.97,38.57,30.48,40.35L32.82,39.43L30.68,38.11L33.01,37.19L30.87,35.87L33.21,34.95L31.07,33.63"/>
+ <path
+ transform = "rotate(-0.00 25.00 26.90)"
+ fill="url(#fillGrad107)"
+ stroke="#4C2F00"
+ fill-opacity="1.0"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.32"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M19.13,24.75C19.24,25.97,19.36,27.19,21.00,28.00C22.64,28.81,25.81,29.22,28.00,29.00C30.19,28.78,31.40,27.94,30.67,27.67C29.93,27.39,27.25,27.69,25.00,27.30C22.75,26.91,20.94,25.83,19.13,24.75z"/>
+ <path
+ fill="#211400"
+ stroke="#694100"
+ fill-opacity="1.000"
+ stroke-opacity="1.000"
+ fill-rule="nonzero"
+ stroke-width="0.08146739"
+ stroke-linejoin="round"
+ stroke-linecap="round"
+ d="M22.00,14.69C22.17,14.69,22.30,14.83,22.30,15.01C22.30,15.18,22.17,15.32,22.00,15.32C21.83,15.32,21.70,15.18,21.70,15.01C21.70,14.83,21.83,14.69,22.00,14.69z"/>
+</svg>
\ No newline at end of file