feat: implement Pixel Slide puzzle game with procedural art generation and Web Audio engine
This commit is contained in:
@@ -0,0 +1,136 @@
|
|||||||
|
# ๐งฉ PixelSlide โ 15-Puzzle Image Game with PixiJS
|
||||||
|
|
||||||
|
> A premium sliding puzzle game built with **PixiJS v8**, Vanilla HTML5/CSS3/JavaScript, procedural canvas artwork, soundtrack integration, and a persistent local leaderboard.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## โจ Features
|
||||||
|
|
||||||
|
- **๐ผ๏ธ Custom Image Slicing**:
|
||||||
|
- Upload any image (PNG, JPG, WebP, GIF) via file picker or drag-and-drop.
|
||||||
|
- Automatically center-crops and slices into grid tiles.
|
||||||
|
- Comes with 4 built-in procedural gallery presets (*Neon City*, *Deep Galaxy*, *Hex Prism*, *Aurora Peak*) for instant offline play.
|
||||||
|
- **๐ฎ 5 Difficulty Levels**:
|
||||||
|
- ๐ **Debug Mode (3ร3)**: Starts from solved state and performs 5 non-reversing valid moves (guaranteed solvable in **โค 5 moves**).
|
||||||
|
- ๐ข **Easy (3ร3)**: 8 tiles + 1 blank, 30 valid shuffle moves.
|
||||||
|
- ๐ต **Medium (4ร4)**: Classic 15-puzzle (15 tiles + 1 blank), 100 valid shuffle moves.
|
||||||
|
- ๐ฃ **Hard (5ร5)**: 24 tiles + 1 blank, 200 valid shuffle moves.
|
||||||
|
- ๐ด **Insane (6ร6)**: 35 tiles + 1 blank, 400 valid shuffle moves.
|
||||||
|
- **โก 100% Solvability Guarantee**:
|
||||||
|
- Shuffling simulates valid legal moves from the solved board state to ensure the puzzle is always solvable without parity issues.
|
||||||
|
- **๐จ Ultra-Smooth PixiJS v8 Rendering**:
|
||||||
|
- High-DPI canvas rendering with hardware acceleration.
|
||||||
|
- 60FPS smooth lerp/easing tile sliding animations.
|
||||||
|
- **๐ต Sound System & Soundtracks**:
|
||||||
|
- Background music ([`assets/sounds/backsound.mp3`](assets/sounds/backsound.mp3)) with auto-looping and browser autoplay-policy handling.
|
||||||
|
- Victory fanfare ([`assets/sounds/winner.mp3`](assets/sounds/winner.mp3)) upon solving.
|
||||||
|
- Native Web Audio synthesizer for tile slides, clicks, and invalid move bumps.
|
||||||
|
- Persistent sound toggle (`๐` / `๐`).
|
||||||
|
- **๐ Persistent Leaderboard**:
|
||||||
|
- High scores saved in browser `localStorage`.
|
||||||
|
- Filterable by difficulty (All, Debug, Easy, Medium, Hard, Insane).
|
||||||
|
- Sorted by fastest completion time and least moves made.
|
||||||
|
- **๐ก Helper Tools & Accessibility**:
|
||||||
|
- `#๏ธโฃ` **Tile Numbers Toggle**: Overlay numbering (1 to N-1) for challenging abstract images.
|
||||||
|
- `๐๏ธ` **Ghost Image Hint**: Semi-transparent reference overlay of the full image.
|
||||||
|
- `โฑ๏ธ` **Millisecond-Precision Timer**: Starts on the very first move.
|
||||||
|
- `๐` **Quick Restart**: Re-shuffle the same image and reset stats with one click.
|
||||||
|
- `โธ๏ธ` **Pause Modal**: Stops the clock when taking a break.
|
||||||
|
- `๐` **Confetti Burst**: Physics-based canvas confetti explosion on victory.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ๐ Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
eigen_vibe_code_competition/
|
||||||
|
โโโ index.html # Main HTML markup, HUD, modals, and screen containers
|
||||||
|
โโโ style.css # Cyber dark theme, glassmorphism, responsive grid, animations
|
||||||
|
โโโ game.js # PixiJS v8 setup, puzzle engine, Web Audio, leaderboard logic
|
||||||
|
โโโ assets/
|
||||||
|
โ โโโ sounds/
|
||||||
|
โ โโโ backsound.mp3 # Looping background soundtrack
|
||||||
|
โ โโโ winner.mp3 # Victory celebration audio track
|
||||||
|
โโโ README.md # Project documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ๐ How to Run the Project
|
||||||
|
|
||||||
|
Since the project uses ES6 features and fetches audio assets / PixiJS canvas textures, it should be run through a local HTTP server.
|
||||||
|
|
||||||
|
### Option 1: Python (Recommended, no installation required)
|
||||||
|
|
||||||
|
If you have Python installed, run in your terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Python 3
|
||||||
|
python3 -m http.server 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open your browser at:
|
||||||
|
๐ **[http://localhost:8080](http://localhost:8080)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 2: Node.js (`npx serve` or `npx http-server`)
|
||||||
|
|
||||||
|
If you have Node.js installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx serve . -p 8080
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
npx http-server -p 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open **[http://localhost:8080](http://localhost:8080)**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 3: VS Code Live Server
|
||||||
|
|
||||||
|
1. Open the project folder in **Visual Studio Code**.
|
||||||
|
2. Install the **Live Server** extension (by Ritwick Dey).
|
||||||
|
3. Right-click [`index.html`](index.html) and select **"Open with Live Server"**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ๐ฎ Controls & Shortcuts
|
||||||
|
|
||||||
|
| Input / Key | Action |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **Mouse Click / Tap** | Slide adjacent tile into the blank slot |
|
||||||
|
| <kbd>โ</kbd> / <kbd>W</kbd> | Move tile below blank upwards |
|
||||||
|
| <kbd>โ</kbd> / <kbd>S</kbd> | Move tile above blank downwards |
|
||||||
|
| <kbd>โ</kbd> / <kbd>A</kbd> | Move tile on right to the left |
|
||||||
|
| <kbd>โ</kbd> / <kbd>D</kbd> | Move tile on left to the right |
|
||||||
|
| <kbd>N</kbd> | Toggle tile number overlays (`#๏ธโฃ`) |
|
||||||
|
| <kbd>H</kbd> | Toggle ghost image hint (`๐๏ธ`) |
|
||||||
|
| <kbd>R</kbd> | Quick restart level (`๐`) |
|
||||||
|
| <kbd>M</kbd> | Toggle audio mute (`๐`/`๐`) |
|
||||||
|
| <kbd>Esc</kbd> | Pause / Resume game (`โธ๏ธ`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ๐ ๏ธ Technology Stack
|
||||||
|
|
||||||
|
- **Rendering Engine**: [PixiJS v8.20.0](https://pixijs.com/) via CDN
|
||||||
|
- **Structure & Logic**: Vanilla HTML5, Vanilla JavaScript (ES6+ Classes)
|
||||||
|
- **Styling**: Vanilla CSS3 (Custom Properties, Glassmorphism `backdrop-filter`, Flexbox, CSS Grid)
|
||||||
|
- **Typography**: Google Fonts (*Outfit*, *Inter*)
|
||||||
|
- **Audio**: HTML5 Audio API & Web Audio API Synthesizer
|
||||||
|
- **Storage**: Browser `localStorage` API
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ๐ License
|
||||||
|
|
||||||
|
Distributed under the MIT License. Feel free to use and customize for your own projects!
|
||||||
Binary file not shown.
Binary file not shown.
+328
@@ -0,0 +1,328 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>Pixel Slide โ Premium 15-Puzzle Game</title>
|
||||||
|
<meta name="description" content="Experience the ultimate sliding puzzle game powered by PixiJS. Slices any custom image into dynamic sliding tiles across multiple difficulty levels." />
|
||||||
|
|
||||||
|
<!-- Google Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700;800;900&display=swap" rel="stylesheet" />
|
||||||
|
|
||||||
|
<!-- PixiJS v8.20.0 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/pixi.js@8.20.0/dist/pixi.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Stylesheet -->
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Ambient background glow particles / decorative elements -->
|
||||||
|
<div class="ambient-bg">
|
||||||
|
<div class="glow-orb orb-1"></div>
|
||||||
|
<div class="glow-orb orb-2"></div>
|
||||||
|
<div class="glow-orb orb-3"></div>
|
||||||
|
<div class="grid-overlay"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="app-root">
|
||||||
|
<!-- TOP NAVIGATION BAR -->
|
||||||
|
<header class="app-header">
|
||||||
|
<div class="logo-group" id="btn-nav-home" role="button" tabindex="0" title="Return to Home">
|
||||||
|
<div class="logo-icon">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<rect x="3" y="3" width="7" height="7" rx="1.5"></rect>
|
||||||
|
<rect x="14" y="3" width="7" height="7" rx="1.5"></rect>
|
||||||
|
<rect x="3" y="14" width="7" height="7" rx="1.5"></rect>
|
||||||
|
<rect x="14" y="14" width="7" height="7" rx="1.5" stroke-dasharray="2 2"></rect>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span class="logo-text">PIXEL<span class="logo-highlight">SLIDE</span></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-controls">
|
||||||
|
<button id="btn-sound-toggle" class="icon-btn" title="Toggle Sound (M)" aria-label="Toggle Sound">
|
||||||
|
<span id="sound-icon">๐</span>
|
||||||
|
</button>
|
||||||
|
<button id="btn-header-leaderboard" class="glass-pill-btn" title="View Leaderboard">
|
||||||
|
<span>๐</span> Leaderboard
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- SCREEN: HOME -->
|
||||||
|
<main id="screen-home" class="screen active">
|
||||||
|
<div class="hero-section">
|
||||||
|
<h1 class="hero-title">
|
||||||
|
Master the <span class="gradient-text">Art of Sliding</span>
|
||||||
|
</h1>
|
||||||
|
<p class="hero-subtitle">
|
||||||
|
Upload any picture or choose from gallery presets. Sliced, shuffled, and rendered with ultra-smooth 60FPS physics.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Image source selection -->
|
||||||
|
<div class="upload-container">
|
||||||
|
<div class="upload-dropzone" id="upload-dropzone">
|
||||||
|
<input type="file" id="file-input" accept="image/*" class="visually-hidden" />
|
||||||
|
<div class="dropzone-icon">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||||
|
<polyline points="17 8 12 3 7 8"></polyline>
|
||||||
|
<line x1="12" y1="3" x2="12" y2="15"></line>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="dropzone-text">
|
||||||
|
<strong>Click to upload</strong> or drag and drop an image
|
||||||
|
</div>
|
||||||
|
<div class="dropzone-hint">Supports PNG, JPG, WebP, GIF (Max 15MB)</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="preset-divider">
|
||||||
|
<span>OR CHOOSE A PRESET IMAGE</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="preset-gallery" id="preset-gallery">
|
||||||
|
<!-- Preset items will be injected by JS -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- SCREEN: LEVEL SELECT -->
|
||||||
|
<section id="screen-level-select" class="screen">
|
||||||
|
<div class="screen-header">
|
||||||
|
<button id="btn-back-to-home" class="back-btn">
|
||||||
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
||||||
|
</svg>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<div class="screen-title-group">
|
||||||
|
<h2>Select Difficulty</h2>
|
||||||
|
<p>Pick your grid complexity and test your spatial reasoning.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="level-selection-layout">
|
||||||
|
<div class="image-preview-card">
|
||||||
|
<div class="preview-header">
|
||||||
|
<span>Selected Image</span>
|
||||||
|
<button id="btn-change-image" class="text-link-btn">Change</button>
|
||||||
|
</div>
|
||||||
|
<div class="preview-canvas-wrapper">
|
||||||
|
<canvas id="preview-canvas"></canvas>
|
||||||
|
<div class="preview-grid-overlay" id="preview-grid-overlay"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="level-cards-grid" id="level-cards-grid">
|
||||||
|
<!-- Level Cards rendered by JS -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- SCREEN: GAMEPLAY -->
|
||||||
|
<section id="screen-game" class="screen">
|
||||||
|
<!-- HUD BAR -->
|
||||||
|
<div class="game-hud">
|
||||||
|
<div class="hud-left">
|
||||||
|
<button id="btn-game-pause" class="hud-btn pause-hud-btn" title="Pause Game (Esc)">
|
||||||
|
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<rect x="6" y="4" width="4" height="16" rx="1"></rect>
|
||||||
|
<rect x="14" y="4" width="4" height="16" rx="1"></rect>
|
||||||
|
</svg>
|
||||||
|
<span>Pause</span>
|
||||||
|
</button>
|
||||||
|
<div class="level-badge" id="hud-level-badge">Medium 4ร4</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hud-center">
|
||||||
|
<div class="stat-box timer-box">
|
||||||
|
<span class="stat-label">TIME</span>
|
||||||
|
<span class="stat-value" id="hud-timer">00:00.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-box moves-box">
|
||||||
|
<span class="stat-label">MOVES</span>
|
||||||
|
<span class="stat-value" id="hud-moves">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hud-right">
|
||||||
|
<button id="btn-toggle-numbers" class="hud-btn icon-only" title="Toggle Tile Numbers (N)" aria-label="Toggle Numbers">
|
||||||
|
<span class="btn-icon">#๏ธโฃ</span>
|
||||||
|
</button>
|
||||||
|
<button id="btn-toggle-hint" class="hud-btn icon-only" title="Toggle Image Ghost Hint (H)" aria-label="Toggle Hint">
|
||||||
|
<span class="btn-icon">๐๏ธ</span>
|
||||||
|
</button>
|
||||||
|
<button id="btn-game-restart-quick" class="hud-btn icon-only" title="Restart Level (R)" aria-label="Restart Level">
|
||||||
|
<span class="btn-icon">๐</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- MAIN PUZZLE CANVAS CONTAINER -->
|
||||||
|
<div class="puzzle-viewport-container">
|
||||||
|
<div class="puzzle-board-frame" id="puzzle-board-frame">
|
||||||
|
<div id="pixi-canvas-mount"></div>
|
||||||
|
<!-- Ghost image overlay for hints -->
|
||||||
|
<div id="ghost-overlay" class="ghost-overlay"></div>
|
||||||
|
<!-- Shuffling overlay -->
|
||||||
|
<div id="shuffle-overlay" class="shuffle-overlay">
|
||||||
|
<div class="shuffle-spinner"></div>
|
||||||
|
<span>Shuffling tiles...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- BOTTOM CONTROL BAR -->
|
||||||
|
<div class="game-footer-info">
|
||||||
|
<span class="tip-text">๐ก Tap adjacent tiles or use <kbd>Arrow Keys</kbd> / <kbd>WASD</kbd> to slide</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- SCREEN: LEADERBOARD -->
|
||||||
|
<section id="screen-leaderboard" class="screen">
|
||||||
|
<div class="screen-header">
|
||||||
|
<button id="btn-back-from-leaderboard" class="back-btn">
|
||||||
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
||||||
|
</svg>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<div class="screen-title-group">
|
||||||
|
<h2>Hall of Fame</h2>
|
||||||
|
<p>Global high scores sorted by fastest completion time and move count.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="leaderboard-container glass-card">
|
||||||
|
<div class="leaderboard-tabs" id="leaderboard-tabs">
|
||||||
|
<button class="tab-btn active" data-level="all">All Levels</button>
|
||||||
|
<button class="tab-btn" data-level="debug">Debug</button>
|
||||||
|
<button class="tab-btn" data-level="easy">Easy (3ร3)</button>
|
||||||
|
<button class="tab-btn" data-level="medium">Medium (4ร4)</button>
|
||||||
|
<button class="tab-btn" data-level="hard">Hard (5ร5)</button>
|
||||||
|
<button class="tab-btn" data-level="insane">Insane (6ร6)</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="leaderboard-table-wrapper">
|
||||||
|
<table class="leaderboard-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Rank</th>
|
||||||
|
<th>Player</th>
|
||||||
|
<th>Difficulty</th>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Moves</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="leaderboard-tbody">
|
||||||
|
<!-- Entries injected by JS -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div id="leaderboard-empty" class="leaderboard-empty">
|
||||||
|
<div class="empty-icon">๐</div>
|
||||||
|
<p>No records found for this category.</p>
|
||||||
|
<span class="empty-sub">Complete a puzzle to claim the first spot!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="leaderboard-footer">
|
||||||
|
<button id="btn-clear-leaderboard" class="danger-link-btn">Clear Records</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- OVERLAY: PAUSE MODAL -->
|
||||||
|
<div id="overlay-pause" class="modal-overlay">
|
||||||
|
<div class="modal-card pause-card">
|
||||||
|
<div class="modal-icon-badge">โธ</div>
|
||||||
|
<h2>Game Paused</h2>
|
||||||
|
<p>Take a breath. The timer is currently stopped.</p>
|
||||||
|
|
||||||
|
<div class="modal-stats-row">
|
||||||
|
<div class="modal-stat">
|
||||||
|
<span class="m-label">Elapsed Time</span>
|
||||||
|
<span class="m-val" id="pause-modal-time">00:00.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-stat">
|
||||||
|
<span class="m-label">Moves Made</span>
|
||||||
|
<span class="m-val" id="pause-modal-moves">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-actions-stacked">
|
||||||
|
<button id="btn-pause-resume" class="btn btn-primary btn-glow">
|
||||||
|
<span>โถ</span> Resume Game
|
||||||
|
</button>
|
||||||
|
<button id="btn-pause-restart" class="btn btn-secondary">
|
||||||
|
<span>๐</span> Restart Puzzle
|
||||||
|
</button>
|
||||||
|
<button id="btn-pause-change-level" class="btn btn-outline">
|
||||||
|
<span>๐ฎ</span> Change Difficulty
|
||||||
|
</button>
|
||||||
|
<button id="btn-pause-quit" class="btn btn-danger-outline">
|
||||||
|
<span>๐ </span> Quit to Menu
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- OVERLAY: VICTORY MODAL -->
|
||||||
|
<div id="overlay-victory" class="modal-overlay">
|
||||||
|
<canvas id="confetti-canvas" class="confetti-canvas"></canvas>
|
||||||
|
<div class="modal-card victory-card">
|
||||||
|
<div class="victory-header">
|
||||||
|
<div class="crown-icon">๐</div>
|
||||||
|
<h2>Puzzle Solved!</h2>
|
||||||
|
<p class="victory-tagline">Flawless spatial mastery. Here are your final stats:</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="victory-stats-grid">
|
||||||
|
<div class="v-stat-card highlight">
|
||||||
|
<span class="v-label">TIME</span>
|
||||||
|
<span class="v-value" id="victory-time">00:00.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="v-stat-card">
|
||||||
|
<span class="v-label">MOVES</span>
|
||||||
|
<span class="v-value" id="victory-moves">0</span>
|
||||||
|
</div>
|
||||||
|
<div class="v-stat-card">
|
||||||
|
<span class="v-label">DIFFICULTY</span>
|
||||||
|
<span class="v-value" id="victory-difficulty">Medium</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Name submit form -->
|
||||||
|
<form id="victory-form" class="victory-form" onsubmit="return false;">
|
||||||
|
<label for="player-name-input">Save to Leaderboard</label>
|
||||||
|
<div class="input-with-btn">
|
||||||
|
<input type="text" id="player-name-input" maxlength="20" placeholder="Enter your name" required autocomplete="off" />
|
||||||
|
<button type="submit" id="btn-save-score" class="btn btn-primary">
|
||||||
|
Save Score
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="save-feedback" class="save-feedback"></div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="victory-actions">
|
||||||
|
<button id="btn-victory-replay" class="btn btn-secondary">
|
||||||
|
<span>๐</span> Play Again
|
||||||
|
</button>
|
||||||
|
<button id="btn-victory-levels" class="btn btn-primary">
|
||||||
|
<span>๐ฎ</span> Select Level
|
||||||
|
</button>
|
||||||
|
<button id="btn-victory-leaderboard" class="btn btn-outline">
|
||||||
|
<span>๐</span> Leaderboard
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Game script -->
|
||||||
|
<script src="game.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user