create-template-html-css 1.9.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/COMPONENTS-GALLERY.html +735 -747
  3. package/README.md +179 -2
  4. package/bin/cli.js +15 -3
  5. package/package.json +1 -1
  6. package/templates/blackjack/index.html +97 -0
  7. package/templates/blackjack/script.js +381 -0
  8. package/templates/blackjack/style.css +452 -0
  9. package/templates/breakout/index.html +56 -0
  10. package/templates/breakout/script.js +387 -0
  11. package/templates/breakout/style.css +239 -0
  12. package/templates/connect-four/index.html +78 -0
  13. package/templates/connect-four/script.js +413 -0
  14. package/templates/connect-four/style.css +426 -0
  15. package/templates/dice-game/index.html +99 -0
  16. package/templates/dice-game/script.js +291 -0
  17. package/templates/dice-game/style.css +403 -0
  18. package/templates/flappy-bird/index.html +47 -0
  19. package/templates/flappy-bird/script.js +394 -0
  20. package/templates/flappy-bird/style.css +243 -0
  21. package/templates/game-2048/index.html +59 -0
  22. package/templates/game-2048/script.js +269 -0
  23. package/templates/game-2048/style.css +281 -0
  24. package/templates/pong/index.html +90 -0
  25. package/templates/pong/script.js +364 -0
  26. package/templates/pong/style.css +371 -0
  27. package/templates/rock-paper-scissors/index.html +84 -0
  28. package/templates/rock-paper-scissors/script.js +199 -0
  29. package/templates/rock-paper-scissors/style.css +295 -0
  30. package/templates/simon-says/index.html +64 -0
  31. package/templates/simon-says/script.js +206 -0
  32. package/templates/simon-says/style.css +250 -0
  33. package/templates/slot-machine/index.html +112 -0
  34. package/templates/slot-machine/script.js +238 -0
  35. package/templates/slot-machine/style.css +464 -0
  36. package/templates/tetris/index.html +84 -0
  37. package/templates/tetris/script.js +447 -0
  38. package/templates/tetris/style.css +286 -0
  39. package/templates/whack-a-mole/index.html +85 -0
  40. package/templates/whack-a-mole/script.js +172 -0
  41. package/{demo-games/snake-game → templates/whack-a-mole}/style.css +114 -97
  42. package/PUBLISH-GUIDE.md +0 -112
  43. package/create-template-html-css-1.8.0.tgz +0 -0
  44. package/demo-games/guess-number/index.html +0 -71
  45. package/demo-games/guess-number/script.js +0 -216
  46. package/demo-games/guess-number/style.css +0 -337
  47. package/demo-games/memory-game/index.html +0 -50
  48. package/demo-games/memory-game/script.js +0 -216
  49. package/demo-games/memory-game/style.css +0 -288
  50. package/demo-games/snake-game/index.html +0 -61
  51. package/demo-games/snake-game/script.js +0 -360
  52. package/demo-games/tic-tac-toe/index.html +0 -57
  53. package/demo-games/tic-tac-toe/script.js +0 -156
  54. package/demo-games/tic-tac-toe/style.css +0 -244
