junkerstock
 ccc0.0.18 

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Snake Game (Score & Compass)</title>
<style>
body {
background-color: #111;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
color: white;
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
touch-action: none; user-select: none; -webkit-user-select: none;
}

/* スコアボード */
#scoreBoard {
font-size: 18px; /* 項目が増えたので少し小さく */
margin-bottom: 10px;
z-index: 20;
text-shadow: 2px 2px 0 #000;
pointer-events: none;
color: #fff;
font-weight: bold;
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
width: 100%;
}
.stat-item { white-space: nowrap; }
.label-score { color: #d87093; } /* SCORE: PaleVioletRed */
.label-gold { color: #ffd700; } /* GOLD: Gold */
.label-garde { color: #00ffcc; } /* GARDE: TealAccent */
.label-home { color: #aaa; } /* HOME: Gray */

.stat-val { color: white; margin-left: 2px; }

/* 矢印は目立つように少し大きく */
#compassVal {
color: #ff9900;
font-weight: 900;
font-size: 22px;
letter-spacing: -2px; /* 矢印をくっつける */
}

canvas {
border: 4px solid #555;
background-color: #0a0a0a;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.8);
border-radius: 8px;
max-width: 98vw;
max-height: 80vh;
object-fit: contain;
z-index: 10;
}
#gameOverScreen {
display: none;
position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%);
text-align: center;
background-color: rgba(0, 0, 0, 0.95);
padding: 30px; border: 2px solid #d87093; /* Score色に合わせる */
z-index: 30; min-width: 240px; border-radius: 10px;
}
#replayBtn {
padding: 15px 20px; font-size: 20px; cursor: pointer;
background-color: #ffd700; border: none; width: 100%;
border-radius: 5px; font-weight: bold; margin-top: 20px;
color: #000;
}
#statusMessage {
position: absolute; bottom: 5%;
color: #fff; font-size: 18px; font-weight: bold;
text-align: center; width: 100%;
text-shadow: 2px 2px 4px #000;
z-index: 20; pointer-events: none;
}

