<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Boss Battle</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Courier New', monospace;
background-color: black;
}
canvas {
display: block;
margin: 0 auto;
}
#start-screen,
#end-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.8);
color: white;
text-align: center;
}
#start-button {
font-size: 24px;
padding: 10px 20px;
margin-top: 20px;
cursor: pointer;
}
#time {
font-size: 5vw;
color: red;
}
#message {
font-size: 2vw;
margin-top: 20px;
max-width: 80%;
}
@media (max-width: 600px) {
#time {
font-size: 10vw;
}
#message {
font-size: 4vw;
}
}
#mobile-controls {
display: none;
position: fixed;
bottom: 20px;
left: 20px;
right: 20px;
z-index: 1000;
}
#joystick-area {
width: 150px;
height: 150px;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
position: absolute;
left: 20px;
bottom: 20px;
}
#joystick {
width: 50px;
height: 50px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
position: absolute;
left: 50px;
top: 50px;
}
#shoot-button {
position: absolute;
right: 20px;
bottom: 20px;
width: 80px;
height: 80px;
background: rgba(255, 0, 0, 0.5);
border-radius: 50%;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="start-screen">
<h1>FINAL PRE MINT BOSS BATTLE</h1>
<p>DO YOU HAVE WHAT IT TAKES TO DEFEAT THE BOSS AND EARN YOURSELF A CONTRACT?</p>
<button id="start-button">Start Game</button>
</div>
<div id="end-screen" style="display: none;">
<div id="time"></div>
<div id="message">Post your results on X tagging @agooddoctorbtc to potentially sell your soul.</div>
</div>
<audio id="background-music" loop>
<source src="/content/918a68b26b77f3b6f1a286c35bd1b1c1370fc5ad92d43f15416db8ae6ea2330ci0" type="audio/mp3">
</audio>
<div id="mobile-controls">
<div id="joystick-area">
<div id="joystick"></div>
</div>
<div id="shoot-button"></div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const keys = {};
let player;
let boss;
let bullets = [];
let bossBullets = [];
let bossMoveTimer = 0;
let gameEnded = false;
let startTime;
let gameLoop;
const playerImage = new Image();
playerImage.src = '/content/7f58430bab3cf61c9712f6530de341c1c9d9ddef49824105acc8fb60867c5522i0';
const bossImage = new Image();
bossImage.src = '/content/d8bf7a28c8d39283eeded0696f58fbe76d405994862bdb996f7d6ef4bc297a80i0';
const playerBulletImage = new Image();
playerBulletImage.src = '/content/7c8ffe9220a15ba3f1fd6a146c13d93bc24a37da92d57a7ff29e7b77e02037cfi2';
const bossBulletImage = new Image();
bossBulletImage.src = '/content/7c8ffe9220a15ba3f1fd6a146c13d93bc24a37da92d57a7ff29e7b77e02037cfi1';
document.addEventListener('keydown', function(e) {
keys[e.key] = true;
});
document.addEventListener('keyup', function(e) {
keys[e.key] = false;
});
const startScreen = document.getElementById('start-screen');
const startButton = document.getElementById('start-button');
const endScreen = document.getElementById('end-screen');
const backgroundMusic = document.getElementById('background-music');
startButton.addEventListener('click', function() {
startScreen.style.display = 'none';
startTime = Date.now();
init();
backgroundMusic.play();
});
function resizeCanvas() {
const aspectRatio = canvas.width / canvas.height;
const windowAspectRatio = window.innerWidth / window.innerHeight;
let width, height;
if (windowAspectRatio > aspectRatio) {
height = window.innerHeight;
width = height * aspectRatio;
} else {
width = window.innerWidth;
height = width / aspectRatio;
}
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}
window.addEventListener('load', resizeCanvas);
window.addEventListener('resize', resizeCanvas);
class Player {
constructor() {
this.x = canvas.width / 2 - 20;
this.y = canvas.height - 70;
this.width = 40;
this.height = 40;
this.speed = 2;
this.shootTimer = 0;
this.lives = 3;
this.invincibleTimer = 0;
}
move() {
if (joystickActive) {
this.x += this.speed * joystickPos.x;
this.y += this.speed * joystickPos.y;
this.x = Math.max(0, Math.min(canvas.width - this.width, this.x));
this.y = Math.max(canvas.height * 0.25, Math.min(canvas.height - this.height, this.y));
} else {
// Existing keyboard controls
if (keys['ArrowLeft'] && this.x > 0) {
this.x -= this.speed;
}
if (keys['ArrowRight'] && this.x + this.width < canvas.width) {
this.x += this.speed;
}
if (keys['ArrowUp'] && this.y > canvas.height * 0.45) {
this.y -= this.speed;
}
if (keys['ArrowDown'] && this.y + this.height < canvas.height) {
this.y += this.speed;
}
}
}
shoot() {
if (keys[' '] || shootActive) {
if (this.shootTimer <= 0) {
bullets.push(new Bullet(this.x + this.width / 2, this.y));
this.shootTimer = 15;
}
}
if (this.shootTimer > 0) {
this.shootTimer--;
}
}
update() {
if (this.invincibleTimer > 0) {
this.invincibleTimer--;
}
}
draw() {
if (this.invincibleTimer > 0) {
if (Math.floor(this.invincibleTimer / 5) % 2 === 0) {
ctx.drawImage(playerImage, this.x, this.y, this.width, this.height);
}
} else {
ctx.drawImage(playerImage, this.x, this.y, this.width, this.height);
}
}
}
class Bullet {
constructor(x, y) {
this.x = x - 2.5;
this.y = y;
this.width = 5;
this.height = 10;
this.speed = 7;
}
update() {
this.y -= this.speed;
}
draw() {
ctx.drawImage(playerBulletImage, this.x, this.y, this.width, this.height);
}
}
class SpiralBullet {
constructor(x, y) {
this.x = x;
this.y = y;
this.radius = 5;
this.angle = 0;
this.speed = 3;
this.downwardSpeed = 1.5;
this.color = 'purple';
}
update() {
this.angle += 0.15;
this.x += Math.cos(this.angle) * this.speed;
this.y += Math.sin(this.angle) * this.speed + this.downwardSpeed;
}
draw() {
ctx.save();
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.globalCompositeOperation = 'lighter';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.restore();
}
getBoundingBox() {
return {
x: this.x - this.radius,
y: this.y - this.radius,
width: this.radius * 2,
height: this.radius * 2
};
}
}
class Boss {
constructor() {
this.x = canvas.width / 4 - 100;
this.y = 50;
this.width = 100;
this.height = 100;
this.health = 100;
this.maxHealth = 100;
this.flashTimer = 0;
this.moveSpeed = 3;
this.specialAttackTimer = 0;
}
move() {
bossMoveTimer++;
this.x += Math.sin(bossMoveTimer / 60) * this.moveSpeed;
}
shoot() {
if (bossMoveTimer % 60 === 0) {
bossBullets.push(new BossBullet(this.x + this.width / 2, this.y + this.height, 0, 7)); // Increased speed from 5 to 7
}
if (bossMoveTimer % 120 === 0) {
for (let angle = -1; angle <= 1; angle += 0.5) {
const hue = (angle + 1) * 60;
bossBullets.push(new BossBullet(this.x + this.width / 2, this.y + this.height, angle, 5, hue)); // Increased speed from 3 to 5
}
}
if (bossMoveTimer % 240 === 0) {
bossBullets.push(new SpiralBullet(this.x + this.width / 2, this.y + this.height));
}
this.specialAttackTimer++;
if (this.specialAttackTimer >= 600) {
if (Math.random() < 0.2) {
bossBullets.push(new SpecialBullet(this.x + this.width / 2, this.y + this.height));
this.specialAttackTimer = 0;
}
}
}
draw() {
if (this.flashTimer > 0) {
ctx.globalAlpha = 0.5 + Math.sin(this.flashTimer * 0.5) * 0.5;
this.flashTimer--;
}
ctx.drawImage(bossImage, this.x, this.y, this.width, this.height);
ctx.globalAlpha = 1;
}
}
class BossBullet {
constructor(x, y, angle, speed, hue = 0) {
this.x = x - 2.5;
this.y = y;
this.width = 5;
this.height = 10;
this.speed = speed;
this.angle = angle;
this.hue = hue;
}
update() {
this.x += this.angle * this.speed;
this.y += this.speed;
}
draw() {
ctx.save();
ctx.filter = `hue-rotate(${this.hue}deg)`;
ctx.drawImage(bossBulletImage, this.x, this.y, this.width, this.height);
ctx.restore();
}
}
let stars = [];
const NUM_STARS = 100;
class Star {
constructor() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.size = Math.random() * 2;
this.opacity = Math.random();
this.fadeSpeed = 0.005 + Math.random() * 0.01;
}
update() {
this.opacity += this.fadeSpeed;
if (this.opacity > 1 || this.opacity < 0) {
this.fadeSpeed = -this.fadeSpeed;
}
}
draw() {
ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity})`;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
function init() {
player = new Player();
boss = new Boss();
gameEnded = false;
bullets = [];
bossBullets = [];
bossMoveTimer = 0;
resizeCanvas();
gameLoop = requestAnimationFrame(update);
stars = [];
for (let i = 0; i < NUM_STARS; i++) {
stars.push(new Star());
}
}
function update() {
if (!gameEnded) {
updateGame();
draw();
gameLoop = requestAnimationFrame(update);
}
}
function updateGame() {
player.update();
player.move();
player.shoot();
boss.move();
boss.shoot();
bullets.forEach((bullet, index) => {
bullet.update();
if (bullet.y + bullet.height < 0) {
bullets.splice(index, 1);
}
if (rectCollision(bullet, boss)) {
bullets.splice(index, 1);
boss.health -= 1;
boss.flashTimer = 10;
if (boss.health <= 0) {
gameOver(true);
}
}
});
bossBullets.forEach((bullet, index) => {
bullet.update();
if (bullet.y > canvas.height || bullet.x < 0 || bullet.x > canvas.width) {
bossBullets.splice(index, 1);
}
});
checkCollision(player, bossBullets);
}
function draw() {
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
stars.forEach(star => {
star.update();
star.draw();
});
player.draw();
boss.draw();
ctx.fillStyle = 'green';
const healthBarWidth = 200;
ctx.fillRect(20, 20, (boss.health / boss.maxHealth) * healthBarWidth, 20);
ctx.strokeStyle = 'white';
ctx.strokeRect(20, 20, healthBarWidth, 20);
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.textAlign = 'right';
ctx.fillText('Lives: ' + player.lives, canvas.width - 20, 40);
bullets.forEach(bullet => bullet.draw());
bossBullets.forEach(bullet => {
if (bullet instanceof SpecialBullet) {
bullet.draw();
} else {
bullet.draw();
}
});
}
function rectCollision(a, b) {
return (
a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y
);
}
function checkCollision(player, bullets) {
if (player.invincibleTimer > 0) {
return;
}
for (let i = 0; i < bullets.length; i++) {
const bullet = bullets[i];
let bulletBox;
if (bullet instanceof SpiralBullet) {
bulletBox = bullet.getBoundingBox();
} else {
bulletBox = bullet;
}
if (rectCollision(player, bulletBox)) {
bullets.splice(i, 1);
player.lives--;
player.invincibleTimer = 60;
if (player.lives <= 0) {
gameOver(false);
}
break;
}
}
}
function gameOver(won) {
gameEnded = true;
cancelAnimationFrame(gameLoop);
const endTime = Date.now();
const timeElapsed = ((endTime - startTime) / 1000).toFixed(2);
if (won) {
endScreen.style.display = 'flex';
document.getElementById('time').textContent = timeElapsed;
} else {
showLoseScreen();
}
backgroundMusic.pause();
backgroundMusic.currentTime = 0;
}
function resetGame() {
startScreen.style.display = 'flex';
endScreen.style.display = 'none';
}
function handleRestart() {
document.removeEventListener('keydown', handleRestart);
init();
}
function isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
if (isMobile()) {
document.getElementById('mobile-controls').style.display = 'block';
}
const joystickArea = document.getElementById('joystick-area');
const joystick = document.getElementById('joystick');
const shootButton = document.getElementById('shoot-button');
let joystickActive = false;
let shootActive = false;
let joystickPos = {
x: 0,
y: 0
};
function handleJoystickStart(e) {
joystickActive = true;
updateJoystickPosition(e);
}
function handleJoystickMove(e) {
if (joystickActive) {
updateJoystickPosition(e);
}
}
function handleJoystickEnd() {
joystickActive = false;
joystick.style.transform = 'translate(0px, 0px)';
joystickPos = {
x: 0,
y: 0
};
}
function updateJoystickPosition(e) {
const rect = joystickArea.getBoundingClientRect();
const centerX = rect.width / 2;
const centerY = rect.height / 2;
let x, y;
if (e.touches) {
x = e.touches[0].clientX - rect.left;
y = e.touches[0].clientY - rect.top;
} else {
x = e.clientX - rect.left;
y = e.clientY - rect.top;
}
const dx = x - centerX;
const dy = y - centerY;
const distance = Math.min(rect.width / 2, Math.sqrt(dx * dx + dy * dy));
const angle = Math.atan2(dy, dx);
const joystickX = Math.cos(angle) * distance;
const joystickY = Math.sin(angle) * distance;
joystick.style.transform = `translate(${joystickX}px, ${joystickY}px)`;
joystickPos = {
x: joystickX / (rect.width / 2),
y: joystickY / (rect.height / 2)
};
}
joystickArea.addEventListener('touchstart', handleJoystickStart);
joystickArea.addEventListener('touchmove', handleJoystickMove);
joystickArea.addEventListener('touchend', handleJoystickEnd);
shootButton.addEventListener('touchstart', () => {
shootActive = true;
});
shootButton.addEventListener('touchend', () => {
shootActive = false;
});
function showLoseScreen() {
const loseScreen = document.createElement('div');
loseScreen.id = 'lose-screen';
loseScreen.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.8);
color: white;
text-align: center;
`;
loseScreen.innerHTML = `
<h2>You died. Try again?</h2>
<button id="retry-button" style="font-size: 24px; padding: 10px 20px; margin-top: 20px; cursor: pointer;">Start Game</button>
`;
document.body.appendChild(loseScreen);
document.getElementById('retry-button').addEventListener('click', function() {
document.body.removeChild(loseScreen);
init();
backgroundMusic.play();
});
}
const backgroundImage = new Image();
backgroundImage.src = '/content/f39d29543c4038130c35f49506a9dd6fa9750d93c54cd6b2b68c40522f1c8f85i0';
function draw() {
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
stars.forEach(star => {
star.update();
star.draw();
});
player.draw();
boss.draw();
ctx.fillStyle = 'green';
const healthBarWidth = 200;
ctx.fillRect(20, 20, (boss.health / boss.maxHealth) * healthBarWidth, 20);
ctx.strokeStyle = 'white';
ctx.strokeRect(20, 20, healthBarWidth, 20);
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.textAlign = 'right';
ctx.fillText('Lives: ' + player.lives, canvas.width - 20, 40);
bullets.forEach(bullet => bullet.draw());
bossBullets.forEach(bullet => {
if (bullet instanceof SpecialBullet) {
bullet.draw();
} else {
bullet.draw();
}
});
}
const specialBulletImage = new Image();
specialBulletImage.src = '/content/f39d29543c4038130c35f49506a9dd6fa9750d93c54cd6b2b68c40522f1c8f85i2';
class SpecialBullet {
constructor(x, y) {
this.x = x - 15;
this.y = y;
this.width = 30;
this.height = 30;
this.speed = 4;
this.horizontalSpeed = (Math.random() - 0.5) * 4;
}
update() {
this.y += this.speed;
this.x += this.horizontalSpeed;
}
draw() {
ctx.drawImage(specialBulletImage, this.x, this.y, this.width, this.height);
}
}
</script>
</body>
</html>
165 days ago
164 days ago
161 days ago
164 days ago
164 days ago
164 days ago
164 days ago
164 days ago
164 days ago
164 days ago
164 days ago
154 days ago
159 days ago
160 days ago
161 days ago
161 days ago
161 days ago
161 days ago
161 days ago
161 days ago
162 days ago
162 days ago
162 days ago
162 days ago
162 days ago