Complete update to the world map
This commit is contained in:
parent
0e0a4c8e38
commit
87b29a3828
File diff suppressed because one or more lines are too long
159
public/assets/css/game.css
Normal file
159
public/assets/css/game.css
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
@import 'src/buttons.css';
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
--main-font: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #bcc6cf;
|
||||||
|
background-image: url('/assets/img/bg.jpg');
|
||||||
|
background-attachment: fixed;
|
||||||
|
background-position: center top;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
font-family: var(--main-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
main#game-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#game-ui, div#game-windows {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#game-windows {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 3;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
& > div.window {
|
||||||
|
pointer-events: auto;
|
||||||
|
background-color: #bcc6cf;
|
||||||
|
background-image: url('/assets/img/bg.jpg');
|
||||||
|
background-attachment: fixed;
|
||||||
|
background-position: center top;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
box-shadow: 0px 0px 5px black;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1rem 1rem 0.5rem 1rem;
|
||||||
|
cursor: grab;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 1rem;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding: 0 1rem 1rem 1rem;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
padding: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas#game-canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#character-hud {
|
||||||
|
width: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
span#character-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
span#character-title {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.hud-meter {
|
||||||
|
background-color: black;
|
||||||
|
height: 16px;
|
||||||
|
min-width: 100px;
|
||||||
|
border-radius: 0.1rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 0.1rem;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.hp {
|
||||||
|
background-color: #e57373;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(139, 0, 0, 0.1));
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #d32f2f #c62828 #b71c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mp {
|
||||||
|
background-color: #5a9bd4;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(60, 100, 150, 0.1));
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #4a8ab0 #3a7a9c #2a6a88;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tp {
|
||||||
|
background-color: #f4cc67;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #C59F43 #AA8326 #957321;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
@import 'buttons.css';
|
@import 'buttons.css';
|
||||||
@import 'forms.css';
|
@import 'forms.css';
|
||||||
@import 'profile.css';
|
@import 'profile.css';
|
||||||
|
@import 'game.css';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #bcc6cf;
|
background-color: #bcc6cf;
|
||||||
|
|
176
public/assets/scripts/WindowManager.js
Normal file
176
public/assets/scripts/WindowManager.js
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
The WindowManager is responsible for creation, destruction, modification and tracking of game UI windows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WindowManager
|
||||||
|
{
|
||||||
|
constructor(container)
|
||||||
|
{
|
||||||
|
this.windows = {}
|
||||||
|
this.container = container
|
||||||
|
}
|
||||||
|
|
||||||
|
updateWindow(id, content, title = '')
|
||||||
|
{
|
||||||
|
if (id in this.windows) {
|
||||||
|
let w = this.windows[id]
|
||||||
|
w.querySelector('header .title').innerHTML = title
|
||||||
|
w.querySelector('.body').innerHTML = content
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createWindow(id, content, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
createWindow(id, content, title = '')
|
||||||
|
{
|
||||||
|
// create window
|
||||||
|
let w = document.createElement('div')
|
||||||
|
w.id = `window-${id}`
|
||||||
|
w.classList.add('window')
|
||||||
|
|
||||||
|
// create header
|
||||||
|
let h = document.createElement('header')
|
||||||
|
w.appendChild(h)
|
||||||
|
|
||||||
|
// create header title
|
||||||
|
let ht = document.createElement('span')
|
||||||
|
ht.classList.add('title')
|
||||||
|
ht.innerHTML = title
|
||||||
|
h.appendChild(ht)
|
||||||
|
|
||||||
|
// create close button
|
||||||
|
ht.insertAdjacentHTML('afterend', `
|
||||||
|
<svg class="close" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/>
|
||||||
|
</svg>
|
||||||
|
`)
|
||||||
|
h.querySelector('svg').addEventListener('click', () => {
|
||||||
|
this.windows[id].remove()
|
||||||
|
delete this.windows[id]
|
||||||
|
})
|
||||||
|
|
||||||
|
// create body
|
||||||
|
let b = document.createElement('div')
|
||||||
|
b.classList.add('body')
|
||||||
|
b.innerHTML = content
|
||||||
|
w.appendChild(b)
|
||||||
|
|
||||||
|
// track window and add it to the container
|
||||||
|
this.makeWindowDraggable(w, this.container)
|
||||||
|
this.windows[id] = w
|
||||||
|
this.container.appendChild(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
makeWindowDraggable(w, c)
|
||||||
|
{
|
||||||
|
const header = w.querySelector('header');
|
||||||
|
if (!header) return;
|
||||||
|
|
||||||
|
let isDragging = false;
|
||||||
|
let currentX;
|
||||||
|
let currentY;
|
||||||
|
let initialX;
|
||||||
|
let initialY;
|
||||||
|
|
||||||
|
header.addEventListener('mousedown', startDragging);
|
||||||
|
document.addEventListener('mousemove', drag);
|
||||||
|
document.addEventListener('mouseup', stopDragging);
|
||||||
|
|
||||||
|
w.addEventListener('mousedown', () => this.bringToFront(w));
|
||||||
|
|
||||||
|
function startDragging(e)
|
||||||
|
{
|
||||||
|
isDragging = true;
|
||||||
|
initialX = e.clientX - w.offsetLeft;
|
||||||
|
initialY = e.clientY - w.offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag(e)
|
||||||
|
{
|
||||||
|
if (!isDragging) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
currentX = e.clientX - initialX;
|
||||||
|
currentY = e.clientY - initialY;
|
||||||
|
|
||||||
|
// Get viewport dimensions
|
||||||
|
const viewportWidth = window.innerWidth;
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// Get window dimensions
|
||||||
|
const windowRect = w.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Constrain to viewport bounds
|
||||||
|
// Left edge
|
||||||
|
currentX = Math.max(0, currentX);
|
||||||
|
// Right edge
|
||||||
|
currentX = Math.min(viewportWidth - windowRect.width, currentX);
|
||||||
|
// Top edge
|
||||||
|
currentY = Math.max(0, currentY);
|
||||||
|
// Bottom edge
|
||||||
|
currentY = Math.min(viewportHeight - windowRect.height, currentY);
|
||||||
|
|
||||||
|
// Apply the constrained position
|
||||||
|
w.style.left = currentX + 'px';
|
||||||
|
w.style.top = currentY + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopDragging()
|
||||||
|
{
|
||||||
|
isDragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle window resize
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
// Get current position and dimensions
|
||||||
|
const rect = w.getBoundingClientRect();
|
||||||
|
const viewportWidth = window.innerWidth;
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// Adjust position if window is outside viewport after resize
|
||||||
|
let newX = parseInt(w.style.left);
|
||||||
|
let newY = parseInt(w.style.top);
|
||||||
|
|
||||||
|
// Constrain to new viewport bounds
|
||||||
|
newX = Math.min(Math.max(0, newX), viewportWidth - rect.width);
|
||||||
|
newY = Math.min(Math.max(0, newY), viewportHeight - rect.height);
|
||||||
|
|
||||||
|
w.style.left = newX + 'px';
|
||||||
|
w.style.top = newY + 'px';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeZIndices()
|
||||||
|
{
|
||||||
|
const array = Array.from(this.windows);
|
||||||
|
array.sort((a, b) => (parseInt(a.style.zIndex) || 0) - (parseInt(b.style.zIndex) || 0));
|
||||||
|
|
||||||
|
// Reassign z-indices starting from 1
|
||||||
|
array.forEach((win, index) => {
|
||||||
|
win.style.zIndex = index + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return array.length + 1; // Return next available z-index
|
||||||
|
}
|
||||||
|
|
||||||
|
bringToFront(windowElement)
|
||||||
|
{
|
||||||
|
const currentMax = Math.max(...Object.values(this.windows)
|
||||||
|
.map(w => parseInt(w.style.zIndex) || 0));
|
||||||
|
|
||||||
|
if (parseInt(windowElement.style.zIndex) >= currentMax) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If z-index is getting too high, normalize all z-indices
|
||||||
|
if (currentMax > 10000) {
|
||||||
|
const newZ = this.normalizeZIndices();
|
||||||
|
windowElement.style.zIndex = newZ;
|
||||||
|
} else {
|
||||||
|
windowElement.style.zIndex = currentMax + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,11 @@ $r->get('/settings', 'settings_controller_get');
|
||||||
*/
|
*/
|
||||||
$r->get('/auctions', 'auctions_controller_get');
|
$r->get('/auctions', 'auctions_controller_get');
|
||||||
|
|
||||||
|
/*
|
||||||
|
UI
|
||||||
|
*/
|
||||||
|
router_post($r, '/ui/stats', 'ui_contoller_stats_post');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Testing
|
Testing
|
||||||
*/
|
*/
|
||||||
|
@ -91,8 +96,3 @@ stopwatch_stop('handler');
|
||||||
Cleanup
|
Cleanup
|
||||||
*/
|
*/
|
||||||
clear_flashes();
|
clear_flashes();
|
||||||
|
|
||||||
/*
|
|
||||||
Stopwatch
|
|
||||||
*/
|
|
||||||
if (env('debug')) echo c_debug_stopwatch();
|
|
||||||
|
|
|
@ -25,12 +25,13 @@ require_once SRC . '/models/session.php';
|
||||||
require_once SRC . '/models/token.php';
|
require_once SRC . '/models/token.php';
|
||||||
|
|
||||||
// Controllers
|
// Controllers
|
||||||
require_once SRC . '/controllers/char.php';
|
require_once SRC . '/controller/char.php';
|
||||||
require_once SRC . '/controllers/auth.php';
|
require_once SRC . '/controller/auth.php';
|
||||||
require_once SRC . '/controllers/world.php';
|
require_once SRC . '/controller/world.php';
|
||||||
require_once SRC . '/controllers/settings.php';
|
require_once SRC . '/controller/settings.php';
|
||||||
require_once SRC . '/controllers/auctions.php';
|
require_once SRC . '/controller/auctions.php';
|
||||||
require_once SRC . '/controllers/profile.php';
|
require_once SRC . '/controller/profile.php';
|
||||||
|
require_once SRC . '/controller/ui.php';
|
||||||
|
|
||||||
spl_autoload_register(function (string $class) {
|
spl_autoload_register(function (string $class) {
|
||||||
if (array_key_exists($class, CLASS_MAP)) require_once SRC . CLASS_MAP[$class];
|
if (array_key_exists($class, CLASS_MAP)) require_once SRC . CLASS_MAP[$class];
|
||||||
|
|
7
src/controllers/ui.php
Normal file
7
src/controllers/ui.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function ui_contoller_stats_post()
|
||||||
|
{
|
||||||
|
auth_only_and_must_have_character(); ajax_only(); csrf_ensure();
|
||||||
|
echo c_profile_stats(char());
|
||||||
|
}
|
|
@ -6,8 +6,7 @@
|
||||||
function world_controller_get()
|
function world_controller_get()
|
||||||
{
|
{
|
||||||
auth_only_and_must_have_character();
|
auth_only_and_must_have_character();
|
||||||
$GLOBALS['active_nav_tab'] = 'world';
|
echo render('layouts/game');
|
||||||
echo page('world/base');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
<h4>Stats</h4>
|
<div class="cell"><span class="label">Max HP</span> <?= abb_num($char->m_hp) ?></div>
|
||||||
<div class="grid">
|
<div class="cell"><span class="label">Max MP</span> <?= abb_num($char->m_mp) ?></div>
|
||||||
<div class="cell"><span class="label">Max HP</span> <?= abb_num($char->m_hp) ?></div>
|
<div class="cell"><span class="label">Power</span> <?= abb_num($char->pow) ?></div>
|
||||||
<div class="cell"><span class="label">Max MP</span> <?= abb_num($char->m_mp) ?></div>
|
<div class="cell"><span class="label">Accuracy</span> <?= abb_num($char->acc) ?></div>
|
||||||
<div class="cell"><span class="label">Power</span> <?= abb_num($char->pow) ?></div>
|
<div class="cell"><span class="label">Penetration</span> <?= abb_num($char->pen) ?></div>
|
||||||
<div class="cell"><span class="label">Accuracy</span> <?= abb_num($char->acc) ?></div>
|
<div class="cell"><span class="label">Focus</span> <?= abb_num($char->foc) ?></div>
|
||||||
<div class="cell"><span class="label">Penetration</span> <?= abb_num($char->pen) ?></div>
|
<div class="cell"><span class="label">Toughness</span> <?= abb_num($char->tou) ?></div>
|
||||||
<div class="cell"><span class="label">Focus</span> <?= abb_num($char->foc) ?></div>
|
<div class="cell"><span class="label">Armor</span> <?= abb_num($char->arm) ?></div>
|
||||||
<div class="cell"><span class="label">Toughness</span> <?= abb_num($char->tou) ?></div>
|
<div class="cell"><span class="label">Resist</span> <?= abb_num($char->res) ?></div>
|
||||||
<div class="cell"><span class="label">Armor</span> <?= abb_num($char->arm) ?></div>
|
<div class="cell"><span class="label">Precision</span> <?= abb_num($char->pre) ?></div>
|
||||||
<div class="cell"><span class="label">Resist</span> <?= abb_num($char->res) ?></div>
|
<div class="cell"><span class="label">Ferocity</span> <?= abb_num($char->fer) ?></div>
|
||||||
<div class="cell"><span class="label">Precision</span> <?= abb_num($char->pre) ?></div>
|
<div class="cell"><span class="label">Luck</span> <?= abb_num($char->luck) ?></div>
|
||||||
<div class="cell"><span class="label">Ferocity</span> <?= abb_num($char->fer) ?></div>
|
|
||||||
<div class="cell"><span class="label">Luck</span> <?= abb_num($char->luck) ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
325
templates/layouts/game.php
Normal file
325
templates/layouts/game.php
Normal file
|
@ -0,0 +1,325 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Dragon Knight</title>
|
||||||
|
<link rel="stylesheet" href="/assets/css/game.css">
|
||||||
|
<script src="/assets/scripts/htmx.js"></script>
|
||||||
|
<script src="/assets/scripts/WindowManager.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main id="game-container">
|
||||||
|
<div id="game-ui">
|
||||||
|
<section id="character-hud">
|
||||||
|
<span id="character-name"><?= char()->name ?></span>
|
||||||
|
<span id="character-title">L<?= char()->level ?> <?= char()->title()['name'] ?></span>
|
||||||
|
|
||||||
|
<div class="hud-meter">
|
||||||
|
<div class="hp" style="width: <?= percent(char()->hp, char()->m_hp) ?>%"></div>
|
||||||
|
<!--<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Health<br><?= char()->hp ?> / <?= char()->m_hp ?>"></div>-->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hud-meter">
|
||||||
|
<div class="mp" style="width: <?= percent(char()->mp, char()->m_mp) ?>%"></div>
|
||||||
|
<!--<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Mana<br><?= char()->mp ?> / <?= char()->m_mp ?>"></div>-->
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="menu">
|
||||||
|
<button id="stats-button" class="ui button primary">Stats</button>
|
||||||
|
<button id="rand-button" class="ui button primary">Rand</button>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="game-windows"></div>
|
||||||
|
|
||||||
|
<canvas id="game-canvas"></canvas>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const csrf = '<?= csrf() ?>'
|
||||||
|
let WM = new WindowManager(document.getElementById('game-windows'))
|
||||||
|
|
||||||
|
const statsButton = document.getElementById('stats-button')
|
||||||
|
const randButton = document.getElementById('rand-button')
|
||||||
|
|
||||||
|
statsButton.addEventListener('click', function () {
|
||||||
|
fetch('/ui/stats', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
|
},
|
||||||
|
body: `csrf=${csrf}`
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.text()
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to move character');
|
||||||
|
}
|
||||||
|
}).then(text => {
|
||||||
|
WM.updateWindow('stats', text, 'Stats')
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
randButton.addEventListener('click', function () {
|
||||||
|
WM.updateWindow('rand', generateRandomString(32), 'Random')
|
||||||
|
})
|
||||||
|
|
||||||
|
function generateRandomString(length = 8) {
|
||||||
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * characters.length));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const game = {
|
||||||
|
canvas: document.getElementById('game-canvas'),
|
||||||
|
tiles: {
|
||||||
|
size: 32,
|
||||||
|
img: new Image(),
|
||||||
|
cols: 3
|
||||||
|
},
|
||||||
|
sprites: {
|
||||||
|
size: 32,
|
||||||
|
img: new Image(),
|
||||||
|
cols: 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 player = {
|
||||||
|
location: { x: <?= location('x') ?>, y: <?= location('y') ?> },
|
||||||
|
current: { x: <?= location('x') ?>, y: <?= location('y') ?> },
|
||||||
|
target: { x: <?= location('x') ?>, y: <?= location('y') ?> },
|
||||||
|
char: 23, sprite: { x: 0, y: 0 },
|
||||||
|
tweenDuration: 0.2, // seconds
|
||||||
|
tweenProgress: 0
|
||||||
|
}
|
||||||
|
let camera = { x: 0, y: 0 }
|
||||||
|
let visible = { x: 0, y: 0 }
|
||||||
|
|
||||||
|
game.tiles.img.src = '/assets/img/world/tiles.jpg';
|
||||||
|
game.sprites.img.src = '/assets/img/world/rogues.png';
|
||||||
|
|
||||||
|
let lastFrameTime = 0;
|
||||||
|
let fps = 0;
|
||||||
|
|
||||||
|
let debounce = false;
|
||||||
|
|
||||||
|
function getPlayerSprite() {
|
||||||
|
let col = player.char % game.sprites.cols
|
||||||
|
let row = Math.floor(player.char / game.sprites.cols)
|
||||||
|
player.sprite = { x: col * game.sprites.size, y: row * game.sprites.size }
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupEventListeners() {
|
||||||
|
window.addEventListener('resize', updateCanvasSize)
|
||||||
|
window.addEventListener('keydown', handleKeyPress)
|
||||||
|
window.addEventListener('keyup', () => debounce = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle keyboard input
|
||||||
|
function handleKeyPress(e) {
|
||||||
|
if (debounce) return;
|
||||||
|
debounce = true;
|
||||||
|
let moved = false;
|
||||||
|
const newPos = { ...player }
|
||||||
|
|
||||||
|
// 0 = up, 1 = down, 2 = left, 3 = right
|
||||||
|
direction = {
|
||||||
|
'w': 0,
|
||||||
|
's': 1,
|
||||||
|
'a': 2,
|
||||||
|
'd': 3,
|
||||||
|
'ArrowUp': 0,
|
||||||
|
'ArrowDown': 1,
|
||||||
|
'ArrowLeft': 2,
|
||||||
|
'ArrowRight': 3
|
||||||
|
}[e.key];
|
||||||
|
|
||||||
|
// Direction vectors: [up, down, left, right]
|
||||||
|
const dx = [0, 0, -1, 1];
|
||||||
|
const dy = [-1, 1, 0, 0];
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
const newX = player.location.x + dx[direction];
|
||||||
|
const newY = player.location.y + dy[direction];
|
||||||
|
|
||||||
|
if (direction !== undefined) {
|
||||||
|
// Check if the new position is outside the map bounds
|
||||||
|
if (newX < 0 || newX >= map[0].length || newY < 0 || newY >= map.length) return;
|
||||||
|
|
||||||
|
if (map[newY][newX] !== 0) return;
|
||||||
|
|
||||||
|
// 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=${csrf}`
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
response.json().then(data => {
|
||||||
|
player.location = { x: data.x, y: data.y }
|
||||||
|
player.target = { x: data.x, y: data.y }
|
||||||
|
player.tweenProgress = 0
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to move character');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update camera position
|
||||||
|
function updateCamera() {
|
||||||
|
camera.x = player.current.x * game.tiles.size - game.canvas.width / 2;
|
||||||
|
camera.y = player.current.y * game.tiles.size - game.canvas.height / 2;
|
||||||
|
|
||||||
|
// Clamp camera to map bounds
|
||||||
|
camera.x = Math.max(0, Math.min(camera.x,
|
||||||
|
map[0].length * game.tiles.size - game.canvas.width));
|
||||||
|
camera.y = Math.max(0, Math.min(camera.y,
|
||||||
|
map.length * game.tiles.size - game.canvas.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
function lerp(start, end, t) {
|
||||||
|
return start + (end - start) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the game
|
||||||
|
function render(t) {
|
||||||
|
const ctx = game.canvas.getContext('2d')
|
||||||
|
|
||||||
|
// Calculate FPS
|
||||||
|
if (lastFrameTime) {
|
||||||
|
const delta = (t - lastFrameTime) / 1000;
|
||||||
|
fps = Math.round(1 / delta);
|
||||||
|
}
|
||||||
|
lastFrameTime = t;
|
||||||
|
|
||||||
|
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 = Math.round(x * game.tiles.size - camera.x)
|
||||||
|
const screenY = Math.round(y * game.tiles.size - camera.y)
|
||||||
|
|
||||||
|
ctx.drawImage(game.tiles.img, map[y][x] * game.tiles.size, 0, game.tiles.size, game.tiles.size,
|
||||||
|
screenX, screenY, game.tiles.size, game.tiles.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tween player position
|
||||||
|
if (player.tweenProgress < 1) {
|
||||||
|
player.tweenProgress += 1 / player.tweenDuration / 60
|
||||||
|
player.current.x = lerp(player.current.x, player.target.x, player.tweenProgress)
|
||||||
|
player.current.y = lerp(player.current.y, player.target.y, player.tweenProgress)
|
||||||
|
} else {
|
||||||
|
player.current = { x: player.current.x, y: player.current.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCamera()
|
||||||
|
|
||||||
|
// Render the player on top of the map using their current position
|
||||||
|
const playerX = Math.round((player.current.x * game.tiles.size) - camera.x)
|
||||||
|
const playerY = Math.round((player.current.y * game.tiles.size) - camera.y)
|
||||||
|
ctx.drawImage(game.sprites.img, player.sprite.x, player.sprite.y, game.sprites.size, game.sprites.size,
|
||||||
|
playerX, playerY, game.sprites.size, game.sprites.size)
|
||||||
|
|
||||||
|
// Render FPS counter
|
||||||
|
ctx.fillStyle = 'white';
|
||||||
|
ctx.font = '16px Arial';
|
||||||
|
ctx.fillText(`FPS: ${fps}`, game.canvas.width - 70, 20);
|
||||||
|
|
||||||
|
requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
getPlayerSprite()
|
||||||
|
updateCanvasSize()
|
||||||
|
setupEventListeners()
|
||||||
|
requestAnimationFrame(render)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user