Skip to content

davismiler/poke-flip

Repository files navigation

Pokeflip Memory Game

📋 Project Overview

Pokeflip is a Pokemon-themed memory card matching game built with Vue 3 and Tailwind CSS. Players flip cards to find matching Pokemon pairs while tracking their progress, moves, and scores.

🏗️ Architecture & Structure

Tech Stack

  • Framework: Vue 3 (Composition API)
  • Build Tool: Vite 2.8.4
  • Styling: Tailwind CSS 3.0 with custom theme system
  • Fonts: Inter (replaced Press Start 2P)
  • Additional: canvas-confetti for celebration effects

Project Structure

src/
├── App.vue                 # Main application component (game logic)
├── main.js                 # Application entry point
├── assets/
│   ├── tailwind.css       # Global styles + theme system
│   └── sounds/            # Audio files (music, effects)
├── components/
│   ├── PokeCard.vue       # Individual card with flip animation
│   ├── PokeCardImg.vue    # Pokemon image loader
│   ├── PokeGameBox.vue    # Card grid container
│   ├── PokeGameContain.vue # Game area wrapper
│   ├── PokeGameStatus.vue # Score/moves display
│   ├── PokeSidebar.vue    # Settings sidebar
│   ├── PokeSidebarControls.vue # Game controls
│   ├── PokeSidebarSelect.vue # Settings selector
│   ├── PokeSidebarSelectItem.vue # Individual setting option
│   ├── PokeEndGameResults.vue # Results modal
│   ├── PokeSoundConfigure.vue # Audio settings
│   ├── PokeHelper.vue     # Sound helper button
│   ├── PokeHeader.vue     # App header
│   ├── PokeFooter.vue     # App footer
│   ├── PokeLogo.vue       # Logo component
│   ├── PokeCardNotData.vue # Empty state
│   ├── TheButton.vue      # Reusable button component
│   └── ui/
│       └── Modal.vue      # Modal wrapper
├── data/
│   └── pokemonData.js     # Pokemon data generator
├── helpers/
│   └── getRandomNumbers.js # Random number generator
└── utils/
    └── confetti.js        # Celebration effect

🎮 Game Features

Core Gameplay

  1. Card Matching: Flip cards to find matching Pokemon pairs
  2. Difficulty Levels:
    • Normal: Cards stay in place when matched
    • Hard: Cards shuffle after each match
    • Extreme: Cards shuffle after every move (including wrong guesses)
  3. Card Quantities: 8, 12, or 16 cards (4, 6, or 8 pairs)
  4. Progress Tracking:
    • Completed pairs counter
    • Total moves counter
    • Scoring system based on cards/moves ratio

UI Features

  • Responsive Design: Desktop-only (mobile shows message)
  • Color-Coded Settings:
    • Difficulty: Green (normal), Yellow (hard), Red (extreme)
    • Quantity: Blue (8), Purple (12), Pink (16)
  • Animations: Card flip, transitions, confetti on win
  • Sound System: Background music + action sounds with volume controls
  • Results System: Ranked scoring (Champion, Master, Legend, Divine)

🔧 Technical Implementation

State Management

  • Pattern: Local component state using Vue 3 Composition API
  • State Storage:
    • ref() for reactive primitives
    • ref({}) for objects
    • localStorage for sound preferences persistence
  • Key State Variables:
    - pokemons: ref([])           // Card array
    - isGameStart: ref(false)     // Game state
    - isComparing: ref(false)     // Comparison lock
    - evaluatePokemons: ref([])   // Cards being compared
    - pokeStatus: ref({})         // Score tracking

Game Logic Flow

  1. Initialization: User selects difficulty & quantity
  2. Start: Generates random Pokemon pairs, shuffles, displays cards
  3. Selection: User clicks cards (max 2 at a time)
  4. Comparison:
    • Match → Cards stay visible, increment score
    • No match → Cards flip back, increment moves
  5. Difficulty Effects: Shuffle behavior based on difficulty
  6. Win Condition: All pairs found → Show results modal

Data Flow

App.vue (Central State)
    ↓
PokeSidebarSelect → Difficulty/Quantity Selection
    ↓
PokeSidebarControls → Game Actions (Start/Restart/Finish)
    ↓
PokeCard → Card Selection Event
    ↓
App.vue → Comparison Logic
    ↓
PokeGameStatus → Display Progress
    ↓
PokeEndGameResults → Show Final Score

🎨 Design System

Theme Configuration

  • CSS Variables: HSL-based color system
  • Dark Theme: Primary (dark purple/blue tones)
  • Components: Card, border, foreground, muted variants
  • Custom Class: bg-custom with glassmorphic effect

Typography

  • Primary Font: Inter (replaces pixel font)
  • Font Features: Ligatures, contextual alternates
  • Sizes: Responsive with Tailwind utilities

Color System

  • Uses CSS custom properties for theming
  • Supports light/dark mode (class-based)
  • Gradient backgrounds for depth

📊 Code Quality Analysis

