1 er commit
This commit is contained in:
369
README.md
Normal file
369
README.md
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
# 🎮 Oulvic - Jeu de type Pac-Man
|
||||||
|
|
||||||
|
Un jeu de type Pac-Man développé en JavaScript vanilla par **Ludo** et **Syoul**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Table des matières
|
||||||
|
|
||||||
|
1. [Description](#description)
|
||||||
|
2. [Fonctionnalités](#fonctionnalités)
|
||||||
|
3. [Structure du projet](#structure-du-projet)
|
||||||
|
4. [Installation](#installation)
|
||||||
|
5. [Comment jouer](#comment-jouer)
|
||||||
|
6. [Architecture du code](#architecture-du-code)
|
||||||
|
7. [Documentation technique](#documentation-technique)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Description
|
||||||
|
|
||||||
|
**Oulvic** est un clone de Pac-Man développé entièrement en HTML5, CSS3 et JavaScript vanilla. Le jeu utilise l'élément `<canvas>` pour le rendu graphique et propose une expérience de jeu complète avec :
|
||||||
|
|
||||||
|
- Un personnage jouable aux couleurs changeantes
|
||||||
|
- 4 fantômes avec intelligence artificielle
|
||||||
|
- 3 labyrinthes différents
|
||||||
|
- Système de niveaux progressifs
|
||||||
|
- Classement des scores (localStorage)
|
||||||
|
- Interface responsive
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Fonctionnalités
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- **Déplacement fluide** : Mouvement pixel par pixel avec interpolation
|
||||||
|
- **Système de vies** : 3 vies représentées par des cœurs
|
||||||
|
- **Points** : Collecte de pastilles (+10 points) et bonus
|
||||||
|
- **Progression de niveau** : Passer au niveau suivant en mangeant 4 cerises
|
||||||
|
|
||||||
|
### Bonus
|
||||||
|
| Bonus | Points | Effet |
|
||||||
|
|-------|--------|-------|
|
||||||
|
| 🍒 Cerise | +100 | Active la poursuite des fantômes pendant un temps limité. 4 cerises = niveau suivant |
|
||||||
|
| ⭐ Étoile "L" | +15 | Bonus supplémentaire |
|
||||||
|
|
||||||
|
### Fantômes
|
||||||
|
- **4 fantômes** avec couleurs distinctes (rouge, magenta, cyan, orange)
|
||||||
|
- **IA adaptative** : Les fantômes poursuivent Pac-Man après qu'une cerise soit mangée
|
||||||
|
- **Vitesse croissante** : Les fantômes accélèrent à chaque niveau
|
||||||
|
|
||||||
|
### Labyrinthes
|
||||||
|
- 3 variantes de labyrinthes qui alternent à chaque niveau
|
||||||
|
- Génération dynamique avec remplissage des espaces vides
|
||||||
|
- Randomisation légère pour plus de variété
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Structure du projet
|
||||||
|
|
||||||
|
```
|
||||||
|
pacmanludo/
|
||||||
|
├── index.html # Page HTML principale
|
||||||
|
├── style.css # Feuille de styles
|
||||||
|
├── game.js # Logique du jeu
|
||||||
|
└── README.md # Documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Installation
|
||||||
|
|
||||||
|
1. **Cloner ou télécharger** le projet
|
||||||
|
2. **Ouvrir** `index.html` dans un navigateur web moderne
|
||||||
|
3. **Jouer !**
|
||||||
|
|
||||||
|
Aucune dépendance externe n'est requise.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Comment jouer
|
||||||
|
|
||||||
|
### Contrôles
|
||||||
|
| Touche | Action |
|
||||||
|
|--------|--------|
|
||||||
|
| ↑ Flèche Haut | Déplacer vers le haut |
|
||||||
|
| ↓ Flèche Bas | Déplacer vers le bas |
|
||||||
|
| ← Flèche Gauche | Déplacer vers la gauche |
|
||||||
|
| → Flèche Droite | Déplacer vers la droite |
|
||||||
|
|
||||||
|
### Objectif
|
||||||
|
1. Collectez toutes les pastilles blanches pour marquer des points
|
||||||
|
2. Mangez les cerises pour activer la poursuite et progresser
|
||||||
|
3. Évitez les fantômes !
|
||||||
|
4. Atteignez le score le plus élevé possible
|
||||||
|
|
||||||
|
### Progression
|
||||||
|
- **4 cerises mangées** = passage au niveau suivant
|
||||||
|
- À chaque niveau :
|
||||||
|
- Pac-Man accélère légèrement (+5% par niveau)
|
||||||
|
- Les fantômes deviennent plus rapides (+20% par niveau)
|
||||||
|
- Le labyrinthe change (cycle de 3 labyrinthes)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Architecture du code
|
||||||
|
|
||||||
|
### `index.html`
|
||||||
|
|
||||||
|
Structure HTML de la page :
|
||||||
|
|
||||||
|
```html
|
||||||
|
├── main-wrapper
|
||||||
|
│ ├── container (zone de jeu)
|
||||||
|
│ │ ├── Titre "OULVIC"
|
||||||
|
│ │ ├── Champ nom d'utilisateur
|
||||||
|
│ │ ├── Barre d'informations (score, niveau, vies, statut)
|
||||||
|
│ │ ├── Canvas du jeu (600x600)
|
||||||
|
│ │ └── Instructions et bouton rejouer
|
||||||
|
│ └── leaderboard-container (classement)
|
||||||
|
└── footer (crédits)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `style.css`
|
||||||
|
|
||||||
|
| Section | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| Reset & Body | Styles de base, fond sombre avec effets |
|
||||||
|
| Layout | Flexbox pour disposition responsive |
|
||||||
|
| Game Info | Styles pour score, niveau, vies |
|
||||||
|
| Canvas | Bordure dorée, ombres |
|
||||||
|
| Leaderboard | Tableau des scores stylisé |
|
||||||
|
| Responsive | Media queries pour mobile |
|
||||||
|
|
||||||
|
### `game.js`
|
||||||
|
|
||||||
|
#### Constantes principales
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
CELL_SIZE = 20 // Taille d'une cellule en pixels
|
||||||
|
COLS = 30 // Nombre de colonnes
|
||||||
|
ROWS = 30 // Nombre de lignes
|
||||||
|
|
||||||
|
// Types de cellules
|
||||||
|
WALL = 1 // Mur (bleu)
|
||||||
|
DOT = 2 // Pastille (blanc)
|
||||||
|
EMPTY = 0 // Vide
|
||||||
|
TUNNEL = 3 // Tunnel (passage fantômes)
|
||||||
|
BONUS_CHERRY = 4 // Cerise bonus
|
||||||
|
BONUS_LUDO = 5 // Étoile bonus
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation technique
|
||||||
|
|
||||||
|
### Classe `Pacman`
|
||||||
|
|
||||||
|
Gère le personnage jouable.
|
||||||
|
|
||||||
|
| Propriété | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `x, y` | number | Position en cellules |
|
||||||
|
| `pixelX, pixelY` | number | Position en pixels (mouvement fluide) |
|
||||||
|
| `direction` | number | Direction actuelle (0=haut, 1=droite, 2=bas, 3=gauche) |
|
||||||
|
| `nextDirection` | number | Prochaine direction demandée |
|
||||||
|
| `speed` | number | Vitesse de déplacement |
|
||||||
|
| `mouthAngle` | number | Animation de la bouche |
|
||||||
|
| `colorAnimation` | number | Animation des couleurs HSL |
|
||||||
|
|
||||||
|
| Méthode | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `update()` | Met à jour la position et l'animation |
|
||||||
|
| `canMove(direction)` | Vérifie si le mouvement est possible |
|
||||||
|
| `collectDot()` | Collecte les pastilles et bonus |
|
||||||
|
| `draw()` | Dessine Pac-Man sur le canvas |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Classe `Ghost`
|
||||||
|
|
||||||
|
Gère les fantômes ennemis.
|
||||||
|
|
||||||
|
| Propriété | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `x, y` | number | Position en cellules |
|
||||||
|
| `pixelX, pixelY` | number | Position en pixels |
|
||||||
|
| `color` | string | Couleur du fantôme |
|
||||||
|
| `direction` | number | Direction de déplacement |
|
||||||
|
| `speed` | number | Vitesse (augmente avec le niveau) |
|
||||||
|
| `moveInterval` | number | Intervalle entre changements de direction |
|
||||||
|
|
||||||
|
| Méthode | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `update()` | Met à jour la position et l'IA |
|
||||||
|
| `updateSpeed()` | Ajuste la vitesse selon le niveau |
|
||||||
|
| `canMove(direction)` | Vérifie si le mouvement est possible |
|
||||||
|
| `getDirectionToPacman(dirs)` | Calcule la meilleure direction vers Pac-Man |
|
||||||
|
| `draw()` | Dessine le fantôme (corps + yeux) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Classe `Bonus`
|
||||||
|
|
||||||
|
Gère les objets bonus (cerises, étoiles).
|
||||||
|
|
||||||
|
| Propriété | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `x, y` | number | Position en cellules |
|
||||||
|
| `type` | number | Type de bonus (CHERRY ou LUDO) |
|
||||||
|
| `animation` | number | Animation de pulsation |
|
||||||
|
|
||||||
|
| Méthode | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `update()` | Met à jour l'animation |
|
||||||
|
| `draw()` | Dessine le bonus avec effet de scale |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Fonctions principales
|
||||||
|
|
||||||
|
#### Gestion du labyrinthe
|
||||||
|
|
||||||
|
| Fonction | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `countDots()` | Compte le nombre de pastilles restantes |
|
||||||
|
| `drawMaze()` | Dessine le labyrinthe complet |
|
||||||
|
| `fillEmptySpaces()` | Remplit les espaces vides avec des pastilles |
|
||||||
|
| `randomizeMaze()` | Ajoute des variations aléatoires au labyrinthe |
|
||||||
|
| `placeBonuses()` | Place les bonus aux positions définies |
|
||||||
|
|
||||||
|
#### Gestion du jeu
|
||||||
|
|
||||||
|
| Fonction | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `initGame()` | Initialise une nouvelle partie |
|
||||||
|
| `gameLoop()` | Boucle principale du jeu (requestAnimationFrame) |
|
||||||
|
| `checkCollisions()` | Détecte les collisions Pac-Man/fantômes |
|
||||||
|
| `nextLevel()` | Passe au niveau suivant |
|
||||||
|
| `restartCurrentLevel()` | Recommence le niveau actuel (après perte de vie) |
|
||||||
|
|
||||||
|
#### Interface utilisateur
|
||||||
|
|
||||||
|
| Fonction | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `updateLivesDisplay()` | Met à jour l'affichage des vies |
|
||||||
|
| `updateLeaderboard()` | Rafraîchit le classement |
|
||||||
|
| `saveScore()` | Sauvegarde le score en localStorage |
|
||||||
|
| `getScores()` | Récupère les scores depuis localStorage |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Variables globales d'état
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
let score = 0; // Score actuel
|
||||||
|
let level = 1; // Niveau actuel
|
||||||
|
let lives = 3; // Vies restantes
|
||||||
|
let gameRunning = true; // État du jeu
|
||||||
|
let totalDots = 0; // Pastilles restantes
|
||||||
|
let cherriesEaten = 0; // Cerises mangées (niveau actuel)
|
||||||
|
let isChangingLevel = false; // Flag de transition
|
||||||
|
let cherryEatenRecently = false; // Mode poursuite activé
|
||||||
|
let cherryEatenTimer = 0; // Durée du mode poursuite
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Système de stockage des scores
|
||||||
|
|
||||||
|
Les scores sont sauvegardés dans le `localStorage` du navigateur sous la clé `pacmanScores`.
|
||||||
|
|
||||||
|
**Format des données :**
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
username: "NomJoueur", // Nom saisi ou "Anonyme"
|
||||||
|
score: 1500, // Score final
|
||||||
|
date: "2025-12-01T..." // Date ISO
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Maximum **10 scores** conservés
|
||||||
|
- Triés par score décroissant
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Labyrinthes
|
||||||
|
|
||||||
|
Le jeu dispose de 3 labyrinthes prédéfinis (`originalMaze1`, `originalMaze2`, `originalMaze3`) stockés comme tableaux 2D de 30x30.
|
||||||
|
|
||||||
|
**Rotation des labyrinthes :**
|
||||||
|
```javascript
|
||||||
|
mazeIndex = (level - 1) % 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Les labyrinthes sont modifiés dynamiquement :
|
||||||
|
1. `fillEmptySpaces()` - Remplit les zones vides
|
||||||
|
2. `randomizeMaze()` - Ajoute de la variété
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Design
|
||||||
|
|
||||||
|
### Palette de couleurs
|
||||||
|
|
||||||
|
| Élément | Couleur |
|
||||||
|
|---------|---------|
|
||||||
|
| Fond | `#0a0a0a` (noir) |
|
||||||
|
| Murs | `#0000ff` (bleu) |
|
||||||
|
| Pastilles | `#ffffff` (blanc) |
|
||||||
|
| Texte titre | `#ffd700` (or) |
|
||||||
|
| Cerises | `#ff0000` (rouge) |
|
||||||
|
| Cœurs | `#ff0000` (rouge) |
|
||||||
|
|
||||||
|
### Fantômes
|
||||||
|
- Rouge : `#ff0000`
|
||||||
|
- Magenta : `#ff00ff`
|
||||||
|
- Cyan : `#00ffff`
|
||||||
|
- Orange : `#ffa500`
|
||||||
|
|
||||||
|
### Pac-Man
|
||||||
|
- Couleur animée en HSL (arc-en-ciel)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Personnalisation
|
||||||
|
|
||||||
|
### Modifier la difficulté
|
||||||
|
|
||||||
|
Dans `game.js` :
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Vitesse de base de Pac-Man (ligne 145)
|
||||||
|
this.baseSpeed = 0.15;
|
||||||
|
|
||||||
|
// Vitesse de base des fantômes (ligne 277)
|
||||||
|
this.baseSpeed = 0.1;
|
||||||
|
|
||||||
|
// Accélération par niveau
|
||||||
|
pacman.speed = pacman.baseSpeed * (1 + (level - 1) * 0.05);
|
||||||
|
ghost.speed = ghost.baseSpeed * (1 + (level - 1) * 0.2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modifier les points
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Pastille (ligne 213)
|
||||||
|
score += 10;
|
||||||
|
|
||||||
|
// Cerise (ligne 224)
|
||||||
|
score += 100;
|
||||||
|
|
||||||
|
// Étoile Ludo (ligne 241)
|
||||||
|
score += 15;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 Licence
|
||||||
|
|
||||||
|
Projet créé par **Ludo** et **Syoul**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🙏 Crédits
|
||||||
|
|
||||||
|
- Inspiration : Pac-Man original (Namco, 1980)
|
||||||
|
- Développement : Ludo & Syoul
|
||||||
|
|
||||||
|
|
||||||
40
index.html
Normal file
40
index.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Jeu Oulvic</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main-wrapper">
|
||||||
|
<div class="container">
|
||||||
|
<h1>OULVIC</h1>
|
||||||
|
<div class="user-input-section">
|
||||||
|
<label for="username">Nom d'utilisateur:</label>
|
||||||
|
<input type="text" id="username" placeholder="Entrez votre nom" maxlength="15">
|
||||||
|
</div>
|
||||||
|
<div class="game-info">
|
||||||
|
<div class="score">Score: <span id="score">0</span></div>
|
||||||
|
<div class="level">Niveau: <span id="level">1</span></div>
|
||||||
|
<div class="lives">Vies: <span id="lives"><span class="heart">♥</span><span class="heart">♥</span><span class="heart">♥</span></span></div>
|
||||||
|
<div class="status" id="status">Prêt à jouer</div>
|
||||||
|
</div>
|
||||||
|
<canvas id="gameCanvas" width="600" height="600"></canvas>
|
||||||
|
<div class="instructions">
|
||||||
|
<p>Utilisez les flèches directionnelles pour déplacer Oulvic</p>
|
||||||
|
<button id="restartBtn" style="display: none;">Rejouer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="leaderboard-container">
|
||||||
|
<h2>Classement</h2>
|
||||||
|
<div id="leaderboard"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<p>By Ludo and Syoul</p>
|
||||||
|
</footer>
|
||||||
|
<script src="game.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
302
style.css
Normal file
302
style.css
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
background: #0a0a0a;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(circle at 20% 30%, rgba(255, 0, 0, 0.1) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 80% 70%, rgba(0, 0, 255, 0.1) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 50% 50%, rgba(128, 0, 128, 0.1) 0%, transparent 50%);
|
||||||
|
color: #fff;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
position: relative;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image:
|
||||||
|
url("data:image/svg+xml,%3Csvg width='100' height='100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M50 20 Q60 10 70 20 Q80 30 70 40 Q60 50 50 40 Q40 50 30 40 Q20 30 30 20 Q40 10 50 20 Z' fill='%23ffffff' opacity='0.05'/%3E%3Ccircle cx='45' cy='30' r='3' fill='%23000000' opacity='0.3'/%3E%3Ccircle cx='55' cy='30' r='3' fill='%23000000' opacity='0.3'/%3E%3Cpath d='M50 40 Q45 45 50 50 Q55 45 50 40' fill='%23000000' opacity='0.2'/%3E%3C/svg%3E");
|
||||||
|
background-size: 200px 200px;
|
||||||
|
background-repeat: repeat;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::after {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent,
|
||||||
|
transparent 2px,
|
||||||
|
rgba(255, 255, 255, 0.02) 2px,
|
||||||
|
rgba(255, 255, 255, 0.02) 4px
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 30px;
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8), 0 0 50px rgba(255, 0, 0, 0.2);
|
||||||
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
border: 2px solid rgba(255, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3em;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-shadow: 3px 3px 6px rgba(0, 0, 0, 0.5);
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 10px;
|
||||||
|
gap: 15px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lives {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lives .heart {
|
||||||
|
color: #ff0000;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 0 2px;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status {
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameCanvas {
|
||||||
|
border: 3px solid #ffd700;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #000;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-input-section {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-input-section label {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#username {
|
||||||
|
padding: 8px 15px;
|
||||||
|
font-size: 1em;
|
||||||
|
border: 2px solid #ffd700;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
outline: none;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#username:focus {
|
||||||
|
border-color: #ffed4e;
|
||||||
|
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-container {
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
padding: 25px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8), 0 0 50px rgba(255, 0, 0, 0.2);
|
||||||
|
min-width: 300px;
|
||||||
|
max-height: 700px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
border: 2px solid rgba(255, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-container h2 {
|
||||||
|
color: #ffd700;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 2em;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#leaderboard {
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-item {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-left: 4px solid #ffd700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-item.top {
|
||||||
|
background: rgba(255, 215, 0, 0.2);
|
||||||
|
border-left-color: #ffed4e;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-rank {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffd700;
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-name {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 15px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-score {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffd700;
|
||||||
|
min-width: 80px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-leaderboard {
|
||||||
|
text-align: center;
|
||||||
|
color: #aaa;
|
||||||
|
padding: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartBtn {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 12px 30px;
|
||||||
|
font-size: 1.2em;
|
||||||
|
background: #ffd700;
|
||||||
|
color: #000;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartBtn:hover {
|
||||||
|
background: #ffed4e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartBtn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
padding: 20px;
|
||||||
|
color: #ffd700;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.main-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
#gameCanvas {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-info {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-input-section {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user