${item.qty || 1}
${item.itemName} ×${item.qty || 1}
@@ -54,11 +70,57 @@ export class Backpack {
);
}
}
+ this.saveInventoryState(this.inventory);
+ }
+
+ saveInventoryState() {
const newState = getGameState();
newState.player.backpack.items = this.inventory;
setGameState(newState);
}
+ selectItem(slotEl) {
+ const itemId = slotEl.getAttribute('data-id');
+ selectedItem = itemId;
+ // deselect others
+ const slots = document.querySelectorAll(
+ '#backpack-content .inventory-slot:not(.empty)'
+ );
+ slots.forEach((item) => {
+ item.classList.remove('selected');
+ });
+ //higlight selected item
+ slotEl.classList.add('selected');
+ }
+
+ decreaseItemQty(itemId) {
+ const ind = this.inventory.findIndex(
+ (item) => item.itemName === itemId
+ );
+
+ if (ind != -1) {
+ if (this.inventory[ind].qty >= 2) {
+ --this.inventory[ind].qty;
+ } else {
+ //remove item
+ this.inventory.splice(ind, 1);
+ selectedItem = null;
+ }
+ this.saveInventoryState();
+ this.render();
+ }
+ }
+
+ useItem() {
+ if (!selectedItem) return;
+ const action = itemsMap[selectedItem];
+ action?.();
+ // Decrease the qty
+ this.decreaseItemQty(selectedItem);
+ }
+
+ dropItem() {}
+
render() {
const backpack = document.getElementById('backpack-content');
backpack.style.display = 'flex';
@@ -79,10 +141,7 @@ export class Backpack {
static getInstance() {
const gameState = getGameState();
if (gameState.player.backpack) {
- return new Backpack(
- gameState.player.backpack.items,
- gameState.player.backpack.maxSlots
- );
+ return new Backpack(gameState.player.backpack.maxSlots);
}
return false;
}
@@ -99,34 +158,35 @@ export class Backpack {
items: [],
maxSlots: 20,
};
+ saveGameState(gameState);
}
- handleCloseBackpack() {
- if (!k.isFocused()) {
- k.pressButton('backpack');
- k.canvas.focus();
+ handleDocumentKeypress(e) {
+ if (e.key == 'i') {
+ //workaround for press backpack key if canvas lose the focus
+ if (!k.isFocused()) {
+ k.canvas.focus();
+ k.pressButton('backpack');
+ }
+ } else if (e.key == 'r') {
+ this.useItem();
}
}
openBackpack() {
this.render();
- document.addEventListener('keypress', this.handleCloseBackpack);
- const inventoryCloseBtn = document.getElementById(
- 'inventory-close-btn'
+ document.addEventListener(
+ 'keypress',
+ this.handleDocumentKeypress.bind(this)
);
- inventoryCloseBtn.addEventListener('click', this.handleCloseBackpack);
isOpened = true;
}
hideBackpack() {
this.hide();
- document.removeEventListener('keypress', this.handleCloseBackpack);
- const inventoryCloseBtn = document.getElementById(
- 'inventory-close-btn'
- );
- inventoryCloseBtn.removeEventListener(
- 'click',
- this.handleCloseBackpack
+ document.removeEventListener(
+ 'keypress',
+ this.handleDocumentKeypress.bind(this)
);
isOpened = false;
}
@@ -134,11 +194,36 @@ export class Backpack {
static init() {
const instance = Backpack.getInstance();
if (instance) {
- backpackBtn.style.display = 'block';
+ Backpack.showButton();
backpackBtn.addEventListener('click', () => {
instance.openBackpack();
});
+
+ const inventoryCloseBtn = document.getElementById(
+ 'inventory-close-btn'
+ );
+ const useItem = document.getElementById('item-use-btn');
+ const dropItem = document.getElementById('item-drop-btn');
+ inventoryCloseBtn.addEventListener(
+ 'click',
+ instance.hideBackpack.bind(instance)
+ );
+ useItem.addEventListener('click', instance.useItem.bind(instance));
+ dropItem.addEventListener(
+ 'click',
+ instance.dropItem.bind(instance)
+ );
+
+ document
+ .getElementById('backpack-content')
+ .addEventListener('click', (e) => {
+ const slot = e.target.closest(
+ '.inventory-slot:not(.empty)'
+ );
+ if (!slot) return;
+ instance.selectItem(slot);
+ });
}
}
@@ -157,11 +242,6 @@ export class Backpack {
static showButton() {
backpackBtn.style.display = 'block';
-
- const instance = Backpack.getInstance();
- backpackBtn.addEventListener('click', () => {
- instance.openBackpack();
- });
}
static removeButton() {
diff --git a/src/interactions/map_campus_house_1/backpack.interaction.js b/src/interactions/map_campus_house_1/backpack.interaction.js
index d068fb9..1906964 100644
--- a/src/interactions/map_campus_house_1/backpack.interaction.js
+++ b/src/interactions/map_campus_house_1/backpack.interaction.js
@@ -14,10 +14,10 @@ export const backpackInteractions = (player, k, map) => {
const dialog = [];
if (wantBackpack) {
- Backpack.initState();
k.destroy(backpack);
// show backpack on side right panel
- Backpack.showButton();
+ Backpack.initState();
+ Backpack.init();
dialog.push('Aye, a trusty pack for a worthy traveler.');
} else {
diff --git a/src/styles/backpack.css b/src/styles/backpack.css
index ff4d3fd..9ba96b4 100644
--- a/src/styles/backpack.css
+++ b/src/styles/backpack.css
@@ -47,8 +47,6 @@
.backpack-frame .backpack-container {
padding: 0 16px 16px 16px;
- max-height: 300px;
- overflow: auto;
}
.backpack-frame .backpack-graphic {
@@ -92,6 +90,11 @@
position: relative;
}
+.backpack-frame .inventory-slot.selected,
+.backpack-frame .inventory-slot.selected:hover {
+ background: #48d387;
+}
+
.backpack-frame .inventory-slot:hover {
background: #2d7a4f;
transform: translateY(-2px);
@@ -202,26 +205,63 @@
cursor: pointer;
}
-@media (max-width: 600px) {
+/* Adding responsive CSS media queries for mobile devices */
+@media (max-width: 768px) {
+ #backpack-content .backpack-frame {
+ width: 90vw;
+ max-width: 400px;
+ }
+
.backpack-frame .inventory-grid {
- grid-template-columns: repeat(4, 1fr);
- gap: 8px;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 6px;
+ }
+}
+
+@media (max-width: 480px) {
+ #backpack-content .backpack-frame {
+ width: 70vw;
+ border: 6px solid #2a1a42;
}
- .backpack-frame .title-bar h1 {
- font-size: 16px;
- letter-spacing: 2px;
+ .backpack-frame .title-bar {
+ font-size: 14px;
+ padding: 8px 10px;
+ letter-spacing: 0.5px;
}
.backpack-frame .backpack-container {
- max-height: 180px;
+ padding: 12px;
+ }
+
+ .backpack-frame .inventory-grid {
+ grid-template-columns: repeat(4, 1fr);
+ gap: 5px;
+ margin-bottom: 12px;
}
- .backpack-frame .inventory-slot {
- font-size: 24px;
+ .backpack-frame .backpack-flap {
+ height: 10px;
+ margin-bottom: 8px;
}
+}
- .backpack-frame .footer button {
- font-size: 10px;
+/* Adding landscape mobile optimization */
+@media (max-height: 800px) {
+ #backpack-content .backpack-frame {
+ width: 85vw;
+ max-width: 600px;
+ margin: 10px auto;
+ }
+
+ .backpack-frame .backpack-flap {
+ height: 12px;
+ margin-bottom: 6px;
+ }
+
+ .backpack-frame .inventory-grid {
+ grid-template-columns: repeat(10, 1fr);
+ gap: 6px;
+ margin-bottom: 8px;
}
}