#shopMenu {
display: none;
position: absolute;
bottom: 12%;
z-index: 40;
background: rgba(0, 0, 0, 0.9);
padding: 15px;
border: 2px solid #ffd700;
border-radius: 8px;
text-align: center;
display: flex;
flex-direction: column;
gap: 8px;
}
.shop-btn {
background: #333; color: white;
border: 1px solid #555; padding: 10px 15px;
font-family: monospace; font-weight: bold; font-size: 14px;
cursor: pointer; border-radius: 4px;
width: 260px;
transition: all 0.1s;
}
.shop-btn:active { transform: scale(0.98); }
.shop-btn:disabled { background: #222; color: #555; border-color: #333; cursor: not-allowed; }

.btn-garde { border-color: #00ffcc; color: #00ffcc; }
.btn-garde:hover:not(:disabled) { background: #004433; }

.btn-mode { border-color: #ffcc00; color: #ffcc00; }
.btn-mode:hover:not(:disabled) { background: #443300; }

.btn-active-mode { background: #ffcc00 !important; color: black !important; }

</style>
</head>
<body>

<div id="scoreBoard">
<div class="stat-item"><span class="label-score">SCORE:</span><span id="totalScoreVal" class="stat-val">0</span></div>
<div class="stat-item"><span class="label-gold">GOLD:</span><span id="goldVal" class="stat-val">0</span></div>
<div class="stat-item"><span class="label-garde">GARDE:</span><span id="gardeVal" class="stat-val">0</span></div>
<div class="stat-item"><span class="label-home">HOME:</span><span id="compassVal" class="stat-val">🏠</span></div>
</div>

<canvas id="gameCanvas"></canvas>

<div id="shopMenu">
<div style="color:#aaa; font-size:12px; margin-bottom:5px;">SHOP & STATUS</div>
<button id="buyGardeBtn" class="shop-btn btn-garde" onclick="buyGarde()">GARDE + : 100 G</button>
<button id="buyWide1Btn" class="shop-btn btn-mode" onclick="buyMode('medium')">WIDE+1 : 50 G</button>
<button id="buyWide2Btn" class="shop-btn btn-mode" onclick="buyMode('small')">WIDE+2 : 70 G</button>
</div>

<div id="statusMessage">家(中央)で待機中...<br>矢印キーで出発</div>

<div id="gameOverScreen">
<h2 style="color:red; margin:0 0 10px 0;">GAME OVER</h2>
<p style="font-size:14px; color:#ccc; margin:0;">FINAL SCORE</p>
<p style="font-size:32px; font-weight:bold; color:#d87093; margin:10px 0;"><span id="finalTotalScore">0</span></p>
<button id="replayBtn">REPLAY</button>
</div>

<script>
let canvas, ctx;
let gameInterval;

const WORLD_SIZE_FIXED = 60;
const levels = {
small: { gs: 20, viewTiles: 35 },
medium: { gs: 40, viewTiles: 19 },
huge: { gs: 80, viewTiles: 9 }
};

const COST_GARDE = 100;
const COST_WIDE1 = 50;
const COST_WIDE2 = 70;

let currentConfigKey = 'huge';
let gs, viewTiles;
let worldSize = WORLD_SIZE_FIXED;
let targetFoodCount = 30;

let homeX, homeY;

// アセット
const assets = {
head: { src: 'head.png', img: new Image(), loaded: false, fallback: null },
body: { src: 'body.png', img: new Image(), loaded: false, fallback: null },
food: { src: 'food.png', img: new Image(), loaded: false, fallback: null },
obstacle: { src: 'obstacle.png', img: new Image(), loaded: false, fallback: null },
house: { src: 'house.png', img: new Image(), loaded: false, fallback: null },
wall: { src: 'wall.png', img: new Image(), loaded: false, fallback: null }
};

const baseSize = 80;

function createFallbackGraphic(type) {
const c = document.createElement('canvas');
c.width = baseSize; c.height = baseSize;
const x = c.getContext('2d');
const s = baseSize;

if (type === 'head') {
x.fillStyle = "#228B22"; x.fillRect(0, 0, s, s);
x.fillStyle = "white";
x.fillRect(s*0.2, s*0.2, s*0.25, s*0.25); x.fillRect(s*0.55, s*0.2, s*0.25, s*0.25);
x.fillStyle = "black";
x.fillRect(s*0.25, s*0.25, s*0.1, s*0.1); x.fillRect(s*0.6, s*0.25, s*0.1, s*0.1);
}
else if (type === 'body') {
x.fillStyle = "#32CD32"; x.fillRect(0, 0, s, s);
x.strokeStyle = "#228B22"; x.lineWidth = s * 0.05;
x.strokeRect(s*0.02, s*0.02, s*0.96, s*0.96);
}
else if (type === 'food') {
x.beginPath(); x.arc(s/2, s/2, s/2 - (s*0.1), 0, Math.PI*2);
x.fillStyle = "#ffd700"; x.fill();
x.lineWidth = s * 0.05; x.strokeStyle = "orange"; x.stroke();
}
else if (type === 'obstacle') {
x.fillStyle = "#cc0000"; x.fillRect(0, 0, s, s);
x.strokeStyle = "#550000"; x.lineWidth = s * 0.08;
x.strokeRect(s*0.05, s*0.05, s*0.9, s*0.9);
x.beginPath(); x.strokeStyle = "white"; x.lineWidth = s * 0.08;
x.moveTo(s*0.2, s*0.2); x.lineTo(s*0.8, s*0.8);
x.moveTo(s*0.8, s*0.2); x.lineTo(s*0.2, s*0.8); x.stroke();
}
else if (type === 'house') {
x.fillStyle = "#8B4513";
x.fillRect(s*0.1, s*0.3, s*0.8, s*0.6);
x.fillStyle = "#FFD700";
x.beginPath();
x.moveTo(s*0.05, s*0.35); x.lineTo(s*0.5, s*0.05); x.lineTo(s*0.95, s*0.35);
x.fill();
x.fillStyle = "#444";
x.fillRect(s*0.4, s*0.6, s*0.2, s*0.3);
}
else if (type === 'wall') {
x.fillStyle = "#555"; x.fillRect(0, 0, s, s);
x.fillStyle = "#777"; x.fillRect(0, 0, s, s*0.1); x.fillRect(0, 0, s*0.1, s);
x.fillStyle = "#333"; x.fillRect(0, s*0.9, s, s*0.1); x.fillRect(s*0.9, 0, s*0.1, s);
x.strokeStyle = "#222"; x.strokeRect(s*0.2, s*0.2, s*0.6, s*0.6);
}
return c;
}

function initAssets() {
Object.keys(assets).forEach(type => {
assets[type].fallback = createFallbackGraphic(type);
assets[type].img.onload = () => { assets[type].loaded = true; };
assets[type].img.src = assets[type].src;
});
}
function getAsset(type) { return assets[type].loaded ? assets[type].img : assets[type].fallback; }

let px, py;
let xv, yv;
let trail;
let tail;

// ★スコア管理
let gold; // 現在の所持金(消費可能)
let totalScore; // 累積スコア(消費不可・ゲームオーバー時に表示)

let garde;
let foods = [];
let obstacles = [];
let walls = [];
let isGameOver = false;
let isResting = true;
let animFrame = 0;
let touchStartX = 0;
let touchStartY = 0;
let deliverySequence = 1;

let hitStopActive = false;

window.onload = function() {
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");

initAssets();

document.addEventListener("keydown", keyPush);
document.addEventListener("touchstart", handleTouchStart, {passive: false});
document.addEventListener("touchend", handleTouchEnd, {passive: false});
document.getElementById("replayBtn").addEventListener("click", () => resetGame());

resetGame();
}

function applyConfig(key) {
currentConfigKey = key;
const cfg = levels[key];
gs = cfg.gs;
viewTiles = cfg.viewTiles;

canvas.width = viewTiles * gs;
canvas.height = viewTiles * gs;

updateUI();
}

function initMapWalls() {
walls = [];
for (let x = 0; x < worldSize; x++) {
for (let y = 0; y < worldSize; y++) {
if (x === 0 || x === worldSize - 1 || y === 0 || y === worldSize - 1) {
walls.push({x: x, y: y});
}
}
}
}

function resetGame() {
homeX = Math.floor(worldSize / 2);
homeY = Math.floor(worldSize / 2);

px = homeX;
py = homeY;
xv = 0; yv = 0;
trail = [];
obstacles = [];
foods = [];
tail = 0;

gold = 0; // リセット
totalScore = 0; // リセット

garde = 0;
deliverySequence = 1;
isGameOver = false;
isResting = true;
animFrame = 0;
hitStopActive = false;

initMapWalls();
applyConfig('huge');

for(let i=0; i<targetFoodCount; i++) {
spawnFood();
}

updateUI();
updateCompass(); // 初期表示
updateStatus("家で待機中...<br>矢印キーで出発");

document.getElementById("gameOverScreen").style.display = "none";
document.getElementById("statusMessage").style.visibility = "visible";
document.getElementById("shopMenu").style.display = "flex";

clearInterval(gameInterval);
gameInterval = setInterval(game, 1000 / 6);
}

function addScore(amount) {
gold += amount;
totalScore += amount; // 累積スコアも加算
}

// --- ショップ機能 ---
function buyGarde() {
if (gold >= COST_GARDE) {
gold -= COST_GARDE; // Goldのみ減る
garde++;
updateUI();
updateStatus(`強化完了! GARDE: ${garde}`);
}
}

function buyMode(modeKey) {
let cost = (modeKey === 'medium') ? COST_WIDE1 : COST_WIDE2;

if (currentConfigKey === modeKey) {
updateStatus("既にこのモードです");
return;
}

if (gold >= cost) {
gold -= cost; // Goldのみ減る
applyConfig(modeKey);
updateUI();
updateStatus(`視界拡張完了! (${modeKey.toUpperCase()})`);
}
}
// ------------------

function isNearPlayer(x, y) {
const safeZone = Math.ceil(levels['huge'].viewTiles / 2) + 2;
if (Math.abs(x - px) < safeZone && Math.abs(y - py) < safeZone) return true;
return false;
}

function isOccupied(x, y) {
if (x === homeX && y === homeY) return true;
if (isPositionOnSnake(x, y)) return true;
if (x === px && y === py) return true;
for (let f of foods) if (f.x === x && f.y === y) return true;
for (let obs of obstacles) if (obs.x === x && obs.y === y) return true;
for (let w of walls) if (w.x === x && w.y === y) return true;
return false;
}

function spawnFood() {
let fx, fy; let attempt = 0;
do {
fx = Math.floor(Math.random() * worldSize);
fy = Math.floor(Math.random() * worldSize);
attempt++; if (attempt > 1000) break;
} while(isOccupied(fx, fy) || isNearPlayer(fx, fy));
foods.push({x: fx, y: fy});
}

function spawnObstacle() {
let ox, oy; let attempt = 0;
do {
ox = Math.floor(Math.random() * worldSize);
oy = Math.floor(Math.random() * worldSize);
attempt++; if (attempt > 1000) return;
} while(isOccupied(ox, oy) || isNearPlayer(ox, oy));
obstacles.push({x: ox, y: oy});
}

// ★コンパス更新機能
function updateCompass() {
const el = document.getElementById("compassVal");

// 家にいる場合
if (px === homeX && py === homeY) {
el.innerText = "🏠";
return;
}

let hStr = "";
let vStr = "";

// 水平方向判定
if (px < homeX) hStr = "→"; // 家は右にある
else if (px > homeX) hStr = "←"; // 家は左にある

// 垂直方向判定
if (py < homeY) vStr = "↓"; // 家は下にある
else if (py > homeY) vStr = "↑"; // 家は上にある

// 文字列結合ロジック
if (px === homeX) {
// 縦一直線 (左右のズレなし) -> 縦矢印を2つ重ねる
el.innerText = vStr + vStr;
} else if (py === homeY) {
// 横一直線 (上下のズレなし) -> 横矢印を2つ重ねる
el.innerText = hStr + hStr;
} else {
// 斜め位置
el.innerText = hStr + vStr;
}
}

function game() {
if (hitStopActive) return;

if (!isResting) {
px += xv; py += yv;
if (px === homeX && py === homeY) {
xv = 0; yv = 0;
}
} else {
xv = 0; yv = 0;
}

// コンパス更新
updateCompass();

// 壁判定
if (px < 0 || px >= worldSize || py < 0 || py >= worldSize) { gameOver(); return; }
for (let w of walls) {
if (px === w.x && py === w.y) { gameOver(); return; }
}

// 障害物判定
if (!isResting || (px !== homeX || py !== homeY)) {
for (let i = 0; i < obstacles.length; i++) {
if (px === obstacles[i].x && py === obstacles[i].y) {
if (garde > 0) {
garde--;
updateUI();
obstacles.splice(i, 1);
updateStatus("<b>GARDE発動!</b>");
hitStopActive = true;
setTimeout(() => { hitStopActive = false; }, 150);
} else {
gameOver(); return;
}
break;
}
}
}

// --- 描画処理 ---
ctx.fillStyle = "#222"; ctx.fillRect(0, 0, canvas.width, canvas.height);

const centerTileIndex = Math.floor(viewTiles / 2);
const offsetX = centerTileIndex - px;
const offsetY = centerTileIndex - py;

// グリッド
ctx.fillStyle = "#0a0a0a";
ctx.fillRect(offsetX * gs, offsetY * gs, worldSize * gs, worldSize * gs);
ctx.strokeStyle = "#333"; ctx.lineWidth = 1; ctx.beginPath();

let startX = Math.floor(-offsetX) - 1; let endX = startX + viewTiles + 2;
let startY = Math.floor(-offsetY) - 1; let endY = startY + viewTiles + 2;

for (let x = startX; x <= endX; x++) {
if(x >= 0 && x <= worldSize) {
let drawX = (x + offsetX) * gs;
ctx.moveTo(drawX, (0 + offsetY) * gs); ctx.lineTo(drawX, (worldSize + offsetY) * gs);
}
}
for (let y = startY; y <= endY; y++) {
if(y >= 0 && y <= worldSize) {
let drawY = (y + offsetY) * gs;
ctx.moveTo((0 + offsetX) * gs, drawY); ctx.lineTo((worldSize + offsetX) * gs, drawY);
}
}
ctx.stroke();

// 壁
const wallImg = getAsset('wall');
for (let w of walls) {
let drawWx = (w.x + offsetX) * gs;
let drawWy = (w.y + offsetY) * gs;
if (drawWx >= -gs && drawWx <= canvas.width && drawWy >= -gs && drawWy <= canvas.height) {
ctx.drawImage(wallImg, drawWx, drawWy, gs, gs);
}
}

// 障害物
animFrame++;
const pulseScale = 1 + 0.05 * Math.sin(animFrame * 0.2);
const pulseSize = gs * pulseScale;
const pulseOffsetXY = (gs - pulseSize) / 2;
const obstacleImg = getAsset('obstacle');

for (let obs of obstacles) {
let drawOx = (obs.x + offsetX) * gs;
let drawOy = (obs.y + offsetY) * gs;
if (drawOx >= -gs && drawOx <= canvas.width && drawOy >= -gs && drawOy <= canvas.height) {
ctx.drawImage(obstacleImg, drawOx + pulseOffsetXY, drawOy + pulseOffsetXY, pulseSize, pulseSize);
}
}

// エサ
const foodImg = getAsset('food');
for (let f of foods) {
let drawFx = (f.x + offsetX) * gs;
let drawFy = (f.y + offsetY) * gs;
if (drawFx >= -gs && drawFx <= canvas.width && drawFy >= -gs && drawFy <= canvas.height) {
ctx.drawImage(foodImg, drawFx, drawFy, gs, gs);
}
}

// 蛇の体
const bodyImg = getAsset('body');
for (var i = 0; i < trail.length; i++) {
let drawTx = (trail[i].x + offsetX) * gs;
let drawTy = (trail[i].y + offsetY) * gs;
if (trail[i].x === homeX && trail[i].y === homeY) continue;
if (drawTx >= -gs && drawTx <= canvas.width && drawTy >= -gs && drawTy <= canvas.height) {
ctx.drawImage(bodyImg, drawTx, drawTy, gs, gs);
}
if (!isResting && trail[i].x == px && trail[i].y == py) { gameOver(); return; }
}

ctx.drawImage(getAsset('head'), (px + offsetX) * gs, (py + offsetY) * gs, gs, gs);

// 家
let drawHomeX = (homeX + offsetX) * gs;
let drawHomeY = (homeY + offsetY) * gs;
if (drawHomeX >= -gs && drawHomeX <= canvas.width && drawHomeY >= -gs && drawHomeY <= canvas.height) {
ctx.drawImage(getAsset('house'), drawHomeX, drawHomeY, gs, gs);
}

// --- ロジック ---

if (px === homeX && py === homeY) {
if (trail.length > 0) {
// 納品中
addScore(deliverySequence); // ScoreとGold両方加算
updateUI();
updateStatus(`納品中... (+${deliverySequence} G!)`);
deliverySequence++;
trail.shift();
} else {
// 完了
if (currentConfigKey !== 'huge' && !isResting) {
applyConfig('huge');
}
deliverySequence = 1;
if (!isResting) {
isResting = true;
tail = 0;
updateStatus("休息中...<br>買い物 または 出発");
}
document.getElementById("shopMenu").style.display = "flex";
}
} else {
document.getElementById("shopMenu").style.display = "none";
deliverySequence = 1;
trail.push({ x: px, y: py });
while (trail.length > tail) { trail.shift(); }

const currentStatus = document.getElementById("statusMessage").innerHTML;
if(!currentStatus.includes("GARDE")) {
updateStatus("探索中...");
}
}

for (let i = 0; i < foods.length; i++) {
if (px === foods[i].x && py === foods[i].y) {
tail++;
addScore(1); // ScoreとGold両方加算
updateUI();
foods.splice(i, 1);
spawnFood();
spawnObstacle();
spawnObstacle();
break;
}
}
}

function isPositionOnSnake(x, y) {
if (!trail) return false;
for (let i = 0; i < trail.length; i++) { if (trail[i].x === x && trail[i].y === y) return true; }
return false;
}

function updateUI() {
document.getElementById("totalScoreVal").innerText = totalScore; // 累積
document.getElementById("goldVal").innerText = gold; // 所持金
document.getElementById("gardeVal").innerText = garde;

// GARDEボタン
const btnGarde = document.getElementById("buyGardeBtn");
if (gold >= COST_GARDE) {
btnGarde.disabled = false;
btnGarde.innerText = `GARDE + (${COST_GARDE} G)`;
} else {
btnGarde.disabled = true;
btnGarde.innerText = `GARDE + (不足 ${COST_GARDE} G)`;
}

// WIDE+1 ボタン
const btnWide1 = document.getElementById("buyWide1Btn");
if(currentConfigKey === 'medium') {
btnWide1.innerText = "WIDE+1 (装着中)";
btnWide1.classList.add('btn-active-mode');
btnWide1.disabled = false;
} else if (gold >= COST_WIDE1) {
btnWide1.innerText = `WIDE+1 : ${COST_WIDE1} G`;
btnWide1.classList.remove('btn-active-mode');
btnWide1.disabled = false;
} else {
btnWide1.innerText = `WIDE+1 (不足 ${COST_WIDE1} G)`;
btnWide1.classList.remove('btn-active-mode');
btnWide1.disabled = true;
}

// WIDE+2 ボタン
const btnWide2 = document.getElementById("buyWide2Btn");
if(currentConfigKey === 'small') {
btnWide2.innerText = "WIDE+2 (装着中)";
btnWide2.classList.add('btn-active-mode');
btnWide2.disabled = false;
} else if (gold >= COST_WIDE2) {
btnWide2.innerText = `WIDE+2 : ${COST_WIDE2} G`;
btnWide2.classList.remove('btn-active-mode');
btnWide2.disabled = false;
} else {
btnWide2.innerText = `WIDE+2 (不足 ${COST_WIDE2} G)`;
btnWide2.classList.remove('btn-active-mode');
btnWide2.disabled = true;
}
}

function updateStatus(msg) {
const el = document.getElementById("statusMessage");
if(el) el.innerHTML = msg;
}

function gameOver() {
isGameOver = true; clearInterval(gameInterval);
document.getElementById("finalTotalScore").innerText = totalScore; // 最終スコア表示
document.getElementById("gameOverScreen").style.display = "block";
document.getElementById("statusMessage").style.visibility = "hidden";
document.getElementById("shopMenu").style.display = "none";
}

function keyPush(evt) {
if (isGameOver) return;
if (isResting) {
const k = evt.keyCode;
if (k >= 37 && k <= 40) isResting = false;
else return;
}
switch (evt.keyCode) {
case 37: if (xv !== 1) { xv = -1; yv = 0; } break;
case 38: if (yv !== 1) { xv = 0; yv = -1; } break;
case 39: if (xv !== -1) { xv = 1; yv = 0; } break;
case 40: if (yv !== -1) { xv = 0; yv = 1; } break;
}
}

function handleTouchStart(evt) {
if(evt.target.id === "gameCanvas" || evt.target.tagName === "BODY") evt.preventDefault();
touchStartX = evt.touches[0].clientX; touchStartY = evt.touches[0].clientY;
}

function handleTouchEnd(evt) {
if (isGameOver) return;
if(evt.target.closest('#shopMenu')) return;

if(evt.target.id === "gameCanvas" || evt.target.tagName === "BODY") evt.preventDefault();
const xDiff = touchStartX - evt.changedTouches[0].clientX;
const yDiff = touchStartY - evt.changedTouches[0].clientY;
if (Math.abs(xDiff) < 10 && Math.abs(yDiff) < 10) return;
if (isResting) isResting = false;

if (Math.abs(xDiff) > Math.abs(yDiff)) {
if (xDiff > 0) { if (xv !== 1) { xv = -1; yv = 0; } } else { if (xv !== -1) { xv = 1; yv = 0; } }
} else {
if (yDiff > 0) { if (yv !== 1) { xv = 0; yv = -1; } } else { if (yv !== -1) { xv = 0; yv = 1; } }
}
}
</script>
</body>
</html>


使用変数

addScore -------( Function )
animFrame
applyConfig -------( Function )
assets
attempt
baseSize
bodyImg
btnGarde
btnWide1
btnWide2
buyGarde -------( Function )
buyMode -------( Function )
c
canvas
centerTileIndex
cfg
charset
class
content
cost
COST_GARDE
COST_WIDE1
COST_WIDE2
createFallbackGraphic -------( Function )
ctx
currentConfigKey
currentStatus
deliverySequence
disabled
display
drawFx
drawFy
drawHomeX
drawHomeY
drawOx
drawOy
drawTx
drawTy
drawWx
drawWy
drawX
drawY
el
endX
endY
fallback
fillStyle
foodImg
foods
fx
fy
game -------( Function )
gameInterval
gameOver -------( Function )
garde
getAsset -------( Function )
gold
gs
handleTouchEnd -------( Function )
handleTouchStart -------( Function )
height
hitStopActive
homeX
homeY
hStr
i
id
initAssets -------( Function )
initMapWalls -------( Function )
innerHTML
innerText
isGameOver
isNearPlayer -------( Function )
isOccupied -------( Function )
isPositionOnSnake -------( Function )
isResting
k
keyPush -------( Function )
lang
levels
lineWidth
loaded
modeKey
name
obstacleImg
obstacles
offsetX
offsetY
onclick
onload
ox
oy
pulseOffsetXY
pulseScale
pulseSize
px
py
resetGame -------( Function )
s
safeZone
scalable
scale
spawnFood -------( Function )
spawnObstacle -------( Function )
src
startX
startY
strokeStyle
style
tagName
tail
targetFoodCount
totalScore
touchStartX
touchStartY
trail
type
updateCompass -------( Function )
updateStatus -------( Function )
updateUI -------( Function )
viewTiles
visibility
vStr
wallImg
walls
width
worldSize
WORLD_SIZE_FIXED
x
xDiff
xv
y
yDiff
yv