Strengths

  1. Component Organization: Well-structured, reusable components
  2. Modern Vue 3: Uses Composition API effectively
  3. Clean Separation: Logic, presentation, and utilities separated
  4. Responsive Design: Tailwind utilities for layout
  5. Accessibility: Semantic HTML, proper alt texts
  6. Performance:
    • Vite for fast builds
    • Efficient reactivity system
    • Optimized re-renders

Areas for Improvement ⚠️

1. Code Organization

  • Issue: All game logic in App.vue (300+ lines)
  • Solution: Extract to composable (useGameLogic.js)
  • Benefit: Better testability, reusability

2. State Management

  • Issue: Prop drilling, local state only
  • Solution: Consider Pinia for complex state or composables
  • Benefit: Better state sharing, devtools support

3. Type Safety

  • Issue: No TypeScript
  • Solution: Migrate to Vue 3 + TypeScript
  • Benefit: Better IDE support, fewer runtime errors

4. Testing

  • Issue: No test files found
  • Solution: Add Vitest + Vue Test Utils
  • Benefit: Automated testing, regression prevention

5. Error Handling

  • Issue: No error boundaries or validation
  • Solution: Add try-catch, input validation
  • Benefit: Better UX, easier debugging

6. Performance Optimizations

// Current: Linear search
const indexPokemon = pokemons.value.findIndex(({ key }) => key === pokemon.key)

// Better: Use Map for O(1) lookup
const pokemonMap = new Map(pokemons.value.map(p => [p.key, p]))

7. Accessibility

  • Missing: Keyboard navigation, ARIA labels
  • Solution: Add keyboard support, screen reader labels
  • Benefit: WCAG compliance

8. Code Consistency

  • Issue: Mixed naming conventions (some camelCase, some kebab-case)
  • Solution: Enforce ESLint rules
  • Benefit: Better readability

9. Magic Numbers

  • Issue: Hardcoded values (timeouts, card counts)
  • Solution: Extract to constants file
  • Benefit: Easier configuration

10. Pokemon API

  • Issue: Images from external CDN (could fail)
  • Solution:
    • Download and bundle images
    • Add fallback images
    • Use local image storage

🐛 Potential Bugs

  1. Random Number Generator:

    // Could potentially infinite loop if all numbers used
    while (arrNumbers.length < cant) { /* ... */ }
    • Fix: Add max iterations or use Set
  2. Card Shuffling:

    // Not cryptographically secure, but acceptable for games
    arr.sort(() => Math.random() - 0.5)
  3. Sound Management:

    • No check if audio files exist
    • Could fail silently
  4. LocalStorage:

    • No error handling for quota exceeded
    • Could break on private browsing

📈 Performance Metrics

Bundle Size (Estimated)

  • Core Vue: ~35KB (gzipped)
  • Tailwind CSS: ~10KB (purged)
  • Assets: Audio files (~100-500KB)

Optimization Opportunities

  1. Code Splitting: Lazy load modals
  2. Image Optimization: WebP format, lazy loading
  3. Tree Shaking: Ensure unused code removed
  4. Asset Compression: Optimize audio files

🔐 Security Considerations

  1. XSS: Vue escapes by default ✅
  2. External Resources: Pokemon images from external CDN
  3. LocalStorage: Only stores preferences (low risk)
  4. No Backend: Client-side only (reduces attack surface)

📝 Documentation Status

  • README: Minimal (Spanish TODO)
  • Code Comments: Sparse
  • Component Docs: None
  • API Docs: N/A (no backend)

🚀 Recommended Improvements

Priority 1 (Critical)

  1. Add error handling for API/image loading
  2. Extract game logic to composable
  3. Add input validation
  4. Improve README documentation

Priority 2 (High)

  1. Add unit tests
  2. Implement keyboard navigation
  3. Add loading states
  4. Optimize images

Priority 3 (Nice to Have)

  1. Add TypeScript
  2. Implement Pinia for state
  3. Add animations library (Framer Motion alternative)
  4. Add analytics tracking
  5. Implement PWA features

📦 Dependencies Analysis

Production Dependencies

  • vue@^3.2.31: ✅ Latest stable
  • canvas-confetti@^1.5.1: ✅ Well-maintained

Dev Dependencies

  • vite@^2.8.4: ⚠️ Could upgrade to v4/v5
  • tailwindcss@^3.0.23: ⚠️ Could upgrade to latest
  • @vitejs/plugin-vue@^2.2.2: ⚠️ Could upgrade

Recommendation: Update dependencies regularly for security patches

🎯 Conclusion

Overall Assessment: ⭐⭐⭐⭐ (4/5)

This is a well-structured, modern Vue 3 application with clean code organization and good use of composition API. The UI is polished with thoughtful animations and sound effects. The main areas for improvement are:

  1. Code organization (extract logic from App.vue)
  2. Testing (add unit/integration tests)
  3. Documentation (improve README)
  4. Error handling (add validation and fallbacks)

The project demonstrates solid understanding of Vue 3 best practices and modern web development patterns. With the suggested improvements, it could be production-ready.


Analysis Date: $(date) Project Version: 0.0.0 Lines of Code: ~2,500+ (estimated)

About

Pokeflip is a Pokemon-themed memory matching game built with Vue 3 and Tailwind CSS.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published