Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>2D Sword Duel Game (No Well)</title> | |
<style> | |
body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; } | |
canvas { display: block; } | |
</style> | |
</head> | |
<body> | |
<canvas id="gameCanvas"></canvas> | |
<script> | |
const canvas = document.getElementById('gameCanvas'); | |
const ctx = canvas.getContext('2d'); | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
let playerScore = 0; | |
let enemyScore = 0; | |
function createCharacter(x, y, color) { | |
return { | |
x: x, | |
y: y, | |
color: color, | |
velocity: { x: 0, y: 0 }, | |
parts: [ | |
{ x: 0, y: -30, radius: 15, color: color }, | |
{ x: 0, y: 0, radius: 20, color: color }, | |
{ x: -20, y: 0, radius: 10, color: color }, | |
{ x: 20, y: 0, radius: 10, color: color }, | |
{ x: -10, y: 40, radius: 10, color: color }, | |
{ x: 10, y: 40, radius: 10, color: color } | |
], | |
sword: { | |
length: 50, | |
angle: 0, | |
color: 'gray', | |
extending: false, | |
extendProgress: 0 | |
} | |
}; | |
} | |
const player = createCharacter(canvas.width / 4, canvas.height / 2, 'blue'); | |
const enemy = createCharacter(canvas.width * 3 / 4, canvas.height / 2, 'red'); | |
function drawCharacter(character) { | |
character.parts.forEach(part => { | |
ctx.beginPath(); | |
ctx.arc(character.x + part.x, character.y + part.y, part.radius, 0, Math.PI * 2); | |
ctx.fillStyle = part.color; | |
ctx.fill(); | |
}); | |
} | |
function drawSword(character) { | |
const extendedLength = character.sword.length + character.sword.extendProgress * 50; | |
ctx.beginPath(); | |
ctx.moveTo(character.x, character.y); | |
ctx.lineTo( | |
character.x + Math.cos(character.sword.angle) * extendedLength, | |
character.y + Math.sin(character.sword.angle) * extendedLength | |
); | |
ctx.strokeStyle = character.sword.color; | |
ctx.lineWidth = 5; | |
ctx.stroke(); | |
} | |
function drawScores() { | |
ctx.font = '20px Arial'; | |
ctx.fillStyle = 'black'; | |
ctx.fillText(`Player: ${playerScore}`, 10, 30); | |
ctx.fillText(`Enemy: ${enemyScore}`, canvas.width - 150, 30); | |
} | |
function moveCharacter(character) { | |
character.x += character.velocity.x; | |
character.y += character.velocity.y; | |
character.velocity.x *= 0.9; | |
character.velocity.y *= 0.9; | |
// Keep character within canvas bounds | |
character.x = Math.max(0, Math.min(canvas.width, character.x)); | |
character.y = Math.max(0, Math.min(canvas.height, character.y)); | |
} | |
function moveEnemy() { | |
const dx = player.x - enemy.x; | |
const dy = player.y - enemy.y; | |
const distance = Math.sqrt(dx*dx + dy*dy); | |
if (distance > 100) { | |
enemy.velocity.x += dx / distance * 0.5; | |
enemy.velocity.y += dy / distance * 0.5; | |
} | |
enemy.sword.angle = Math.atan2(dy, dx); | |
} | |
function extendSword(character) { | |
if (character.sword.extending) { | |
character.sword.extendProgress += 0.1; | |
if (character.sword.extendProgress >= 1) { | |
character.sword.extending = false; | |
} | |
} else { | |
character.sword.extendProgress = Math.max(0, character.sword.extendProgress - 0.1); | |
} | |
} | |
function getSwordTip(character) { | |
const extendedLength = character.sword.length + character.sword.extendProgress * 50; | |
return { | |
x: character.x + Math.cos(character.sword.angle) * extendedLength, | |
y: character.y + Math.sin(character.sword.angle) * extendedLength | |
}; | |
} | |
function checkSwordCollision(char1, char2) { | |
const sword1Tip = getSwordTip(char1); | |
const sword2Tip = getSwordTip(char2); | |
const distance = Math.sqrt( | |
Math.pow(sword1Tip.x - sword2Tip.x, 2) + | |
Math.pow(sword1Tip.y - sword2Tip.y, 2) | |
); | |
return distance < 10; // Assuming sword tips are within 10 pixels | |
} | |
function handleCollision(attacker, defender) { | |
const angle = Math.atan2(defender.y - attacker.y, defender.x - attacker.x); | |
attacker.velocity.x += Math.cos(angle) * 5; | |
attacker.velocity.y += Math.sin(angle) * 5; | |
defender.velocity.x -= Math.cos(angle) * 15; | |
defender.velocity.y -= Math.sin(angle) * 15; | |
if (attacker === player) { | |
playerScore++; | |
} else { | |
enemyScore++; | |
} | |
} | |
function update() { | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
moveCharacter(player); | |
moveCharacter(enemy); | |
moveEnemy(); | |
extendSword(player); | |
extendSword(enemy); | |
drawCharacter(player); | |
drawCharacter(enemy); | |
drawSword(player); | |
drawSword(enemy); | |
drawScores(); | |
if (checkSwordCollision(player, enemy)) { | |
handleCollision(player, enemy); | |
} | |
if (checkSwordCollision(enemy, player)) { | |
handleCollision(enemy, player); | |
} | |
requestAnimationFrame(update); | |
} | |
canvas.addEventListener('mousemove', (event) => { | |
player.sword.angle = Math.atan2(event.clientY - player.y, event.clientX - player.x); | |
}); | |
canvas.addEventListener('mousedown', () => { | |
player.sword.extending = true; | |
}); | |
canvas.addEventListener('mouseup', () => { | |
player.sword.extending = false; | |
}); | |
document.addEventListener('keydown', (event) => { | |
if (event.key === 'd' || event.key === 'D') { | |
player.velocity.x += Math.cos(player.sword.angle) * 2; | |
player.velocity.y += Math.sin(player.sword.angle) * 2; | |
} else if (event.key === 'a' || event.key === 'A') { | |
player.velocity.x -= Math.cos(player.sword.angle) * 2; | |
player.velocity.y -= Math.sin(player.sword.angle) * 2; | |
} | |
}); | |
update(); | |
</script> | |
</body> | |
</html> |