const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 1. Game State Setup
const player = {
x: 400,
y: 350,
radius: 12,
speed: 4,
color: '#e67e22', // Camp Half-Blood Orange
currentZone: 'The Main Green'
};
// Fast Travel Portal Infrastructure
const portals = [
{ name: "Big House Portal", x: 160, y: 440, targetX: 620, targetY: 170, radius: 20 },
{ name: "Half-Blood Hill Portal", x: 620, y: 140, targetX: 160, targetY: 410, radius: 20 }
];
let travelCooldown = 0;
const keys = { w: false, a: false, s: false, d: false };
// Input Event Hooks
window.addEventListener('keydown', (e) => {
const k = e.key.toLowerCase();
if (['w', 'a', 's', 'd'].includes(k)) keys[k] = true;
});
window.addEventListener('keyup', (e) => {
const k = e.key.toLowerCase();
if (['w', 'a', 's', 'd'].includes(k)) keys[k] = false;
});
function getDistance(x1, y1, x2, y2) {
return Math.hypot(x2 - x1, y2 - y1);
}
// 2. Logic & Core Math Updates
function update() {
// Player Movement
if (keys.w && player.y - player.radius > 0) player.y -= player.speed;
if (keys.s && player.y + player.radius < canvas.height) player.y += player.speed;
if (keys.a && player.x - player.radius > 0) player.x -= player.speed;
if (keys.d && player.x + player.radius < canvas.width) player.x += player.speed;
// Track active zone coordinates to update HUD text
updateZoneLabel();
// Portal Collision & Fast Travel Teleport Loop
if (travelCooldown > 0) {
travelCooldown--;
} else {
portals.forEach(portal => {
if (getDistance(player.x, player.y, portal.x, portal.y) < player.radius + portal.radius) {
player.x = portal.targetX;
player.y = portal.targetY;
travelCooldown = 90; // 1.5 seconds cooldown to prevent infinite looping
}
});
}
}
function updateZoneLabel() {
if (player.y < 120) {
player.currentZone = "Long Island Sound (Beach)";
} else if (player.x > 550 && player.y < 250) {
player.currentZone = "Half-Blood Hill (Thalia's Pine)";
} else if (player.x < 250 && player.y > 350) {
player.currentZone = "The Big House Grounds";
} else if (player.x > 300 && player.x < 500 && player.y > 220 && player.y < 420) {
player.currentZone = "The Cabin Green (U-Shape Layout)";
} else if (player.x > 520 && player.y > 400) {
player.currentZone = "The Fireworks Amphitheater";
} else if (player.x < 250 && player.y < 250) {
player.currentZone = "Strawberry Fields";
} else {
player.currentZone = "Camp Wilderness Woods";
}
}
// 3. Render Pipeline (Drawing the Actual Camp Map Graphics)
function drawMap() {
// Basic Grass Floor Base
ctx.fillStyle = '#27ae60';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// North Coast: Long Island Sound (Ocean Water)
ctx.fillStyle = '#2980b9';
ctx.fillRect(0, 0, canvas.width, 100);
// Sandy Beach shoreline
ctx.fillStyle = '#f1c40f';
ctx.fillRect(0, 100, canvas.width, 15);
// Northwest Quadrant: Strawberry Fields (Rows of Crops)
ctx.fillStyle = '#1e824c';
for (let i = 30; i < 220; i += 30) {
ctx.fillRect(i, 150, 15, 120);
// Small red berries
ctx.fillStyle = '#e74c3c';
for(let j = 160; j < 270; j += 20) ctx.fillRect(i + 6, j, 4, 4);
ctx.fillStyle = '#1e824c';
}
// Southwest: The Big House (Blue Building Structure Layout)
ctx.fillStyle = '#3498db';
ctx.fillRect(80, 400, 120, 90);
ctx.fillStyle = '#2980b9'; // Porch roof extension wrap
ctx.fillRect(70, 480, 140, 15);
ctx.fillStyle = '#ffffff';
ctx.font = '11px Arial';
ctx.fillText("Big House", 140, 450);
// Southeast: Outdoor Amphitheater semicircles
ctx.strokeStyle = '#d35400';
ctx.lineWidth = 4;
for (let r = 20; r <= 60; r += 15) {
ctx.beginPath();
ctx.arc(660, 500, r, Math.PI, 0);
ctx.stroke();
}
ctx.fillStyle = '#e67e22'; // Central campfire hearth point
ctx.beginPath(); ctx.arc(660, 500, 8, 0, Math.PI*2); ctx.fill();
// Center: The Divine Cabins (Arranged in a U-Shape opening North)
ctx.fillStyle = '#7f8c8d';
// Left Wing Cabins (Zeus, Poseidon, Ares, etc.)
for (let y = 240; y <= 390; y += 35) {
ctx.fillRect(320, y, 35, 22);
ctx.fillRect(445, y, 35, 22); // Right Wing (Hera, Athena, Apollo...)
}
// Bottom Base Cabins (Hermes, Dionysus)
ctx.fillRect(362, 400, 35, 22);
ctx.fillRect(403, 400, 35, 22);
// Northeast Corner: Half-Blood Hill & Thalia's Pine Tree
ctx.fillStyle = '#5ebd74'; // Shaded elevation ground curve rings
ctx.beginPath(); ctx.arc(700, 120, 90, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(720, 100, 50, 0, Math.PI * 2); ctx.fill();
// Tree Trunk
ctx.fillStyle = '#795548';
ctx.fillRect(710, 80, 10, 30);
// Pine Foliage Triangles
ctx.fillStyle = '#0e4d22';
ctx.beginPath(); ctx.moveTo(715, 30); ctx.lineTo(690, 70); ctx.lineTo(740, 70); ctx.closePath(); ctx.fill();
ctx.beginPath(); ctx.moveTo(715, 45); ctx.lineTo(685, 90); ctx.lineTo(745, 90); ctx.closePath(); ctx.fill();
// Render Fast Travel Matrices / Shiny Rings
portals.forEach(portal => {
let pulse = 2 * Math.sin(Date.now() / 150);
ctx.strokeStyle = '#00ffff';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(portal.x, portal.y, portal.radius + pulse, 0, Math.PI * 2);
ctx.stroke();
ctx.fillStyle = 'rgba(0, 255, 255, 0.2)';
ctx.beginPath();
ctx.arc(portal.x, portal.y, portal.radius - 2, 0, Math.PI * 2);
ctx.fill();
});
}
function drawHUD() {
// Dynamic overlay stats box card frame
ctx.fillStyle = 'rgba(26, 15, 6, 0.85)';
ctx.fillRect(15, 15, 310, 75);
ctx.strokeStyle = '#d4af37';
ctx.lineWidth = 2;
ctx.strokeRect(15, 15, 310, 75);
ctx.fillStyle = '#f1c40f';
ctx.font = 'bold 13px Georgia';
ctx.textAlign = 'left';
ctx.fillText(`📍 Current Location:`, 28, 38);
ctx.fillStyle = '#ffffff';
ctx.font = '13px Arial';
ctx.fillText(player.currentZone, 160, 38);
ctx.font = '12px Georgia';
if (travelCooldown > 0) {
ctx.fillStyle = '#e74c3c';
ctx.fillText(`✨ Teleport Matrix Re-aligning: ${Math.ceil(travelCooldown/60)}s`, 28, 65);
} else {
ctx.fillStyle = '#2ecc71';
ctx.fillText(`✨ Fast Travel Matrices: READY TO BEAM`, 28, 65);
}
}
// 4. Main Executive Loop Frame
function mainLoop() {
update();
drawMap();
// Draw Player Demigod Token
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.stroke();
drawHUD();
requestAnimationFrame(mainLoop);
}
mainLoop();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Camp Half-Blood: Conversations</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app-wrapper">
<!-- Left Sidebar: Character Affinities & Profiles -->
<div id="stats-sidebar">
<h3 class="sidebar-title">Demigod Bonds</h3>
<div class="stat-card">
<div class="stat-header">
<span>Percy Jackson</span>
<span id="affinity-percy">0 XP</span>
</div>
<div class="progress-bar"><div id="bar-percy" class="progress-fill"></div></div>
</div>
<div class="stat-card">
<div class="stat-header">
<span>Annabeth Chase</span>
<span id="affinity-annabeth">0 XP</span>
</div>
<div class="progress-bar"><div id="bar-annabeth" class="progress-fill"></div></div>
</div>
<div class="stat-card">
<div class="stat-header">
<span>Clarisse La Rue</span>
<span id="affinity-clarisse">0 XP</span>
</div>
<div class="progress-bar"><div id="bar-clarisse" class="progress-fill"></div></div>
</div>
<div class="stat-card">
<div class="stat-header">
<span>Nico di Angelo</span>
<span id="affinity-nico">0 XP</span>
</div>
<div class="progress-bar"><div id="bar-nico" class="progress-fill"></div></div>
</div>
<!-- Added Grover's missing card -->
<div class="stat-card">
<div class="stat-header">
<span>Grover Underwood</span>
<span id="affinity-grover">0 XP</span>
</div>
<div class="progress-bar"><div id="bar-grover" class="progress-fill"></div></div>
</div>
</div>
<!-- Right Main: Chat Interface Module Layout -->
<div id="chat-container">
<div class="tabs-row">
<button id="tab-percy" class="tab-btn active" onclick="switchTab('percy')">Percy</button>
<button id="tab-annabeth" class="tab-btn" onclick="switchTab('annabeth')">Annabeth</button>
<button id="tab-clarisse" class="tab-btn" onclick="switchTab('clarisse')">Clarisse</button>
<button id="tab-nico" class="tab-btn" onclick="switchTab('nico')">Nico</button>
<button id="tab-grover" class="tab-btn" onclick="switchTab('grover')">Grover</button>
</div>
<!-- Dynamic Dialogue Grid Context Frame Window View -->
<div id="chat-display-area"></div>
<!-- Interactive Typing Status Indicator Node -->
<div id="typing-indicator"></div>
<!-- Operational Form Control Entry Field Bar Row -->
<div class="input-row">
<input type="text" id="user-msg-input" placeholder="Type a message..." maxlength="80" autocomplete="off">
<button id="send-msg-btn">Send</button>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
this is the chat file im trying to get the errors so i could’nt make much changes


these are all the files in this simulator