mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Add NPC sprite test scenario, server for development, and HTML test pages
- Created a new JSON scenario file for testing NPC sprite functionality. - Implemented a simple HTTP server with caching headers for development purposes. - Added an HTML page for testing NPC interactions, including system checks and game controls. - Introduced a separate HTML page for testing item delivery through person chat interactions.
This commit is contained in:
417
test-npc-interaction.html
Normal file
417
test-npc-interaction.html
Normal file
@@ -0,0 +1,417 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NPC Interaction Test</title>
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/panels.css">
|
||||
<link rel="stylesheet" href="css/modals.css">
|
||||
<link rel="stylesheet" href="css/inventory.css">
|
||||
<link rel="stylesheet" href="css/person-chat-minigame.css">
|
||||
<link rel="stylesheet" href="css/npc-interactions.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #222;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.test-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
h1 {
|
||||
color: #4da6ff;
|
||||
border-bottom: 2px solid #4da6ff;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.test-section {
|
||||
background-color: #333;
|
||||
border: 2px solid #4da6ff;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
.test-button {
|
||||
background-color: #4da6ff;
|
||||
color: #000;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.test-button:hover {
|
||||
background-color: #6dbfff;
|
||||
}
|
||||
.test-output {
|
||||
background-color: #222;
|
||||
border: 1px solid #666;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-weight: bold;
|
||||
margin: 0 5px;
|
||||
}
|
||||
.status.ok {
|
||||
background-color: #4db84d;
|
||||
color: white;
|
||||
}
|
||||
.status.error {
|
||||
background-color: #d9534f;
|
||||
color: white;
|
||||
}
|
||||
.status.warning {
|
||||
background-color: #f0ad4e;
|
||||
color: black;
|
||||
}
|
||||
#gameContainer {
|
||||
margin-top: 20px;
|
||||
border: 2px solid #666;
|
||||
background-color: #000;
|
||||
}
|
||||
.instructions {
|
||||
background-color: #1a3a1a;
|
||||
border-left: 4px solid #4db84d;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>🎭 NPC Interaction System Test</h1>
|
||||
|
||||
<div class="instructions">
|
||||
<strong>Test Procedure:</strong>
|
||||
<ol>
|
||||
<li>Click "Load NPC Test Scenario" to start the game</li>
|
||||
<li>Walk the player character near either NPC</li>
|
||||
<li>Look for "Press E to talk to [NPC Name]" prompt at the bottom</li>
|
||||
<li>Press E to trigger the conversation</li>
|
||||
<li>Verify the conversation UI appears with portraits and dialogue</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>🔧 System Checks</h2>
|
||||
<button class="test-button" onclick="checkNPCSystem()">Check NPC System</button>
|
||||
<button class="test-button" onclick="checkNPCProximity()">Check Proximity Detection</button>
|
||||
<button class="test-button" onclick="listNPCs()">List All NPCs</button>
|
||||
<button class="test-button" onclick="testInteractionPrompt()">Test Interaction Prompt</button>
|
||||
<button class="test-button" onclick="clearConsole()">Clear Output</button>
|
||||
<div id="systemOutput" class="test-output">Waiting for tests...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>🎮 Game Controls</h2>
|
||||
<button class="test-button" onclick="startGame()">Load NPC Test Scenario</button>
|
||||
<button class="test-button" onclick="resetGame()">Reset Game</button>
|
||||
<div id="gameOutput" class="test-output">Game status: Ready</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>📊 Debug Info</h2>
|
||||
<button class="test-button" onclick="showDebugInfo()">Show Full Debug Info</button>
|
||||
<button class="test-button" onclick="manuallyTriggerInteraction()">Manually Trigger E-Key</button>
|
||||
<div id="debugOutput" class="test-output">Debug info will appear here...</div>
|
||||
</div>
|
||||
|
||||
<div id="gameContainer"></div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import('./js/main.js').then(() => {
|
||||
updateGameStatus('Game module loaded');
|
||||
});
|
||||
|
||||
window.testFunctions = {
|
||||
checkNPCSystem,
|
||||
checkNPCProximity,
|
||||
listNPCs,
|
||||
testInteractionPrompt,
|
||||
clearConsole,
|
||||
startGame,
|
||||
resetGame,
|
||||
showDebugInfo,
|
||||
manuallyTriggerInteraction
|
||||
};
|
||||
|
||||
function log(message, type = 'info') {
|
||||
console.log(`[${type.toUpperCase()}] ${message}`);
|
||||
}
|
||||
|
||||
function output(text, elementId = 'systemOutput') {
|
||||
const elem = document.getElementById(elementId);
|
||||
if (elem) {
|
||||
elem.textContent += text + '\n';
|
||||
elem.scrollTop = elem.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
function clearOutput(elementId = 'systemOutput') {
|
||||
const elem = document.getElementById(elementId);
|
||||
if (elem) {
|
||||
elem.textContent = '';
|
||||
}
|
||||
}
|
||||
|
||||
function checkNPCSystem() {
|
||||
clearOutput('systemOutput');
|
||||
output('🔍 Checking NPC System...\n');
|
||||
|
||||
const checks = [
|
||||
{ name: 'window.npcManager', check: () => window.npcManager },
|
||||
{ name: 'window.player', check: () => window.player },
|
||||
{ name: 'window.MinigameFramework', check: () => window.MinigameFramework },
|
||||
{ name: 'window.checkNPCProximity', check: () => window.checkNPCProximity },
|
||||
{ name: 'window.tryInteractWithNearest', check: () => window.tryInteractWithNearest }
|
||||
];
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
checks.forEach(({ name, check }) => {
|
||||
try {
|
||||
const result = check();
|
||||
if (result) {
|
||||
output(`✅ ${name}`);
|
||||
passed++;
|
||||
} else {
|
||||
output(`❌ ${name} - exists but is falsy`);
|
||||
failed++;
|
||||
}
|
||||
} catch (e) {
|
||||
output(`❌ ${name} - ${e.message}`);
|
||||
failed++;
|
||||
}
|
||||
});
|
||||
|
||||
output(`\n📊 Results: ${passed} passed, ${failed} failed`);
|
||||
}
|
||||
|
||||
function checkNPCProximity() {
|
||||
clearOutput('systemOutput');
|
||||
output('🔍 Checking NPC Proximity Detection...\n');
|
||||
|
||||
if (!window.npcManager) {
|
||||
output('❌ npcManager not available');
|
||||
return;
|
||||
}
|
||||
|
||||
output(`NPCs registered: ${window.npcManager.npcs.size}\n`);
|
||||
|
||||
if (window.npcManager.npcs.size === 0) {
|
||||
output('⚠️ No NPCs registered. Load a scenario first.\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.player) {
|
||||
output('❌ Player not available');
|
||||
return;
|
||||
}
|
||||
|
||||
output(`Player position: (${window.player.x}, ${window.player.y})\n`);
|
||||
|
||||
// Calculate distances to all NPCs
|
||||
let found = false;
|
||||
window.npcManager.npcs.forEach((npc) => {
|
||||
if (npc._sprite) {
|
||||
const dx = npc._sprite.x - window.player.x;
|
||||
const dy = npc._sprite.y - window.player.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const inRange = distance <= 64;
|
||||
|
||||
output(`${inRange ? '✅' : '⚠️'} ${npc.displayName} (${npc.id})`);
|
||||
output(` Position: (${npc._sprite.x}, ${npc._sprite.y})`);
|
||||
output(` Distance: ${distance.toFixed(2)}px (${inRange ? 'IN RANGE' : 'OUT OF RANGE'})`);
|
||||
output(` Type: ${npc.npcType}`);
|
||||
output(` Sprite active: ${npc._sprite.active}\n`);
|
||||
|
||||
if (inRange) found = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (found) {
|
||||
output('🎯 At least one NPC is in range!\n');
|
||||
} else {
|
||||
output('⚠️ No NPCs are in range. Move player closer.\n');
|
||||
}
|
||||
|
||||
// Manually run proximity check
|
||||
if (window.checkNPCProximity) {
|
||||
output('Running checkNPCProximity()...\n');
|
||||
window.checkNPCProximity();
|
||||
|
||||
const prompt = document.getElementById('npc-interaction-prompt');
|
||||
if (prompt) {
|
||||
output(`✅ Prompt created: "${prompt.querySelector('.prompt-text').textContent}"`);
|
||||
} else {
|
||||
output('⚠️ No prompt created');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listNPCs() {
|
||||
clearOutput('systemOutput');
|
||||
output('📋 NPC Listing\n');
|
||||
|
||||
if (!window.npcManager) {
|
||||
output('❌ npcManager not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const count = window.npcManager.npcs.size;
|
||||
output(`Total NPCs: ${count}\n`);
|
||||
|
||||
if (count === 0) {
|
||||
output('No NPCs registered.');
|
||||
return;
|
||||
}
|
||||
|
||||
window.npcManager.npcs.forEach((npc, id) => {
|
||||
output(`\n📌 ${npc.displayName} (${id})`);
|
||||
output(` Type: ${npc.npcType}`);
|
||||
output(` Phone ID: ${npc.phoneId || 'none'}`);
|
||||
output(` Story: ${npc.storyPath || 'none'}`);
|
||||
output(` Room: ${npc.roomId || 'none'}`);
|
||||
|
||||
if (npc._sprite) {
|
||||
output(` Sprite: YES @ (${npc._sprite.x}, ${npc._sprite.y})`);
|
||||
output(` Active: ${npc._sprite.active}`);
|
||||
} else {
|
||||
output(` Sprite: NO`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testInteractionPrompt() {
|
||||
clearOutput('systemOutput');
|
||||
output('🧪 Testing Interaction Prompt\n');
|
||||
|
||||
if (!window.npcManager) {
|
||||
output('❌ npcManager not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const npcs = Array.from(window.npcManager.npcs.values());
|
||||
if (npcs.length === 0) {
|
||||
output('❌ No NPCs to test');
|
||||
return;
|
||||
}
|
||||
|
||||
const testNpc = npcs[0];
|
||||
output(`Testing with: ${testNpc.displayName}\n`);
|
||||
|
||||
// Manually create prompt
|
||||
output('Creating prompt...\n');
|
||||
if (window.updateNPCInteractionPrompt) {
|
||||
window.updateNPCInteractionPrompt(testNpc);
|
||||
|
||||
const prompt = document.getElementById('npc-interaction-prompt');
|
||||
if (prompt) {
|
||||
output('✅ Prompt created');
|
||||
output(` Element: ${prompt.id}`);
|
||||
output(` Text: ${prompt.querySelector('.prompt-text').textContent}`);
|
||||
output(` NPC ID: ${prompt.dataset.npcId}\n`);
|
||||
|
||||
output('Prompt is visible on screen\n');
|
||||
|
||||
// Clear it
|
||||
output('Clearing prompt...\n');
|
||||
window.updateNPCInteractionPrompt(null);
|
||||
|
||||
if (!document.getElementById('npc-interaction-prompt')) {
|
||||
output('✅ Prompt cleared successfully');
|
||||
} else {
|
||||
output('❌ Prompt still exists');
|
||||
}
|
||||
} else {
|
||||
output('❌ Prompt not created');
|
||||
}
|
||||
} else {
|
||||
output('❌ updateNPCInteractionPrompt not available');
|
||||
}
|
||||
}
|
||||
|
||||
function clearConsole() {
|
||||
clearOutput('systemOutput');
|
||||
output('🗑️ Output cleared');
|
||||
}
|
||||
|
||||
function startGame() {
|
||||
clearOutput('gameOutput');
|
||||
output('🎮 Loading NPC Test Scenario...', 'gameOutput');
|
||||
|
||||
// Redirect to scenario_select with test scenario
|
||||
window.location.href = 'scenario_select.html?scenario=npc-sprite-test';
|
||||
}
|
||||
|
||||
function resetGame() {
|
||||
clearOutput('gameOutput');
|
||||
output('🔄 Resetting game...', 'gameOutput');
|
||||
|
||||
// Reload page
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function showDebugInfo() {
|
||||
clearOutput('debugOutput');
|
||||
const info = {
|
||||
'Player': window.player ? `(${window.player.x}, ${window.player.y})` : 'Not loaded',
|
||||
'NPC Manager': window.npcManager ? `${window.npcManager.npcs.size} NPCs` : 'Not loaded',
|
||||
'Current Prompt': document.getElementById('npc-interaction-prompt') ? 'Yes' : 'No',
|
||||
'MinigameFramework': window.MinigameFramework ? 'Loaded' : 'Not loaded',
|
||||
'E-Key Handler': window.tryInteractWithNearest ? 'Ready' : 'Not ready'
|
||||
};
|
||||
|
||||
output('📊 DEBUG INFO\n');
|
||||
Object.entries(info).forEach(([key, value]) => {
|
||||
output(`${key}: ${value}`);
|
||||
});
|
||||
}
|
||||
|
||||
function manuallyTriggerInteraction() {
|
||||
clearOutput('debugOutput');
|
||||
output('🎯 Manually triggering E-Key interaction...\n');
|
||||
|
||||
if (!window.tryInteractWithNearest) {
|
||||
output('❌ tryInteractWithNearest not available');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
window.tryInteractWithNearest();
|
||||
output('✅ Interaction triggered');
|
||||
} catch (e) {
|
||||
output(`❌ Error: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function updateGameStatus(msg) {
|
||||
const elem = document.getElementById('gameOutput');
|
||||
if (elem) {
|
||||
elem.textContent = `📊 ${msg}`;
|
||||
}
|
||||
}
|
||||
|
||||
window.updateGameStatus = updateGameStatus;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user