diff --git a/src/App.vue b/src/App.vue
index a1165d5..e428051 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -8,7 +8,16 @@ import { usePetSystem } from './composables/usePetSystem';
const currentScreen = ref('game');
const petGameRef = ref(null);
-const showStats = ref(false); // Stats visibility
+const statsMode = ref('none'); // 'none', 'bars', 'details'
+
+// Menu State
+const isMenuOpen = ref(false);
+const selectedMenuIndex = ref(0);
+// Combined menu items: Top (0-3) + Bottom (4-7)
+const MENU_ITEMS = [
+ 'stats', 'feed', 'play', 'sleep', // Top Menu
+ 'clean', 'medicine', 'training', 'info' // Action Menu
+];
// Initialize Pet System
const {
@@ -24,8 +33,48 @@ const {
reset
} = usePetSystem();
+// Handle Physical Buttons
+function handleButton(btnId) {
+ console.log('Button pressed:', btnId);
+
+ // 0. Check if PetGame wants to handle the input (e.g. Prayer Menu, Minigames)
+ if (petGameRef.value && petGameRef.value.handleInput) {
+ if (petGameRef.value.handleInput(btnId)) {
+ return; // Input handled by game component
+ }
+ }
+
+ // 1. Idle State (Menu Closed)
+ if (!isMenuOpen.value) {
+ if (btnId === 1) {
+ // Button 1: Open Menu
+ isMenuOpen.value = true;
+ selectedMenuIndex.value = 0; // Default to first item
+ }
+ // Buttons 2 & 3 do nothing in idle state (or could trigger other things)
+ return;
+ }
+
+ // 2. Menu Active State
+ if (isMenuOpen.value) {
+ if (btnId === 2) {
+ // Button 2: Left (Previous)
+ selectedMenuIndex.value = (selectedMenuIndex.value - 1 + MENU_ITEMS.length) % MENU_ITEMS.length;
+ } else if (btnId === 3) {
+ // Button 3: Right (Next)
+ selectedMenuIndex.value = (selectedMenuIndex.value + 1) % MENU_ITEMS.length;
+ } else if (btnId === 1) {
+ // Button 1: Confirm
+ const action = MENU_ITEMS[selectedMenuIndex.value];
+ handleAction(action);
+ isMenuOpen.value = false; // Close menu after selection
+ }
+ }
+}
+
// Handle Action Menu Events
function handleAction(action) {
+ console.log('Action triggered:', action);
switch(action) {
case 'feed':
const feedResult = feed();
@@ -51,8 +100,25 @@ function handleAction(action) {
}
break;
case 'stats':
- // Toggle stats display
- showStats.value = !showStats.value;
+ // Toggle stats mode: none -> bars -> details -> none
+ if (statsMode.value === 'none') statsMode.value = 'bars';
+ else if (statsMode.value === 'bars') statsMode.value = 'details';
+ else statsMode.value = 'none';
+ break;
+ case 'info':
+ // Show info (same as stats details for now, or separate)
+ if (statsMode.value !== 'details') statsMode.value = 'details';
+ else statsMode.value = 'none';
+ break;
+ case 'training':
+ // Show Prayer Menu (handled in PetGame via prop or event?)
+ // We need to pass this down or handle it here.
+ // Currently PetGame handles 'training' event to show menu.
+ // We can just emit the action to PetGame if we move logic there,
+ // or better, expose a method on PetGame.
+ if (petGameRef.value) {
+ petGameRef.value.openPrayerMenu();
+ }
break;
case 'settings':
// Show reset options
@@ -62,16 +128,6 @@ function handleAction(action) {
reset();
}
break;
- case 'jiaobei':
- // 擲筊功能 - 待實作
- console.log('擲筊功能');
- // TODO: 實作擲筊邏輯
- break;
- case 'fortune':
- // 求籤功能 - 待實作
- console.log('求籤功能');
- // TODO: 實作求籤邏輯
- break;
default:
console.log('Action not implemented:', action);
}
@@ -84,7 +140,7 @@ function setPetState(newState) {
-
+
diff --git a/src/components/ActionMenu.vue b/src/components/ActionMenu.vue
index 2d323db..ca59a01 100644
--- a/src/components/ActionMenu.vue
+++ b/src/components/ActionMenu.vue
@@ -1,9 +1,33 @@
@@ -24,6 +48,14 @@ const props = defineProps({
isSick: {
type: Boolean,
default: false
+ },
+ isMenuOpen: {
+ type: Boolean,
+ default: false
+ },
+ selectedIndex: {
+ type: Number,
+ default: 0
}
});
@@ -48,10 +80,20 @@ defineEmits(['clean', 'medicine', 'training', 'info']);
cursor: pointer;
position: relative;
padding: 0;
+ opacity: 0.5; /* Default dim */
+ transition: opacity 0.2s, transform 0.2s;
+}
+
+.icon-btn.active {
+ opacity: 1;
+ transform: scale(1.1);
+ filter: drop-shadow(0 0 2px rgba(0,0,0,0.5));
+ background: rgba(255, 255, 255, 0.5);
+ border-radius: 4px;
}
.icon-btn:disabled {
- opacity: 0.3;
+ opacity: 0.2;
cursor: not-allowed;
}
diff --git a/src/components/DeviceShell.vue b/src/components/DeviceShell.vue
index 25e87c5..6175bc3 100644
--- a/src/components/DeviceShell.vue
+++ b/src/components/DeviceShell.vue
@@ -7,9 +7,9 @@
diff --git a/src/components/FortuneStickAnimation.vue b/src/components/FortuneStickAnimation.vue
index f490b86..07bcf97 100644
--- a/src/components/FortuneStickAnimation.vue
+++ b/src/components/FortuneStickAnimation.vue
@@ -22,13 +22,13 @@
-
-
+
+
-
+
@@ -37,6 +37,13 @@
diff --git a/src/components/PrayerMenu.vue b/src/components/PrayerMenu.vue
index 36b91cc..cf25fd8 100644
--- a/src/components/PrayerMenu.vue
+++ b/src/components/PrayerMenu.vue
@@ -6,6 +6,7 @@