spinblade-tactics / script.js
Puddisnky's picture
The player must select a direction of movement. Then end the turn for the character to move
bd9f242 verified
document.addEventListener('DOMContentLoaded', () => {
// Game state
const gameState = {
playerTurn: true,
playerPosition: { x: 100, y: 100 },
selectedMove: null,
enemies: [
{ x: 300, y: 100, speed: 2, direction: 'right' },
{ x: 200, y: 200, speed: 1, direction: 'down' }
],
swordAngle: 0,
swordSpinning: false,
swordSpeed: 0,
gameLog: [],
moveConfirmed: false
};
// DOM elements
const gameCanvas = document.getElementById('gameCanvas');
const gameLog = document.getElementById('gameLog');
const turnIndicator = document.getElementById('turnIndicator');
// Movement buttons
const moveUp = document.getElementById('moveUp');
const moveDown = document.getElementById('moveDown');
const moveLeft = document.getElementById('moveLeft');
const moveRight = document.getElementById('moveRight');
const spinBlade = document.getElementById('spinBlade');
// Initialize game
initGame();
function initGame() {
renderGame();
setupControls();
logMessage("Game started! Your turn to move.");
}
function renderGame() {
// Clear canvas
gameCanvas.innerHTML = '';
// Render player
const player = document.createElement('div');
player.className = 'character';
player.style.left = `${gameState.playerPosition.x}px`;
player.style.top = `${gameState.playerPosition.y}px`;
gameCanvas.appendChild(player);
// Render sword
const sword = document.createElement('div');
sword.className = 'sword';
sword.style.left = `${gameState.playerPosition.x}px`;
sword.style.top = `${gameState.playerPosition.y + 15}px`;
sword.style.transform = `rotate(${gameState.swordAngle}deg)`;
gameCanvas.appendChild(sword);
// Render enemies
gameState.enemies.forEach(enemy => {
const enemyElement = document.createElement('div');
enemyElement.className = 'enemy';
enemyElement.style.left = `${enemy.x}px`;
enemyElement.style.top = `${enemy.y}px`;
gameCanvas.appendChild(enemyElement);
});
}
function setupControls() {
moveUp.addEventListener('click', () => selectMove(0, -30));
moveDown.addEventListener('click', () => selectMove(0, 30));
moveLeft.addEventListener('click', () => selectMove(-30, 0));
moveRight.addEventListener('click', () => selectMove(30, 0));
spinBlade.addEventListener('click', () => {
if (!gameState.moveConfirmed) {
selectMove(0, 0, true);
}
});
// Add confirm button
const confirmButton = document.createElement('button');
confirmButton.id = 'confirmMove';
confirmButton.className = 'btn-action bg-green-600 hover:bg-green-700 col-span-3';
confirmButton.innerHTML = '<i data-feather="check"></i> Confirm Move';
document.querySelector('.grid.grid-cols-3').appendChild(confirmButton);
confirmButton.addEventListener('click', confirmMove);
feather.replace();
}
function selectMove(dx, dy, isSpin = false) {
if (!gameState.playerTurn || gameState.moveConfirmed) return;
const newX = gameState.playerPosition.x + dx;
const newY = gameState.playerPosition.y + dy;
// Boundary check for moves (not needed for spin)
if (!isSpin && (newX < 0 || newX > gameCanvas.offsetWidth - 30 ||
newY < 0 || newY > gameCanvas.offsetHeight - 30)) {
logMessage("Can't move there - out of bounds!");
return;
}
gameState.selectedMove = { dx, dy, isSpin };
logMessage(isSpin ? "Spin blade selected!" : `Move to (${newX}, ${newY}) selected`);
}
function confirmMove() {
if (!gameState.playerTurn || !gameState.selectedMove || gameState.moveConfirmed) return;
gameState.moveConfirmed = true;
if (gameState.selectedMove.isSpin) {
startSpin();
} else {
gameState.playerPosition.x += gameState.selectedMove.dx;
gameState.playerPosition.y += gameState.selectedMove.dy;
renderGame();
endTurn();
}
}
function movePlayer(dx, dy) {
if (!gameState.playerTurn) return;
const newX = gameState.playerPosition.x + dx;
const newY = gameState.playerPosition.y + dy;
// Boundary check
if (newX >= 0 && newX <= gameCanvas.offsetWidth - 30 &&
newY >= 0 && newY <= gameCanvas.offsetHeight - 30) {
gameState.playerPosition.x = newX;
gameState.playerPosition.y = newY;
logMessage(`Moved to (${newX}, ${newY})`);
renderGame();
endTurn();
} else {
logMessage("Can't move there - out of bounds!");
}
}
function startSpin() {
if (!gameState.playerTurn) return;
gameState.swordSpinning = true;
gameState.swordSpeed = 10;
logMessage("Spinning blade! Enemies beware!");
endTurn();
}
function updateSpinning() {
if (gameState.swordSpinning) {
gameState.swordAngle += gameState.swordSpeed;
// Slow down over time
gameState.swordSpeed *= 0.98;
if (gameState.swordSpeed < 0.5) {
gameState.swordSpinning = false;
gameState.swordSpeed = 0;
}
// Check for collisions with enemies
checkBladeCollisions();
renderGame();
}
}
function checkBladeCollisions() {
const bladeLength = 40;
const bladeX = gameState.playerPosition.x + Math.cos(gameState.swordAngle * Math.PI / 180) * bladeLength;
const bladeY = gameState.playerPosition.y + 15 + Math.sin(gameState.swordAngle * Math.PI / 180) * bladeLength;
gameState.enemies.forEach((enemy, index) => {
const distance = Math.sqrt(
Math.pow(bladeX - (enemy.x + 15), 2) +
Math.pow(bladeY - (enemy.y + 15), 2)
);
if (distance < 20) {
// Enemy hit!
gameState.enemies.splice(index, 1);
logMessage("Enemy defeated by spinning blade!");
}
});
}
function moveEnemies() {
gameState.enemies.forEach(enemy => {
switch (enemy.direction) {
case 'up':
enemy.y = Math.max(0, enemy.y - enemy.speed);
if (enemy.y === 0) enemy.direction = 'down';
break;
case 'down':
enemy.y = Math.min(gameCanvas.offsetHeight - 30, enemy.y + enemy.speed);
if (enemy.y === gameCanvas.offsetHeight - 30) enemy.direction = 'up';
break;
case 'left':
enemy.x = Math.max(0, enemy.x - enemy.speed);
if (enemy.x === 0) enemy.direction = 'right';
break;
case 'right':
enemy.x = Math.min(gameCanvas.offsetWidth - 30, enemy.x + enemy.speed);
if (enemy.x === gameCanvas.offsetWidth - 30) enemy.direction = 'left';
break;
}
});
}
function endTurn() {
gameState.playerTurn = false;
gameState.selectedMove = null;
gameState.moveConfirmed = false;
turnIndicator.textContent = "Enemy Turn";
turnIndicator.className = "px-3 py-1 bg-red-600 rounded-full";
setTimeout(() => {
// Enemy moves
moveEnemies();
renderGame();
// Blade keeps spinning if it was activated
updateSpinning();
// Return to player turn
setTimeout(() => {
if (!gameState.swordSpinning) {
gameState.playerTurn = true;
turnIndicator.textContent = "Player Turn";
turnIndicator.className = "px-3 py-1 bg-blue-600 rounded-full";
logMessage("Your turn! Select a move.");
} else {
// If blade is still spinning, enemies get another turn
endTurn();
}
}, 500);
}, 1000);
}
function logMessage(message) {
gameState.gameLog.push(message);
if (gameState.gameLog.length > 10) gameState.gameLog.shift();
gameLog.innerHTML = gameState.gameLog.map(msg =>
`<div class="mb-1 last:mb-0">${msg}</div>`
).join('');
gameLog.scrollTop = gameLog.scrollHeight;
}
// Game loop for spinning blade
setInterval(() => {
if (gameState.swordSpinning && !gameState.playerTurn) {
updateSpinning();
}
}, 16);
});