Enhance inventory system in index.html: add new inventory container with dynamic item handling, update styles for improved layout, and refactor item interaction logic for better user experience.

This commit is contained in:
Z. Cliffe Schreuders
2025-05-05 09:57:34 +01:00
parent b0676a48b8
commit 66b9ffb546

View File

@@ -54,8 +54,8 @@
position: fixed; position: fixed;
top: 20px; top: 20px;
right: 20px; right: 20px;
width: 500px; width: 600px;
max-width: 80%; max-width: 90%;
z-index: 2000; z-index: 2000;
font-family: 'Press Start 2P'; font-family: 'Press Start 2P';
pointer-events: none; pointer-events: none;
@@ -136,6 +136,7 @@
bottom: 80px; bottom: 80px;
right: 20px; right: 20px;
width: 500px; width: 500px;
max-width: fit-content;
max-height: 500px; max-height: 500px;
background-color: rgba(0, 0, 0, 0.9); background-color: rgba(0, 0, 0, 0.9);
color: white; color: white;
@@ -844,8 +845,8 @@
/* Toggle Buttons Container */ /* Toggle Buttons Container */
#toggle-buttons-container { #toggle-buttons-container {
position: fixed; position: fixed;
bottom: 20px; bottom: 15px;
right: 20px; right: 15px;
display: flex; display: flex;
flex-direction: row-reverse; flex-direction: row-reverse;
z-index: 1998; z-index: 1998;
@@ -1144,6 +1145,74 @@
font-size: 125%; font-size: 125%;
} }
} }
#inventory-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 80px;
display: flex;
align-items: center;
/* overflow-x: auto; */
padding: 0 20px;
z-index: 1000;
}
#inventory-container::-webkit-scrollbar {
height: 8px;
}
#inventory-container::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
#inventory-container::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 4px;
}
.inventory-slot {
min-width: 60px;
height: 60px;
margin: 0 5px;
border: 1px solid rgba(255, 255, 255, 0.3);
display: flex;
justify-content: center;
align-items: center;
position: relative;
background: rgba(0, 0, 0, 0.8);
}
.inventory-item {
max-width: 48px;
max-height: 48px;
cursor: pointer;
transition: transform 0.2s;
}
.inventory-item:hover {
transform: scale(1.1);
}
.inventory-tooltip {
position: absolute;
bottom: 100%;
left: -10px;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 14px;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
}
.inventory-item:hover + .inventory-tooltip {
opacity: 1;
}
</style> </style>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/easystarjs@0.4.4/bin/easystar-0.4.4.js"></script> <script src="https://cdn.jsdelivr.net/npm/easystarjs@0.4.4/bin/easystar-0.4.4.js"></script>
@@ -1222,6 +1291,9 @@
<div id="biometrics-content"></div> <div id="biometrics-content"></div>
</div> </div>
<!-- Inventory Container -->
<div id="inventory-container"></div>
<script> <script>
const config = { const config = {
type: Phaser.AUTO, type: Phaser.AUTO,
@@ -1994,14 +2066,14 @@
// Convert pointer position to world coordinates // Convert pointer position to world coordinates
// Calculate the inventory area based on the container's position and size // Calculate the inventory area based on the container's position and size
const inventoryBounds = inventory.container.getBounds(); const inventoryBounds = inventory.container.getBoundingClientRect();
if (pointer.y > inventoryBounds.y && pointer.y < inventoryBounds.y + inventoryBounds.height && if (pointer.y > inventoryBounds.top && pointer.y < inventoryBounds.bottom &&
pointer.x > inventoryBounds.x && pointer.x < inventoryBounds.x + inventoryBounds.width) { pointer.x > inventoryBounds.left && pointer.x < inventoryBounds.right) {
// Find clicked inventory item // Find clicked inventory item
const clickedItem = inventory.items.find(item => { const clickedItem = inventory.items.find(item => {
if (!item) return false; if (!item) return false;
const bounds = item.getBounds(); const bounds = item.getBoundingClientRect();
return Phaser.Geom.Rectangle.Contains( return Phaser.Geom.Rectangle.Contains(
bounds, bounds,
pointer.x, pointer.x,
@@ -3173,7 +3245,7 @@
let message = `${data.name}\n\n`; let message = `${data.name}\n\n`;
if (data.observations) { if (data.observations) {
message += `Observations: ${data.observations}\n\n`; message += `Observations: ${data.observations}\n\n`;
} }
if (data.readable && data.text) { if (data.readable && data.text) {
@@ -3312,70 +3384,51 @@
sprite.setVisible(false); sprite.setVisible(false);
const scene = sprite.scene; // Find first empty slot
const slots = inventory.container.getElementsByClassName('inventory-slot');
let emptySlot = null;
for (const slot of slots) {
if (!slot.hasChildNodes()) {
emptySlot = slot;
break;
}
}
// SIMPLIFIED INVENTORY NAMING if (!emptySlot) {
// Use a consistent format: inventory_type_index console.warn('No empty inventory slots available');
const inventoryId = `inventory_${sprite.name}_${inventory.items.length}`; return false;
}
// Create new sprite for inventory // Create inventory item
const inventorySprite = scene.add.sprite( const itemImg = document.createElement('img');
inventory.items.length * 60, itemImg.className = 'inventory-item';
0, itemImg.src = `assets/objects/${sprite.name}.png`;
sprite.name itemImg.alt = sprite.scenarioData.name;
);
inventorySprite.setInteractive({ useHandCursor: true, pixelPerfect: true }); // Create tooltip
inventorySprite.scenarioData = { const tooltip = document.createElement('div');
tooltip.className = 'inventory-tooltip';
tooltip.textContent = sprite.scenarioData.name;
// Add item data
itemImg.scenarioData = {
...sprite.scenarioData, ...sprite.scenarioData,
foundIn: currentRoom ? gameScenario.rooms[currentRoom].name || currentRoom : 'unknown location' foundIn: currentRoom ? gameScenario.rooms[currentRoom].name || currentRoom : 'unknown location'
}; };
inventorySprite.name = sprite.name; itemImg.name = sprite.name;
inventorySprite.objectId = inventoryId; itemImg.objectId = `inventory_${sprite.name}_${inventory.items.length}`;
// Set depth higher than container // Add click handler
inventorySprite.setDepth(2003); itemImg.addEventListener('click', function() {
handleObjectInteraction(this);
// Add pointer events
inventorySprite.on('pointerdown', function(pointer) {
// Handle inventory item interaction
handleObjectInteraction(inventorySprite);
}); });
inventorySprite.on('pointerover', function() { // Add to slot
this.setTint(0xdddddd); emptySlot.appendChild(itemImg);
emptySlot.appendChild(tooltip);
// Show tooltip with item name
const tooltipText = scene.add.text(
this.x,
this.y - 40,
this.scenarioData.name,
{
fontSize: '14px',
backgroundColor: '#000',
padding: { x: 5, y: 3 },
fixedWidth: 150,
align: 'center'
}
).setOrigin(0.5, 0.5).setDepth(2004);
this.tooltip = tooltipText;
});
inventorySprite.on('pointerout', function() {
this.clearTint();
if (this.tooltip) {
this.tooltip.destroy();
this.tooltip = null;
}
});
// Add to inventory array // Add to inventory array
inventory.items.push(inventorySprite); inventory.items.push(itemImg);
// Add to container
inventory.container.add(inventorySprite);
// Show notification // Show notification
gameAlert(`Added ${sprite.scenarioData.name} to inventory`, 'success', 'Item Collected', 3000); gameAlert(`Added ${sprite.scenarioData.name} to inventory`, 'success', 'Item Collected', 3000);
@@ -3399,37 +3452,91 @@
} }
} }
function removeFromInventory(item) {
try {
// Find the item in the inventory array
const itemIndex = inventory.items.indexOf(item);
if (itemIndex === -1) return false;
// Remove from array
inventory.items.splice(itemIndex, 1);
// Remove from DOM
const slot = item.parentElement;
if (slot) {
slot.innerHTML = '';
}
// Hide bluetooth toggle if we dropped the bluetooth scanner
if (item.scenarioData.type === "bluetooth_scanner") {
const bluetoothToggle = document.getElementById('bluetooth-toggle');
bluetoothToggle.style.display = 'none';
}
// Hide biometrics toggle if we dropped the fingerprint kit
if (item.scenarioData.type === "fingerprint_kit") {
const biometricsToggle = document.getElementById('biometrics-toggle');
biometricsToggle.style.display = 'none';
}
return true;
} catch (error) {
console.error('Error removing from inventory:', error);
return false;
}
}
function dropInventoryItem(item) {
try {
if (!item || !item.scenarioData) return false;
// Get player position
const dropPos = {
x: player.x,
y: player.y
};
// Create a new sprite at the drop position
const droppedItem = createInteractiveSprite(
item.scenarioData,
dropPos.x,
dropPos.y,
currentRoom
);
if (!droppedItem) return false;
// Remove from inventory
removeFromInventory(item);
return true;
} catch (error) {
console.error('Error dropping inventory item:', error);
return false;
}
}
// initializes inventory // initializes inventory
// creates the background and slot outlines // creates the background and slot outlines
function initializeInventory() { function initializeInventory() {
// Reset inventory state // Reset inventory state
inventory.items = []; inventory.items = [];
// Create slot outlines // Get the HTML inventory container
const slotsContainer = this.add.container(INVENTORY_X_OFFSET, this.cameras.main.height - INVENTORY_Y_OFFSET) const inventoryContainer = document.getElementById('inventory-container');
.setScrollFactor(0) inventoryContainer.innerHTML = '';
.setDepth(2001);
// Create 10 slot outlines // Create 10 slot outlines
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const outline = this.add.rectangle( const slot = document.createElement('div');
i * 60, slot.className = 'inventory-slot';
0, inventoryContainer.appendChild(slot);
50, // slightly smaller than spacing
50,
0x666666,
0.3
);
outline.setStrokeStyle(1, 0x666666);
slotsContainer.add(outline);
} }
// Initialize inventory container - use the same X offset as slots // Store reference to container
inventory.container = this.add.container(INVENTORY_X_OFFSET, this.cameras.main.height - INVENTORY_Y_OFFSET) inventory.container = inventoryContainer;
.setScrollFactor(0)
.setDepth(2001);
debugLog('INVENTORY INITIALIZED', inventory, 2); // Debug log at level 2 debugLog('INVENTORY INITIALIZED', inventory, 2);
} }
// Process all items marked with inInventory: true in the scenario data // Process all items marked with inInventory: true in the scenario data
@@ -6540,61 +6647,6 @@
biometricsPanel.style.display = 'none'; biometricsPanel.style.display = 'none';
} }
// Function to drop an inventory item
function dropInventoryItem(item) {
try {
if (!item || !item.scenarioData) return false;
// Get player position
const dropPos = {
x: player.x,
y: player.y
};
// Create a new sprite at the drop position
const droppedItem = createInteractiveSprite(
item.scenarioData,
dropPos.x,
dropPos.y,
currentRoom
);
if (!droppedItem) return false;
// Remove from inventory array
const itemIndex = inventory.items.indexOf(item);
if (itemIndex !== -1) {
inventory.items.splice(itemIndex, 1);
}
// Remove from inventory container
inventory.container.remove(item);
// Destroy inventory sprite
item.destroy();
// Recalculate inventory positions
updateInventoryPositions();
// Hide bluetooth toggle if we dropped the bluetooth scanner
if (item.scenarioData.type === "bluetooth_scanner") {
const bluetoothToggle = document.getElementById('bluetooth-toggle');
bluetoothToggle.style.display = 'none';
}
// Hide biometrics toggle if we dropped the fingerprint kit
if (item.scenarioData.type === "fingerprint_kit") {
const biometricsToggle = document.getElementById('biometrics-toggle');
biometricsToggle.style.display = 'none';
}
return true;
} catch (error) {
console.error('Error dropping item:', error);
return false;
}
}
// Function to initialize the toggle buttons container // Function to initialize the toggle buttons container
function initializeToggleButtons() { function initializeToggleButtons() {
// Set up notes toggle button // Set up notes toggle button