DK2/templates/pages/world/base.php

177 lines
6.7 KiB
PHP
Raw Normal View History

<h1>World</h1>
2024-10-10 19:14:14 -05:00
<p>Use WASD keys to move the character</p>
2024-10-11 18:17:38 -05:00
<p>Current location: <span id="char_x"><?= location('x') ?></span>, <span id="char_y"><?= location('y') ?></span></p>
2024-10-11 18:17:38 -05:00
<div id="canvas-container">
<canvas id="canvas"></canvas>
</div>
2024-10-10 19:14:14 -05:00
<script>
2024-10-11 18:17:38 -05:00
const game = {
canvas: document.getElementById('canvas'),
csrf: '<?= csrf() ?>',
tiles: {
size: 32,
colors: {
0: '#fff',
1: '#f00'
2024-10-10 19:14:14 -05:00
}
}
}
2024-10-11 18:17:38 -05:00
const map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
let loc_span = {
x: document.getElementById('char_x'),
y: document.getElementById('char_y')
}
2024-10-10 19:14:14 -05:00
2024-10-11 18:17:38 -05:00
let player = { x: <?= location('x') ?>, y: <?= location('y') ?> }
let camera = { x: 0, y: 0 }
let visible = { x: 0, y: 0 }
function updateCanvasSize() {
game.canvas.width = game.canvas.clientWidth
game.canvas.height = game.canvas.clientHeight
visible.x = Math.ceil(game.canvas.width / game.tiles.size)
visible.y = Math.ceil(game.canvas.height / game.tiles.size)
updateCamera()
render()
}
2024-10-10 19:14:14 -05:00
2024-10-11 18:17:38 -05:00
function setupEventListeners() {
window.addEventListener('resize', updateCanvasSize)
window.addEventListener('keydown', handleKeyPress)
}
2024-10-10 19:14:14 -05:00
2024-10-11 18:17:38 -05:00
// Handle keyboard input
function handleKeyPress(e) {
let moved = false;
const newPos = { ...player }
2024-10-10 19:14:14 -05:00
// 0 = up, 1 = down, 2 = left, 3 = right
2024-10-11 18:17:38 -05:00
direction = {
2024-10-10 19:14:14 -05:00
'w': 0,
's': 1,
'a': 2,
2024-10-11 18:17:38 -05:00
'd': 3,
'ArrowUp': 0,
'ArrowDown': 1,
'ArrowLeft': 2,
'ArrowRight': 3
2024-10-10 19:14:14 -05:00
}[e.key];
2024-10-11 18:17:38 -05:00
if (direction !== undefined) {
// If player would move outside map bounds, return early
if (direction === 0 && player.y === 0) return;
if (direction === 1 && player.y === map.length - 1) return;
if (direction === 2 && player.x === 0) return;
if (direction === 3 && player.x === map[0].length - 1) return;
// Return early if the player is trying to move into a wall
if (direction === 0 && map[player.y - 1][player.x] === 2) return;
if (direction === 1 && map[player.y + 1][player.x] === 2) return;
if (direction === 2 && map[player.y][player.x - 1] === 2) return;
if (direction === 3 && map[player.y][player.x + 1] === 2) return;
2024-10-11 18:17:38 -05:00
// Execute a POST request to /move. If successful, the server will return a new x,y position
fetch('/move', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
body: `direction=${direction}&csrf=${game.csrf}`
}).then(response => {
if (response.ok) {
response.json().then(data => {
map[player.y][player.x] = 0
map[data.y][data.x] = 1
player = data
loc_span.x.textContent = player.x
loc_span.y.textContent = player.y
updateCamera()
render()
});
} else {
throw new Error('Failed to move character');
}
})
}
}
// Update camera position
function updateCamera() {
camera.x = player.x * game.tiles.size - canvas.width / 2;
camera.y = player.y * game.tiles.size - canvas.height / 2;
// Clamp camera to map bounds
camera.x = Math.max(0, Math.min(camera.x,
map[0].length * game.tiles.size - canvas.width));
camera.y = Math.max(0, Math.min(camera.y,
map.length * game.tiles.size - canvas.height));
}
// Render the game
function render() {
const ctx = game.canvas.getContext('2d')
ctx.clearRect(0, 0, game.canvas.width, game.canvas.height)
// Calculate visible tile range
const startTileX = Math.floor(camera.x / game.tiles.size)
const startTileY = Math.floor(camera.y / game.tiles.size)
const endTileX = startTileX + visible.x + 1
const endTileY = startTileY + visible.y + 1
// Only render visible tiles
for (let y = startTileY; y < endTileY; y++) {
if (y >= map.length) continue
for (let x = startTileX; x < endTileX; x++) {
if (x >= map[0].length) continue
const screenX = x * game.tiles.size - camera.x
const screenY = y * game.tiles.size - camera.y
if (map[y][x] === 1) {
// Draw player
ctx.fillStyle = 'red';
ctx.fillRect(screenX, screenY, game.tiles.size, game.tiles.size)
} else if (map[y][x] === 2) {
// Draw wall
ctx.fillStyle = 'black';
ctx.fillRect(screenX, screenY, game.tiles.size, game.tiles.size)
} else {
// Draw empty tile
ctx.strokeStyle = 'gray';
ctx.fillStyle = 'white';
ctx.fillRect(screenX, screenY, game.tiles.size, game.tiles.size)
ctx.strokeRect(screenX, screenY, game.tiles.size, game.tiles.size)
}
}
}
}
window.addEventListener('load', () => {
map[player.y][player.x] = 1
2024-10-11 18:17:38 -05:00
updateCanvasSize()
setupEventListeners()
render()
})
2024-10-10 19:14:14 -05:00
</script>