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.
- package/CHANGELOG.md +80 -0
- package/COMPONENTS-GALLERY.html +735 -747
- package/README.md +179 -2
- package/bin/cli.js +15 -3
- package/package.json +1 -1
- package/templates/blackjack/index.html +97 -0
- package/templates/blackjack/script.js +381 -0
- package/templates/blackjack/style.css +452 -0
- package/templates/breakout/index.html +56 -0
- package/templates/breakout/script.js +387 -0
- package/templates/breakout/style.css +239 -0
- package/templates/connect-four/index.html +78 -0
- package/templates/connect-four/script.js +413 -0
- package/templates/connect-four/style.css +426 -0
- package/templates/dice-game/index.html +99 -0
- package/templates/dice-game/script.js +291 -0
- package/templates/dice-game/style.css +403 -0
- package/templates/flappy-bird/index.html +47 -0
- package/templates/flappy-bird/script.js +394 -0
- package/templates/flappy-bird/style.css +243 -0
- package/templates/game-2048/index.html +59 -0
- package/templates/game-2048/script.js +269 -0
- package/templates/game-2048/style.css +281 -0
- package/templates/pong/index.html +90 -0
- package/templates/pong/script.js +364 -0
- package/templates/pong/style.css +371 -0
- package/templates/rock-paper-scissors/index.html +84 -0
- package/templates/rock-paper-scissors/script.js +199 -0
- package/templates/rock-paper-scissors/style.css +295 -0
- package/templates/simon-says/index.html +64 -0
- package/templates/simon-says/script.js +206 -0
- package/templates/simon-says/style.css +250 -0
- package/templates/slot-machine/index.html +112 -0
- package/templates/slot-machine/script.js +238 -0
- package/templates/slot-machine/style.css +464 -0
- package/templates/tetris/index.html +84 -0
- package/templates/tetris/script.js +447 -0
- package/templates/tetris/style.css +286 -0
- package/templates/whack-a-mole/index.html +85 -0
- package/templates/whack-a-mole/script.js +172 -0
- package/{demo-games/snake-game → templates/whack-a-mole}/style.css +114 -97
- package/PUBLISH-GUIDE.md +0 -112
- package/create-template-html-css-1.8.0.tgz +0 -0
- package/demo-games/guess-number/index.html +0 -71
- package/demo-games/guess-number/script.js +0 -216
- package/demo-games/guess-number/style.css +0 -337
- package/demo-games/memory-game/index.html +0 -50
- package/demo-games/memory-game/script.js +0 -216
- package/demo-games/memory-game/style.css +0 -288
- package/demo-games/snake-game/index.html +0 -61
- package/demo-games/snake-game/script.js +0 -360
- package/demo-games/tic-tac-toe/index.html +0 -57
- package/demo-games/tic-tac-toe/script.js +0 -156
- 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>
|