Use Arrow Keys or WASD to move. Collect all treasures!
(() => {
// ... keep all previous constants and variables same ...
// New helper to check if diagonal move is permitted without clipping walls
function canMoveTo(x, y, fromX, fromY) {
if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) return false;
if (map[y * mapWidth + x] === TILE_WALL) return false;
// Prevent diagonal clipping: if moving diagonally, both adjacent tiles must be free
if(x !== fromX && y !== fromY){
if(map[fromY * mapWidth + x] === TILE_WALL) return false;
if(map[y * mapWidth + fromX] === TILE_WALL) return false;
}
return true;
}
// ... keep drawTile, drawMap, drawPlayer and collectTreasure functions same ...
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawMap();
drawPlayer();
if(!player.moving) {
let dirX = 0;
let dirY = 0;
if(keys['arrowup'] || keys['w']) dirY = -1;
else if(keys['arrowdown'] || keys['s']) dirY = 1;
if(keys['arrowleft'] || keys['a']) dirX = -1;
else if(keys['arrowright'] || keys['d']) dirX = 1;
const newX = player.x + dirX;
const newY = player.y + dirY;
// Only attempt move if we have input (including diagonals)
if(dirX !== 0 || dirY !== 0) {
if(canMoveTo(newX, newY, player.x, player.y)) {
player.targetX = newX;
player.targetY = newY;
player.moving = true;
player.moveProgress = 0;
}
}
} else {
player.moveProgress += 0.15;
if(player.moveProgress >= 1) {
player.x = player.targetX;
player.y = player.targetY;
player.moveProgress = 0;
player.moving = false;
collectTreasure(player.x, player.y);
}
}
if(treasuresCollected === totalTreasures) {
ctx.fillStyle = 'rgba(0,0,0,0.7)';
ctx.fillRect(0, canvas.height/2 - 40, canvas.width, 80);
ctx.fillStyle = '#fff';
ctx.font = '36px monospace';
ctx.textAlign = 'center';
ctx.fillText("You collected all treasures!", canvas.width/2, canvas.height/2);
} else {
ctx.fillStyle = '#eee';
ctx.font = '20px monospace';
ctx.textAlign = 'left';
ctx.fillText(`Treasures: ${treasuresCollected} / ${totalTreasures}`, 10, canvas.height - 10);
}
requestAnimationFrame(gameLoop);
}
gameLoop();
})();