@@ -0,0 +1,59 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{name}} - 2048 Game</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <div class="game-card">
12
+ <div class="header">
13
+ <h1>2048</h1>
14
+ <div class="scores">
15
+ <div class="score-box">
16
+ <div class="score-label">Score</div>
17
+ <div id="score" class="score-value">0</div>
18
+ </div>
19
+ <div class="score-box">
20
+ <div class="score-label">Best</div>
21
+ <div id="bestScore" class="score-value">0</div>
22
+ </div>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="game-intro">
27
+ <p><strong>How to play:</strong> Use arrow keys to move tiles. Tiles with the same number merge into one when they touch. Add them up to reach <strong>2048!</strong></p>
28
+ </div>
29
+
30
+ <div class="game-container">
31
+ <div class="grid-container" id="grid"></div>
32
+ <div class="game-message" id="gameMessage">
33
+ <div class="message-content">
34
+ <p id="messageText"></p>
35
+ <button id="retryBtn" class="btn btn-retry">Try Again</button>
36
+ </div>
37
+ </div>
38
+ </div>
39
+
40
+ <div class="button-group">
41
+ <button id="newGameBtn" class="btn btn-primary">New Game</button>
42
+ <button id="undoBtn" class="btn btn-secondary" disabled>Undo</button>
43
+ </div>
44
+
45
+ <div class="mobile-controls">
46
+ <div class="control-row">
47
+ <button class="control-btn" id="upBtn">↑</button>
48
+ </div>
49
+ <div class="control-row">
50
+ <button class="control-btn" id="leftBtn">←</button>
51
+ <button class="control-btn" id="downBtn">↓</button>
52
+ <button class="control-btn" id="rightBtn">→</button>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ <script src="script.js"></script>
58
+ </body>
59
+ </html>
@@ -0,0 +1,269 @@
1
+ // 2048 Game Logic
2
+
3
+ const grid = document.getElementById('grid');
4
+ const scoreDisplay = document.getElementById('score');
5
+ const bestScoreDisplay = document.getElementById('bestScore');
6
+ const newGameBtn = document.getElementById('newGameBtn');
7
+ const undoBtn = document.getElementById('undoBtn');
8
+ const retryBtn = document.getElementById('retryBtn');
9
+ const gameMessage = document.getElementById('gameMessage');
10
+ const messageText = document.getElementById('messageText');
11
+
12
+ // Mobile controls
13
+ const upBtn = document.getElementById('upBtn');
14
+ const downBtn = document.getElementById('downBtn');
15
+ const leftBtn = document.getElementById('leftBtn');
16
+ const rightBtn = document.getElementById('rightBtn');
17
+
18
+ const GRID_SIZE = 4;
19
+ let board = [];
20
+ let score = 0;
21
+ let bestScore = localStorage.getItem('2048BestScore') || 0;
22
+ let previousState = null;
23
+
24
+ // Initialize game
25
+ function initGame() {
26
+ board = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
27
+ score = 0;
28
+ previousState = null;
29
+ updateScore();
30
+ hideMessage();
31
+ addRandomTile();
32
+ addRandomTile();
33
+ renderBoard();
34
+ undoBtn.disabled = true;
35
+ }
36
+
37
+ // Add random tile (2 or 4)
38
+ function addRandomTile() {
39
+ const emptyCells = [];
40
+ for (let i = 0; i < GRID_SIZE; i++) {
41
+ for (let j = 0; j < GRID_SIZE; j++) {
42
+ if (board[i][j] === 0) {
43
+ emptyCells.push({ row: i, col: j });
44
+ }
45
+ }
46
+ }
47
+
48
+ if (emptyCells.length > 0) {
49
+ const { row, col } = emptyCells[Math.floor(Math.random() * emptyCells.length)];
50
+ board[row][col] = Math.random() < 0.9 ? 2 : 4;
51
+ }
52
+ }
53
+
54
+ // Render board
55
+ function renderBoard() {
56
+ grid.innerHTML = '';
57
+
58
+ for (let i = 0; i < GRID_SIZE; i++) {
59
+ for (let j = 0; j < GRID_SIZE; j++) {
60
+ const tile = document.createElement('div');
61
+ tile.className = 'tile';
62
+
63
+ const value = board[i][j];
64
+ if (value !== 0) {
65
+ tile.textContent = value;
66
+ tile.classList.add(`tile-${value}`);
67
+ tile.classList.add('tile-new');
68
+ }
69
+
70
+ grid.appendChild(tile);
71
+ }
72
+ }
73
+ }
74
+
75
+ // Update score
76
+ function updateScore() {
77
+ scoreDisplay.textContent = score;
78
+
79
+ if (score > bestScore) {
80
+ bestScore = score;
81
+ localStorage.setItem('2048BestScore', bestScore);
82
+ }
83
+
84
+ bestScoreDisplay.textContent = bestScore;
85
+ }
86
+
87
+ // Save state for undo
88
+ function saveState() {
89
+ previousState = {
90
+ board: board.map(row => [...row]),
91
+ score: score
92
+ };
93
+ undoBtn.disabled = false;
94
+ }
95
+
96
+ // Undo move
97
+ function undo() {
98
+ if (previousState) {
99
+ board = previousState.board.map(row => [...row]);
100
+ score = previousState.score;
101
+ updateScore();
102
+ renderBoard();
103
+ hideMessage();
104
+ previousState = null;
105
+ undoBtn.disabled = true;
106
+ }
107
+ }
108
+
109
+ // Move tiles
110
+ function move(direction) {
111
+ saveState();
112
+ let moved = false;
113
+
114
+ if (direction === 'left' || direction === 'right') {
115
+ for (let i = 0; i < GRID_SIZE; i++) {
116
+ const row = board[i];
117
+ const newRow = direction === 'left' ? mergeLine(row) : mergeLine(row.reverse()).reverse();
118
+ if (JSON.stringify(row) !== JSON.stringify(newRow)) {
119
+ moved = true;
120
+ }
121
+ board[i] = newRow;
122
+ }
123
+ } else {
124
+ // Transpose for up/down
125
+ const transposed = transpose(board);
126
+ for (let i = 0; i < GRID_SIZE; i++) {
127
+ const row = transposed[i];
128
+ const newRow = direction === 'up' ? mergeLine(row) : mergeLine(row.reverse()).reverse();
129
+ if (JSON.stringify(row) !== JSON.stringify(newRow)) {
130
+ moved = true;
131
+ }
132
+ transposed[i] = newRow;
133
+ }
134
+ board = transpose(transposed);
135
+ }
136
+
137
+ if (moved) {
138
+ addRandomTile();
139
+ renderBoard();
140
+ updateScore();
141
+
142
+ if (checkWin()) {
143
+ showMessage('You Win! 🎉', true);
144
+ } else if (checkGameOver()) {
145
+ showMessage('Game Over! 😢', false);
146
+ }
147
+ } else {
148
+ // Revert if no move was made
149
+ previousState = null;
150
+ undoBtn.disabled = true;
151
+ }
152
+ }
153
+
154
+ // Merge line (left direction)
155
+ function mergeLine(line) {
156
+ // Remove zeros
157
+ let newLine = line.filter(val => val !== 0);
158
+
159
+ // Merge same values
160
+ for (let i = 0; i < newLine.length - 1; i++) {
161
+ if (newLine[i] === newLine[i + 1]) {
162
+ newLine[i] *= 2;
163
+ score += newLine[i];
164
+ newLine.splice(i + 1, 1);
165
+ }
166
+ }
167
+
168
+ // Fill with zeros
169
+ while (newLine.length < GRID_SIZE) {
170
+ newLine.push(0);
171
+ }
172
+
173
+ return newLine;
174
+ }
175
+
176
+ // Transpose matrix
177
+ function transpose(matrix) {
178
+ return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
179
+ }
180
+
181
+ // Check if won (reached 2048)
182
+ function checkWin() {
183
+ for (let i = 0; i < GRID_SIZE; i++) {
184
+ for (let j = 0; j < GRID_SIZE; j++) {
185
+ if (board[i][j] === 2048) {
186
+ return true;
187
+ }
188
+ }
189
+ }
190
+ return false;
191
+ }
192
+
193
+ // Check if game over
194
+ function checkGameOver() {
195
+ // Check for empty cells
196
+ for (let i = 0; i < GRID_SIZE; i++) {
197
+ for (let j = 0; j < GRID_SIZE; j++) {
198
+ if (board[i][j] === 0) {
199
+ return false;
200
+ }
201
+ }
202
+ }
203
+
204
+ // Check for possible merges
205
+ for (let i = 0; i < GRID_SIZE; i++) {
206
+ for (let j = 0; j < GRID_SIZE; j++) {
207
+ const current = board[i][j];
208
+ if ((j < GRID_SIZE - 1 && current === board[i][j + 1]) ||
209
+ (i < GRID_SIZE - 1 && current === board[i + 1][j])) {
210
+ return false;
211
+ }
212
+ }
213
+ }
214
+
215
+ return true;
216
+ }
217
+
218
+ // Show message
219
+ function showMessage(text, isWin) {
220
+ messageText.textContent = text;
221
+ gameMessage.classList.add('show');
222
+ gameMessage.classList.toggle('win', isWin);
223
+ }
224
+
225
+ // Hide message
226
+ function hideMessage() {
227
+ gameMessage.classList.remove('show', 'win');
228
+ }
229
+
230
+ // Keyboard controls
231
+ document.addEventListener('keydown', (e) => {
232
+ if (gameMessage.classList.contains('show')) return;
233
+
234
+ switch (e.key) {
235
+ case 'ArrowUp':
236
+ e.preventDefault();
237
+ move('up');
238
+ break;
239
+ case 'ArrowDown':
240
+ e.preventDefault();
241
+ move('down');
242
+ break;
243
+ case 'ArrowLeft':
244
+ e.preventDefault();
245
+ move('left');
246
+ break;
247
+ case 'ArrowRight':
248
+ e.preventDefault();
249
+ move('right');
250
+ break;
251
+ }
252
+ });
253
+
254
+ // Button controls
255
+ upBtn.addEventListener('click', () => move('up'));
256
+ downBtn.addEventListener('click', () => move('down'));
257
+ leftBtn.addEventListener('click', () => move('left'));
258
+ rightBtn.addEventListener('click', () => move('right'));
259
+
260
+ newGameBtn.addEventListener('click', initGame);
261
+ retryBtn.addEventListener('click', () => {
262
+ hideMessage();
263
+ initGame();
264
+ });
265
+ undoBtn.addEventListener('click', undo);
266
+
267
+ // Initialize on load
268
+ bestScoreDisplay.textContent = bestScore;
269
+ initGame();
@@ -0,0 +1,281 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
9
+ background: linear-gradient(135deg, #fad0c4 0%, #ffd1ff 100%);
10
+ min-height: 100vh;
11
+ display: flex;
12
+ justify-content: center;
13
+ align-items: center;
14
+ padding: 20px;
15
+ }
16
+
17
+ .container {
18
+ width: 100%;
19
+ max-width: 500px;
20
+ }
21
+
22
+ .game-card {
23
+ background: white;
24
+ border-radius: 16px;
25
+ padding: 30px;
26
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
27
+ }
28
+
29
+ .header {
30
+ display: flex;
31
+ justify-content: space-between;
32
+ align-items: center;
33
+ margin-bottom: 20px;
34
+ }
35
+
36
+ .header h1 {
37
+ font-size: 3rem;
38
+ color: #776e65;
39
+ font-weight: bold;
40
+ }
41
+
42
+ .scores {
43
+ display: flex;
44
+ gap: 10px;
45
+ }
46
+
47
+ .score-box {
48
+ background: #bbada0;
49
+ border-radius: 8px;
50
+ padding: 10px 20px;
51
+ text-align: center;
52
+ min-width: 80px;
53
+ }
54
+
55
+ .score-label {
56
+ color: #eee4da;
57
+ font-size: 0.8rem;
58
+ text-transform: uppercase;
59
+ font-weight: bold;
60
+ }
61
+
62
+ .score-value {
63
+ color: white;
64
+ font-size: 1.5rem;
65
+ font-weight: bold;
66
+ }
67
+
68
+ .game-intro {
69
+ background: #eee4da;
70
+ border-radius: 8px;
71
+ padding: 15px;
72
+ margin-bottom: 20px;
73
+ color: #776e65;
74
+ font-size: 0.9rem;
75
+ line-height: 1.5;
76
+ }
77
+
78
+ .game-container {
79
+ position: relative;
80
+ margin-bottom: 20px;
81
+ }
82
+
83
+ .grid-container {
84
+ background: #bbada0;
85
+ border-radius: 8px;
86
+ padding: 10px;
87
+ display: grid;
88
+ grid-template-columns: repeat(4, 1fr);
89
+ gap: 10px;
90
+ }
91
+
92
+ .tile {
93
+ aspect-ratio: 1;
94
+ background: rgba(238, 228, 218, 0.35);
95
+ border-radius: 4px;
96
+ display: flex;
97
+ justify-content: center;
98
+ align-items: center;
99
+ font-size: 2rem;
100
+ font-weight: bold;
101
+ color: #776e65;
102
+ transition: all 0.15s ease;
103
+ }
104
+
105
+ .tile-new {
106
+ animation: appear 0.2s ease;
107
+ }
108
+
109
+ @keyframes appear {
110
+ 0% {
111
+ transform: scale(0);
112
+ }
113
+ 100% {
114
+ transform: scale(1);
115
+ }
116
+ }
117
+
118
+ .tile-2 { background: #eee4da; color: #776e65; }
119
+ .tile-4 { background: #ede0c8; color: #776e65; }
120
+ .tile-8 { background: #f2b179; color: #f9f6f2; }
121
+ .tile-16 { background: #f59563; color: #f9f6f2; }
122
+ .tile-32 { background: #f67c5f; color: #f9f6f2; }
123
+ .tile-64 { background: #f65e3b; color: #f9f6f2; }
124
+ .tile-128 { background: #edcf72; color: #f9f6f2; font-size: 1.6rem; }
125
+ .tile-256 { background: #edcc61; color: #f9f6f2; font-size: 1.6rem; }
126
+ .tile-512 { background: #edc850; color: #f9f6f2; font-size: 1.6rem; }
127
+ .tile-1024 { background: #edc53f; color: #f9f6f2; font-size: 1.3rem; }
128
+ .tile-2048 { background: #edc22e; color: #f9f6f2; font-size: 1.3rem; }
129
+
130
+ .game-message {
131
+ position: absolute;
132
+ top: 0;
133
+ left: 0;
134
+ width: 100%;
135
+ height: 100%;
136
+ background: rgba(238, 228, 218, 0.95);
137
+ border-radius: 8px;
138
+ display: flex;
139
+ justify-content: center;
140
+ align-items: center;
141
+ opacity: 0;
142
+ pointer-events: none;
143
+ transition: opacity 0.3s ease;
144
+ }
145
+
146
+ .game-message.show {
147
+ opacity: 1;
148
+ pointer-events: all;
149
+ }
150
+
151
+ .message-content {
152
+ text-align: center;
153
+ }
154
+
155
+ #messageText {
156
+ font-size: 2rem;
157
+ font-weight: bold;
158
+ color: #776e65;
159
+ margin-bottom: 20px;
160
+ }
161
+
162
+ .game-message.win #messageText {
163
+ color: #f67c5f;
164
+ }
165
+
166
+ .button-group {
167
+ display: flex;
168
+ gap: 10px;
169
+ margin-bottom: 20px;
170
+ }
171
+
172
+ .btn {
173
+ flex: 1;
174
+ padding: 12px 24px;
175
+ border: none;
176
+ border-radius: 8px;
177
+ font-size: 1rem;
178
+ font-weight: 600;
179
+ cursor: pointer;
180
+ transition: all 0.3s ease;
181
+ }
182
+
183
+ .btn:disabled {
184
+ opacity: 0.5;
185
+ cursor: not-allowed;
186
+ }
187
+
188
+ .btn-primary {
189
+ background: #8f7a66;
190
+ color: white;
191
+ }
192
+
193
+ .btn-primary:hover:not(:disabled) {
194
+ background: #9f8a76;
195
+ transform: translateY(-2px);
196
+ box-shadow: 0 5px 15px rgba(143, 122, 102, 0.4);
197
+ }
198
+
199
+ .btn-secondary {
200
+ background: #bbada0;
201
+ color: white;
202
+ }
203
+
204
+ .btn-secondary:hover:not(:disabled) {
205
+ background: #a89c94;
206
+ transform: translateY(-2px);
207
+ box-shadow: 0 5px 15px rgba(187, 173, 160, 0.4);
208
+ }
209
+
210
+ .btn-retry {
211
+ background: #f67c5f;
212
+ color: white;
213
+ padding: 12px 30px;
214
+ }
215
+
216
+ .btn-retry:hover {
217
+ background: #f65e3b;
218
+ transform: scale(1.05);
219
+ }
220
+
221
+ .mobile-controls {
222
+ display: flex;
223
+ flex-direction: column;
224
+ align-items: center;
225
+ gap: 8px;
226
+ }
227
+
228
+ .control-row {
229
+ display: flex;
230
+ gap: 8px;
231
+ }
232
+
233
+ .control-btn {
234
+ width: 60px;
235
+ height: 60px;
236
+ border: 2px solid #bbada0;
237
+ border-radius: 8px;
238
+ background: white;
239
+ font-size: 1.5rem;
240
+ cursor: pointer;
241
+ transition: all 0.2s ease;
242
+ color: #776e65;
243
+ }
244
+
245
+ .control-btn:hover {
246
+ background: #eee4da;
247
+ transform: scale(1.05);
248
+ }
249
+
250
+ .control-btn:active {
251
+ transform: scale(0.95);
252
+ }
253
+
254
+ @media (max-width: 480px) {
255
+ .game-card {
256
+ padding: 20px;
257
+ }
258
+
259
+ .header h1 {
260
+ font-size: 2rem;
261
+ }
262
+
263
+ .tile {
264
+ font-size: 1.5rem;
265
+ }
266
+
267
+ .tile-128,
268
+ .tile-256,
269
+ .tile-512 {
270
+ font-size: 1.2rem;
271
+ }
272
+
273
+ .tile-1024,
274
+ .tile-2048 {
275
+ font-size: 1rem;
276
+ }
277
+
278
+ #messageText {
279
+ font-size: 1.5rem;
280
+ }
281
+ }
@@ -0,0 +1,90 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Pong</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <div class="header">
12
+ <h1>🕹️ Pong</h1>
13
+ <p class="subtitle">The classic game!</p>
14
+ </div>
15
+
16
+ <div class="game-mode">
17
+ <button class="mode-btn active" data-mode="pvc">🤖 vs Computer</button>
18
+ <button class="mode-btn" data-mode="pvp">👥 Two Players</button>
19
+ </div>
20
+
21
+ <div class="difficulty-selector">
22
+ <label>Difficulty:</label>
23
+ <select id="difficulty">
24
+ <option value="easy">Easy</option>
25
+ <option value="medium" selected>Medium</option>
26
+ <option value="hard">Hard</option>
27
+ <option value="impossible">Impossible</option>
28
+ </select>
29
+ </div>
30
+
31
+ <div class="score-board">
32
+ <div class="player-score">
33
+ <h3>👤 Player 1</h3>
34
+ <div id="player1Score" class="score">0</div>
35
+ </div>
36
+ <div class="divider">:</div>
37
+ <div class="player-score">
38
+ <h3 id="player2Name">🤖 Computer</h3>
39
+ <div id="player2Score" class="score">0</div>
40
+ </div>
41
+ </div>
42
+
43
+ <canvas id="gameCanvas"></canvas>
44
+
45
+ <div class="controls">
46
+ <button id="startBtn" class="btn btn-primary">Start Game</button>
47
+ <button id="pauseBtn" class="btn btn-secondary" disabled>Pause</button>
48
+ <button id="resetBtn" class="btn btn-danger">Reset</button>
49
+ </div>
50
+
51
+ <div id="resultMessage" class="result-message"></div>
52
+
53
+ <div class="instructions">
54
+ <h3>🎮 Game Instructions:</h3>
55
+ <div class="controls-grid">
56
+ <div class="control-item">
57
+ <strong>Player 1:</strong>
58
+ <div class="keys">
59
+ <span class="key">W</span>
60
+ <span>Up</span>
61
+ </div>
62
+ <div class="keys">
63
+ <span class="key">S</span>
64
+ <span>Down</span>
65
+ </div>
66
+ </div>
67
+ <div class="control-item">
68
+ <strong>Player 2:</strong>
69
+ <div class="keys">
70
+ <span class="key">↑</span>
71
+ <span>Up</span>
72
+ </div>
73
+ <div class="keys">
74
+ <span class="key">↓</span>
75
+ <span>Down</span>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ <ul class="rules">
80
+ <li>Goal: Return the ball and score</li>
81
+ <li>Each goal scored = +1 point</li>
82
+ <li>First to 10 points wins!</li>
83
+ <li>Speed increases as the ball is returned</li>
84
+ </ul>
85
+ </div>
86
+ </div>
87
+
88
+ <script src="script.js"></script>
89
+ </body>
90
+ </html>