const canvas = document.getElementById("lienzo"); const ctx = canvas.getContext("2d"); const width = (canvas.width = 288); const height = (canvas.height = 512); ctx.scale(1, 1); const states = { IDLE: 0, RUNNING: 1, GAMEOVER: 2, }; const images = {}; const audiosFx = {}; // function cargarImagenes(images, callback) { // const nombresImagenes = [ // "bg", // "suelo", // "tuberias", // "flappybird", // "logo", // "ready", // "gameover", // "taptap", // ]; // let imagenesCargadas = 0; // nombresImagenes.forEach((nombre) => { // const img = new Image(); // img.src = `./assets/${nombre}.png`; // img.onload = () => { // imagenesCargadas++; // if (imagenesCargadas === nombresImagenes.length) { // callback(); // Llamar al callback una vez que todas las imágenes estén cargadas // } // }; // images[nombre] = img; // }); // } function cargarRecursos(images, audioFx, callback) { const recursos = [ { nombre: "bg", tipo: "imagen" }, { nombre: "suelo", tipo: "imagen" }, { nombre: "tuberias", tipo: "imagen" }, { nombre: "flappybird", tipo: "imagen" }, { nombre: "logo", tipo: "imagen" }, { nombre: "ready", tipo: "imagen" }, { nombre: "gameover", tipo: "imagen" }, { nombre: "taptap", tipo: "imagen" }, { nombre: "gameover", tipo: "audio" }, { nombre: "coin", tipo: "audio" }, { nombre: "flap", tipo: "audio" } ]; let recursosCargados = 0; recursos.forEach((recurso) => { if (recurso.tipo === "imagen") { const img = new Image(); img.src = `./assets/${recurso.nombre}.png`; img.onload = () => { recursosCargados++; if (recursosCargados === recursos.length) { callback(); } }; images[recurso.nombre] = img; } else if (recurso.tipo === "audio") { const audio = new Audio(); audio.src = `./assets/${recurso.nombre}.ogg`; audio.addEventListener("canplaythrough", () => { recursosCargados++; if (recursosCargados === recursos.length) { callback(); } }); audioFx[recurso.nombre] = audio; } }); } // Llama a la función cargarRecursos para cargar imágenes y audios cargarRecursos(images, audiosFx, iniciarJuego); class State { constructor(state) { this.state = state; } } class StateIdle extends State { constructor(sprites) { super("IDLE"); this.bird = sprites[0]; this.tuberias = [sprites[1], sprites[2]]; sprites.push(new Ready(), new TapTap()); } enter() { this.bird.velY = this.bird.gravedad = 0; this.tuberias.forEach((tuberia) => { tuberia.velocidad = 0; }); } } class StateRunnig extends State { constructor(sprites) { super("RUNNING"); this.bird = sprites[0]; this.tuberias = [sprites[1], sprites[2]]; this.suelo = sprites[3]; sprites.splice(-2); } enter() { this.bird.inicializa(); this.bird.velY = 0; this.bird.gravedad = 0.2; this.bird.nFramesAnim = 3; this.tuberias.forEach((tuberia) => { tuberia.inicializa(); tuberia.velocidad = 1; }); this.suelo.velocidad = 1; } } class StateGameOver extends State { constructor(sprites) { super("GAMEOVER"); this.bird = sprites[0]; this.tuberias = [sprites[1], sprites[2]]; this.suelo = sprites[3]; sprites.push(new GameOver(), new TapTap()); } enter() { this.bird.velY = this.bird.gravedad = 0; this.bird.nFramesAnim = 1; this.tuberias.forEach((tuberia) => { tuberia.velocidad = 0; }); this.suelo.velocidad = 0; } } class Logo { constructor() { this.logoImg = images["logo"]; this.posX = width / 2 - this.logoImg.width / 2; this.posY = height - this.logoImg.height - 20; } update() {} draw() { ctx.drawImage(this.logoImg, this.posX, this.posY); } } class Ready { constructor() { this.readyImg = images["ready"]; this.posX = width / 2 - this.readyImg.width / 2; this.posY = height / 4 - this.readyImg.height / 2; } update() {} draw() { ctx.drawImage(this.readyImg, this.posX, this.posY); } } class GameOver { constructor() { this.gameOverImg = images["gameover"]; this.posX = width / 2 - this.gameOverImg.width / 2; this.posY = height / 4 - this.gameOverImg.height / 2; } update() {} draw() { ctx.drawImage(this.gameOverImg, this.posX, this.posY); } } class TapTap { constructor() { this.tapTapImg = images["taptap"]; this.posX = width / 2 - this.tapTapImg.width / 2; this.posY = height / 2 - this.tapTapImg.height / 2; } update() {} draw() { ctx.drawImage(this.tapTapImg, this.posX, this.posY); } } class Suelo { constructor() { this.sueloImg = images["suelo"]; this.posX = 0; this.posY = height - this.sueloImg.height; this.velocidad = 1; } update() { this.posX -= this.velocidad; if (this.posX + this.sueloImg.width === 0) this.posX = 0; } draw() { ctx.drawImage(this.sueloImg, this.posX, this.posY); ctx.drawImage(this.sueloImg, this.posX + width, this.posY); } } class Tuberia { constructor(posX, tipo) { this.tuberiaImg = images["tuberias"]; this.tipo = tipo; this.width = 52; this.height = 320; this.initialPosX = posX; this.puntuada = false; this.inicializa(); } inicializa() { this.separacion = 100; this.velocidad = 0; this.posX = this.initialPosX; this.posY = Math.floor(Math.random() * (300 - 100 + 1)) + 100 - Math.floor(this.height * 2 + this.separacion) / 2; } generaPos() { this.puntuada = false; this.posX = width; this.posY = Math.floor(Math.random() * (300 - 100 + 1)) + 100 - Math.floor(this.height * 2 + this.separacion) / 2; } update() { this.posX -= this.velocidad; if (this.posX <= 0 - this.width) { this.generaPos(); } } draw() { ctx.drawImage( this.tuberiaImg, 1 * this.width, this.tipo * this.height, this.width, this.height, this.posX, this.posY, this.width, this.height ); ctx.drawImage( this.tuberiaImg, 0 * this.width, this.tipo * this.height, this.width, this.height, this.posX, this.posY + this.height + this.separacion, this.width, this.height ); } colision(bird){ if ( bird.posX + bird.width < xB || // Condición 1 bird.posX > this.posX + this.width || // Condición 2 bird.posY + hA < yB || // Condición 3 bird.posY > yB + hB // Condición 4 ) { // No hay colisión return false; } else { // Hay colisión return true; } } superada(bird) { if (bird.posX > this.posX + this.width && this.puntuada === false) { this.puntuada = true; return true; } return false; } } class Bird { constructor() { this.birdImg = images["flappybird"]; this.width = 34; this.height = 24; this.nFramesAnim = 3; this.animFrame = 0; this.gameFrame = 0; this.inicializa(); } inicializa() { this.posY = height / 2; this.posX = width / 8; this.gravedad = 0; this.velY = 0; } impulsar() { this.velY = -4; } update() { this.velY += this.gravedad; this.posY += this.velY; this.animFrame = Math.floor(this.gameFrame / 10) % this.nFramesAnim; this.gameFrame++; } draw() { if (this.velY === 0) { ctx.drawImage( this.birdImg, this.animFrame * this.width, 0, this.width, this.height, this.posX, this.posY, this.width, this.height ); return; } ctx.save(); if (this.velY > 0) { ctx.translate(this.posX + this.width / 2, this.posY + this.height / 2); ctx.rotate((30 * Math.PI) / 180); ctx.drawImage( this.birdImg, this.animFrame * this.width, 0, this.width, this.height, -this.width / 2, -this.height / 2, this.width, this.height ); } else { ctx.translate(this.posX + this.width / 2, this.posY + this.height / 2); ctx.rotate((-30 * Math.PI) / 180); ctx.drawImage( this.birdImg, this.animFrame * this.width, 0, this.width, this.height, -this.width / 2, -this.height / 2, this.width, this.height ); } ctx.restore(); } detectarColisiones(tuberias, suelo) { if (this.posY + this.height >= suelo.posY) { return true; } for (let i = 0; i < tuberias.length; i++) { const tuberia = tuberias[i]; if ( this.posX + this.width > tuberia.posX && this.posX < tuberia.posX + tuberia.width && (this.posY < tuberia.posY + tuberia.height || this.posY + this.height > tuberia.posY + tuberia.height + tuberia.separacion) ) { return true; } } return false; } pasaTuberia(tuberias) { if (tuberias[0].superada(this) || tuberias[1].superada(this)) { return true; } return false; } } function iniciarJuego() { let puntuacion = 0; ctx.font = "24px 'Press Start 2P'"; ctx.fillStyle = "white"; const sprites = [ new Bird(), new Tuberia(width + 100, 1), new Tuberia(width + 100 + width * 0.5 + 25, 0), new Suelo(), new Logo(), ]; let state = new StateIdle(sprites); state.enter(); document.addEventListener("keydown", function (event) { if (event.code === "Space") { if (state.state === "IDLE" || state.state === "GAMEOVER") { puntuacion=0; state = new StateRunnig(sprites); state.enter(); } sprites[0].impulsar(); audiosFx["flap"].play(); } }); function gameLoop(timeStamp) { ctx.clearRect(0, 0, width, height); ctx.drawImage(images["bg"], 0, 0, width, height); if ( sprites[0].detectarColisiones([sprites[1], sprites[2]], sprites[3]) && state.state !== "GAMEOVER" ) { audiosFx["gameover"].play(); console.log('paso'); state = new StateGameOver(sprites); state.enter(); } sprites.forEach((sprite) => { sprite.update(); sprite.draw(); }); if (sprites[0].pasaTuberia([sprites[1], sprites[2]])) { audiosFx["coin"].play(); puntuacion++; } ctx.fillText(puntuacion, 4, 30); requestAnimationFrame(gameLoop); } gameLoop(); } //cargarImagenes(images, iniciarJuego); cargarRecursos(images,audiosFx,iniciarJuego);