de unos alienígenas y finalmente encuentre todas las letras para formar la palabra "space" y volver a casa.
Space Escape
Presiona para empezar
Presiona para jugar de nuevo
// VARIABLES GLOBALES
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
const startDiv = document.querySelector('#start');
const gameOverDiv = document.querySelector('#gameover');
const resultHeader = document.querySelector('#result');
const spaceLetters = ['s', 'p', 'a', 'c', 'e'];
let player;
let girls = [];
let aliens = [];
let letters = [];
let letterIndex = 0;
let score = 0;
let gameOver = true;
let gameStarted = false;
// CLASES
class Player {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.dx = 0;
this.dy = 0;
this.speed = 3;
this.lives = 3;
this.canTeleport = true;
this.superSpeed = false;
this.superSpeedFrames = 0;
this.flickerFrames = 0;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
move() {
this.x += this.dx;
this.y += this.dy;
// Comprobar límites de la pantalla
if (this.x - this.radius < 0) {
this.x = this.radius;
} else if (this.x + this.radius > canvas.width) {
this.x = canvas.width - this.radius;
}
if (this.y - this.radius < 0) {
this.y = this.radius;
} else if (this.y + this.radius > canvas.height) {
this.y = canvas.height - this.radius;
}
}
shoot() {
if (this.superSpeed) {
return;
}
const bullet = new Bullet(this.x, this.y, this.color);
bullets.push(bullet);
}
teleport() {
if (!this.canTeleport || this.superSpeed) {
return;
}
// Teletransportar a una posición aleatoria
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
// Desactivar la habilidad durante unos segundos
this.canTeleport = false;
setTimeout(() => {
this.canTeleport = true;
}, 3000);
}
superSpeedOn() {
this.superSpeed = true;
this.superSpeedFrames = 300;
this.color = 'cyan';
}
superSpeedOff() {
this.superSpeed = false;
this.color = 'white';
}
flickerOn() {
this.flickerFrames = 120;
}
flickerOff() {
this.flickerFrames = 0;
}
}
class Girl {
constructor(x, y, radius, color, speed) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.speed = speed;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
move() {
// Calcula la distancia y ángulo entre la chica y el jugador
const dx = player.x - this.x;
const dy = player.y - this.y;
const distance = Math.sqrt(dx ** 2 + dy ** 2);
const angle = Math.atan2(dy, dx);
// Se mueve hacia el jugador
this.x += Math.cos(angle) * this.speed;
this.y += Math.sin(angle) * this.speed;
// Se asegura de que la chica no se salga de la pantalla
if (this.x - this.radius < 0 || this.x + this.radius > canvas.width) {
this.x -= Math.cos(angle) * this.speed;
}
if (this.y - this.radius < 0 || this.y + this.radius > canvas.height) {
this.y -= Math.sin(angle) * this.speed;
}
// Se asegura de que no se interponga en el movimiento del jugador
if (distance < player.radius + this.radius) {
this.x -= Math.cos(angle) * this.speed;
this.y -= Math.sin(angle) * this.speed;
// Hace daño al jugador
player.lives--;
player.flickerOn();
}
}
}
class Alien {
constructor(x, y, radius, color, speed) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.speed = speed;
this.dx = speed;
this.dy = 0;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
move() {
this.x += this.dx;
this.y += this.dy;
// Cambia de dirección si toca los límites de la pantalla
if (this.x - this.radius < 0 || this.x + this.radius > canvas.width) {
this.dx = -this.dx;
}
if (this.y - this.radius < 0 || this.y + this.radius > canvas.height) {
this.dy = -this.dy;
}
// Hace daño al jugador si lo toca
const distance = Math.sqrt((player.x - this.x) ** 2 + (player.y - this.y) ** 2);
if (distance < player.radius + this.radius) {
player.lives--;
player.flickerOn();
}
}
}
class Letter {
constructor(x, y, letter) {
this.x = x;
this.y = y;
this.letter = letter;
this.color = 'white';
this.speed = 0;
}
draw() {
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.font = 'bold 48px sans-serif';
ctx.fillStyle = this.color;
ctx.fillText(this.letter, this.x, this.y);
}
move() {
this.y += this.speed;
if (this.y > canvas.height + 50) {
this.reset();
}
const distance = Math.sqrt((player.x - this.x) ** 2 + (player.y - this.y) ** 2);
if (distance < player.radius) {
player.superSpeedOn();
this.reset();
}
}
reset() {
const direction = Math.round(Math.random()) === 0 ? -1 : 1;
this.x = Math.random() * canvas.width;
this.y = -100;
this.speed = 3 + Math.random() * 3;
this.letter = spaceLetters[letterIndex];
letterIndex = (letterIndex + 1) % spaceLetters.length;
}
}
class Bullet {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
this.dy = -5;
this.radius = 5;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
move() {
this.y += this.dy;
if (this.y < -this.radius) {
this.remove();
}
// Comprobar colisiones con chicas
for (let i = 0; i < girls.length; i++) {
const girl = girls[i];
const distance = Math.sqrt((this.x - girl.x) ** 2 + (this.y - girl.y) ** 2);
if (distance < this.radius + girl.radius) {
this.remove();
if (player.superSpeed) {
girls.splice(i, 1);
player.score++;
} else {
girl.color = 'red';
setTimeout(() => {
girl.color = 'pink';
}, 100);
}
}
}
// Comprobar colisiones con alienígenas
for (let i = 0; i < aliens.length; i++) {
const alien = aliens[i];
const distance = Math.sqrt((this.x - alien.x) ** 2 + (this.y - alien.y) ** 2);
if (distance < this.radius + alien.radius) {
this.remove();
alien.color = 'red';
setTimeout(() => {
alien.color = 'green';
}, 100);
}
}
}
remove() {
bullets.splice(bullets.indexOf(this), 1);
}
}
// FUNCIONES
function init() {
// Inicializa variables y objetos
player = new Player(canvas.width / 2, canvas.height - 50, 30, 'white');
for (let i = 0; i < 5; i++) {
girls.push(new Girl(Math.random() * canvas.width, Math.random() * canvas.height, 30, 'pink', 1));
}
for (let i = 0; i < 3; i++) {
aliens.push(new Alien(Math.random() * canvas.width, Math.random() * canvas.height, 20, 'green', 1));
}
for (let i = 0; i < 5; i++) {
letters.push(new Letter(Math.random() * canvas.width, -100, spaceLetters[i]));
}
gameOver = false;
gameStarted = true;
score = 0;
letterIndex = 0;
resultHeader.classList.remove('success', 'failure');
resultHeader.innerHTML = '';
}
function draw() {
// Borra el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Dibuja los objetos en el canvas
player.draw();
girls.forEach((girl) => girl.draw());
aliens.forEach((alien) => alien.draw());
letters.forEach((letter) => letter.draw());
bullets.forEach((bullet) => bullet.draw());
// Dibuja los datos del jugador
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
ctx.font = 'bold 16px sans-serif';
ctx.fillStyle = 'white';
ctx.fillText(`Vidas: ${player.lives}`, 10, 10);
ctx.fillText(`Puntuación: ${player.score}`, 10, 30);
// Dibuja animaciones
if (player.flickerFrames > 0) {
player.flickerFrames--;
if (player.flickerFrames % player.speed === 0) {
player.color = player.color === 'white' ? 'red' : 'white';
}
if (player.flickerFrames === 0) {
player.flickerOff();
}
}
if (player.superSpeedFrames > 0) {
player.superSpeedFrames--;
if (player.superSpeedFrames === 0) {
player.superSpeedOff();
}
}
// Comprueba el final del juego
if (player.lives < 1 || score === 5) {
gameOver = true;
gameStarted = false;
if (score === 5) {
resultHeader.classList.add('success');
resultHeader.innerHTML = '¡Ganaste!';
} else {
resultHeader.classList.add('failure');
resultHeader.innerHTML = '¡Perdiste!';
}
gameOverDiv.classList.remove('hidden');
}
}
function update() {
// Actualiza el estado de los objetos
player.move();
girls.forEach((girl) => girl.move());
aliens.forEach((alien) => alien.move());
letters.forEach((letter) => letter.move());
bullets.forEach((bullet) => bullet.move());
// Genera nuevas chicas y alienígenas aleatoriamente
if (Math.random() < 0.02) {
girls.push(new Girl(Math.random() * canvas.width, Math.random() * canvas.height, 30, 'pink', 1));
}
if (Math.random() < 0.01) {
aliens.push(new Alien(Math.random() * canvas.width, Math.random() * canvas.height, 20, 'green', 1));
}
// Genera nuevas letras aleatoriamente
if (Math.random() < 0.01) {
letters.push(new Letter(Math.random() * canvas.width, -100, spaceLetters[letterIndex]));
letterIndex = (letterIndex + 1) % spaceLetters.length;
}
// Comprueba colisiones entre chicas y jugador
for (let i = 0; i < girls.length; i++) {
const girl = girls[i];
const distance = Math.sqrt((player.x - girl.x) ** 2 + (player.y - girl.y) ** 2);
if (distance < player.radius + girl.radius) {
girls.splice(i, 1);
player.score++;
}
}
// Comprueba colisiones entre alienígenas y jugador
for (let i = 0; i < aliens.length; i++) {
const alien = aliens[i];
const distance = Math.sqrt((player.x - alien.x) ** 2 + (player.y - alien.y) ** 2);
if (distance < player.radius + alien.radius) {
aliens.splice(i, 1);
player.lives--;
player.flickerOn();
}
}
// Comprueba si el jugador ha recogido todas las letras
const levelComplete = letters.filter((letter) => letter.y > 0).every((letter) => letter.x < player.x - player.radius || letter.x > player.x + player.radius);
if (levelComplete) {
score++;
}
// Actualiza el estado del juego cada 16ms (aproximadamente 60 FPS)
if (!gameOver && gameStarted) {
requestAnimationFrame(update);
}
}
function restart() {
startDiv.classList.add('hidden');
gameOverDiv.classList.add('hidden');
init();
update();
}
// EVENTOS
canvas.addEventListener('mousemove', (event) => {
const angle = Math.atan2(event.clientY - player.y, event.clientX - player.x);
player.dx = Math.cos(angle) * player.speed;
player.dy = Math.sin(angle) * player.speed;
});
canvas.addEventListener('mousedown', () => {
player.shoot();
});
canvas.addEventListener('dblclick', () => {
player.teleport();
});
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
document.addEventListener('keydown', (event) => {
if (event.code === 'KeyW' || event.code === 'ArrowUp') {
player.dy = -player.speed;
} else if (event.code === 'KeyA' || event.code === 'ArrowLeft') {
player.dx = -player.speed;
} else if (event.code === 'KeyS' || event.code === 'ArrowDown') {
player.dy = player.speed;
} else if (event.code === 'KeyA' || event.code === 'ArrowLeft') {
player.dx = player.speed;
}
});
*This prompt didn't get me into the game this time. Plz try to generate it a few times.