create-template-html-css 1.8.1 → 2.0.0
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/README.md +179 -2
- package/bin/cli.js +20 -2
- 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/guess-number/index.html +71 -0
- package/templates/guess-number/script.js +216 -0
- package/templates/guess-number/style.css +337 -0
- package/templates/memory-game/index.html +50 -0
- package/templates/memory-game/script.js +216 -0
- package/templates/memory-game/style.css +288 -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/snake-game/index.html +61 -0
- package/templates/snake-game/script.js +360 -0
- package/templates/snake-game/style.css +246 -0
- package/templates/tetris/index.html +84 -0
- package/templates/tetris/script.js +447 -0
- package/templates/tetris/style.css +286 -0
- package/templates/tic-tac-toe/index.html +57 -0
- package/templates/tic-tac-toe/script.js +156 -0
- package/templates/tic-tac-toe/style.css +244 -0
- package/templates/whack-a-mole/index.html +85 -0
- package/templates/whack-a-mole/script.js +172 -0
- package/templates/whack-a-mole/style.css +263 -0
- package/COMPONENTS-GALLERY.html +0 -773
- package/PUBLISH-GUIDE.md +0 -112
- package/create-template-html-css-1.8.0.tgz +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
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}} - Snake Game</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="container">
|
|
11
|
+
<div class="game-card">
|
|
12
|
+
<h1>Snake Game</h1>
|
|
13
|
+
|
|
14
|
+
<div class="game-info">
|
|
15
|
+
<div class="info-item">
|
|
16
|
+
<span class="label">Score:</span>
|
|
17
|
+
<span id="score" class="value">0</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="info-item">
|
|
20
|
+
<span class="label">High Score:</span>
|
|
21
|
+
<span id="highScore" class="value">0</span>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="info-item">
|
|
24
|
+
<span class="label">Speed:</span>
|
|
25
|
+
<span id="speed" class="value">Normal</span>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<canvas id="gameCanvas" width="400" height="400"></canvas>
|
|
30
|
+
|
|
31
|
+
<div class="message" id="message">
|
|
32
|
+
Press SPACE or tap Start to begin
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="controls">
|
|
36
|
+
<div class="arrow-buttons">
|
|
37
|
+
<button class="arrow-btn" id="upBtn">↑</button>
|
|
38
|
+
<div class="arrow-row">
|
|
39
|
+
<button class="arrow-btn" id="leftBtn">←</button>
|
|
40
|
+
<button class="arrow-btn" id="downBtn">↓</button>
|
|
41
|
+
<button class="arrow-btn" id="rightBtn">→</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="button-group">
|
|
47
|
+
<button id="startBtn" class="btn btn-success">Start</button>
|
|
48
|
+
<button id="pauseBtn" class="btn btn-warning">Pause</button>
|
|
49
|
+
<button id="resetBtn" class="btn btn-danger">Reset</button>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="instructions">
|
|
53
|
+
<p>🎮 Use Arrow Keys or Buttons to control the snake</p>
|
|
54
|
+
<p>🍎 Eat apples to grow and increase score</p>
|
|
55
|
+
<p>⚠️ Don't hit walls or yourself!</p>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<script src="script.js"></script>
|
|
60
|
+
</body>
|
|
61
|
+
</html>
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
// Snake Game Logic
|
|
2
|
+
|
|
3
|
+
const canvas = document.getElementById('gameCanvas');
|
|
4
|
+
const ctx = canvas.getContext('2d');
|
|
5
|
+
const scoreDisplay = document.getElementById('score');
|
|
6
|
+
const highScoreDisplay = document.getElementById('highScore');
|
|
7
|
+
const speedDisplay = document.getElementById('speed');
|
|
8
|
+
const messageDisplay = document.getElementById('message');
|
|
9
|
+
const startBtn = document.getElementById('startBtn');
|
|
10
|
+
const pauseBtn = document.getElementById('pauseBtn');
|
|
11
|
+
const resetBtn = document.getElementById('resetBtn');
|
|
12
|
+
const upBtn = document.getElementById('upBtn');
|
|
13
|
+
const downBtn = document.getElementById('downBtn');
|
|
14
|
+
const leftBtn = document.getElementById('leftBtn');
|
|
15
|
+
const rightBtn = document.getElementById('rightBtn');
|
|
16
|
+
|
|
17
|
+
// Game constants
|
|
18
|
+
const GRID_SIZE = 20;
|
|
19
|
+
const CELL_SIZE = canvas.width / GRID_SIZE;
|
|
20
|
+
|
|
21
|
+
// Game state
|
|
22
|
+
let snake = [];
|
|
23
|
+
let food = {};
|
|
24
|
+
let direction = 'right';
|
|
25
|
+
let nextDirection = 'right';
|
|
26
|
+
let score = 0;
|
|
27
|
+
let highScore = localStorage.getItem('snakeHighScore') || 0;
|
|
28
|
+
let gameLoop = null;
|
|
29
|
+
let gameSpeed = 150;
|
|
30
|
+
let isPaused = false;
|
|
31
|
+
let isGameOver = false;
|
|
32
|
+
|
|
33
|
+
// Initialize game
|
|
34
|
+
function initGame() {
|
|
35
|
+
snake = [
|
|
36
|
+
{ x: 10, y: 10 },
|
|
37
|
+
{ x: 9, y: 10 },
|
|
38
|
+
{ x: 8, y: 10 }
|
|
39
|
+
];
|
|
40
|
+
direction = 'right';
|
|
41
|
+
nextDirection = 'right';
|
|
42
|
+
score = 0;
|
|
43
|
+
gameSpeed = 150;
|
|
44
|
+
isPaused = false;
|
|
45
|
+
isGameOver = false;
|
|
46
|
+
|
|
47
|
+
updateScore();
|
|
48
|
+
updateSpeed();
|
|
49
|
+
spawnFood();
|
|
50
|
+
draw();
|
|
51
|
+
|
|
52
|
+
messageDisplay.textContent = 'Press SPACE or tap Start to begin';
|
|
53
|
+
messageDisplay.className = 'message';
|
|
54
|
+
startBtn.disabled = false;
|
|
55
|
+
pauseBtn.disabled = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Start game
|
|
59
|
+
function startGame() {
|
|
60
|
+
if (gameLoop || isPaused) return;
|
|
61
|
+
|
|
62
|
+
messageDisplay.textContent = '';
|
|
63
|
+
startBtn.disabled = true;
|
|
64
|
+
pauseBtn.disabled = false;
|
|
65
|
+
|
|
66
|
+
gameLoop = setInterval(() => {
|
|
67
|
+
update();
|
|
68
|
+
draw();
|
|
69
|
+
}, gameSpeed);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Pause game
|
|
73
|
+
function pauseGame() {
|
|
74
|
+
if (isGameOver) return;
|
|
75
|
+
|
|
76
|
+
isPaused = !isPaused;
|
|
77
|
+
|
|
78
|
+
if (isPaused) {
|
|
79
|
+
clearInterval(gameLoop);
|
|
80
|
+
gameLoop = null;
|
|
81
|
+
messageDisplay.textContent = 'PAUSED - Press SPACE or Resume';
|
|
82
|
+
messageDisplay.className = 'message show';
|
|
83
|
+
pauseBtn.textContent = 'Resume';
|
|
84
|
+
startBtn.disabled = false;
|
|
85
|
+
} else {
|
|
86
|
+
startGame();
|
|
87
|
+
messageDisplay.textContent = '';
|
|
88
|
+
pauseBtn.textContent = 'Pause';
|
|
89
|
+
startBtn.disabled = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Reset game
|
|
94
|
+
function resetGame() {
|
|
95
|
+
clearInterval(gameLoop);
|
|
96
|
+
gameLoop = null;
|
|
97
|
+
initGame();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Update game state
|
|
101
|
+
function update() {
|
|
102
|
+
direction = nextDirection;
|
|
103
|
+
|
|
104
|
+
// Calculate new head position
|
|
105
|
+
const head = { ...snake[0] };
|
|
106
|
+
|
|
107
|
+
switch (direction) {
|
|
108
|
+
case 'up':
|
|
109
|
+
head.y--;
|
|
110
|
+
break;
|
|
111
|
+
case 'down':
|
|
112
|
+
head.y++;
|
|
113
|
+
break;
|
|
114
|
+
case 'left':
|
|
115
|
+
head.x--;
|
|
116
|
+
break;
|
|
117
|
+
case 'right':
|
|
118
|
+
head.x++;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check collision with walls
|
|
123
|
+
if (head.x < 0 || head.x >= GRID_SIZE || head.y < 0 || head.y >= GRID_SIZE) {
|
|
124
|
+
gameOver();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Check collision with self
|
|
129
|
+
if (snake.some(segment => segment.x === head.x && segment.y === head.y)) {
|
|
130
|
+
gameOver();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add new head
|
|
135
|
+
snake.unshift(head);
|
|
136
|
+
|
|
137
|
+
// Check if food eaten
|
|
138
|
+
if (head.x === food.x && head.y === food.y) {
|
|
139
|
+
score += 10;
|
|
140
|
+
updateScore();
|
|
141
|
+
spawnFood();
|
|
142
|
+
increaseSpeed();
|
|
143
|
+
} else {
|
|
144
|
+
snake.pop();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Draw everything
|
|
149
|
+
function draw() {
|
|
150
|
+
// Clear canvas
|
|
151
|
+
ctx.fillStyle = '#1f2937';
|
|
152
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
153
|
+
|
|
154
|
+
// Draw grid
|
|
155
|
+
ctx.strokeStyle = '#374151';
|
|
156
|
+
ctx.lineWidth = 1;
|
|
157
|
+
for (let i = 0; i <= GRID_SIZE; i++) {
|
|
158
|
+
ctx.beginPath();
|
|
159
|
+
ctx.moveTo(i * CELL_SIZE, 0);
|
|
160
|
+
ctx.lineTo(i * CELL_SIZE, canvas.height);
|
|
161
|
+
ctx.stroke();
|
|
162
|
+
|
|
163
|
+
ctx.beginPath();
|
|
164
|
+
ctx.moveTo(0, i * CELL_SIZE);
|
|
165
|
+
ctx.lineTo(canvas.width, i * CELL_SIZE);
|
|
166
|
+
ctx.stroke();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Draw snake
|
|
170
|
+
snake.forEach((segment, index) => {
|
|
171
|
+
if (index === 0) {
|
|
172
|
+
// Head
|
|
173
|
+
ctx.fillStyle = '#10b981';
|
|
174
|
+
} else {
|
|
175
|
+
// Body
|
|
176
|
+
ctx.fillStyle = '#34d399';
|
|
177
|
+
}
|
|
178
|
+
ctx.fillRect(
|
|
179
|
+
segment.x * CELL_SIZE + 1,
|
|
180
|
+
segment.y * CELL_SIZE + 1,
|
|
181
|
+
CELL_SIZE - 2,
|
|
182
|
+
CELL_SIZE - 2
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Draw food
|
|
187
|
+
ctx.fillStyle = '#ef4444';
|
|
188
|
+
ctx.beginPath();
|
|
189
|
+
ctx.arc(
|
|
190
|
+
food.x * CELL_SIZE + CELL_SIZE / 2,
|
|
191
|
+
food.y * CELL_SIZE + CELL_SIZE / 2,
|
|
192
|
+
CELL_SIZE / 2 - 2,
|
|
193
|
+
0,
|
|
194
|
+
Math.PI * 2
|
|
195
|
+
);
|
|
196
|
+
ctx.fill();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Spawn food
|
|
200
|
+
function spawnFood() {
|
|
201
|
+
do {
|
|
202
|
+
food = {
|
|
203
|
+
x: Math.floor(Math.random() * GRID_SIZE),
|
|
204
|
+
y: Math.floor(Math.random() * GRID_SIZE)
|
|
205
|
+
};
|
|
206
|
+
} while (snake.some(segment => segment.x === food.x && segment.y === food.y));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Change direction
|
|
210
|
+
function changeDirection(newDirection) {
|
|
211
|
+
// Prevent 180 degree turns
|
|
212
|
+
if (
|
|
213
|
+
(newDirection === 'up' && direction !== 'down') ||
|
|
214
|
+
(newDirection === 'down' && direction !== 'up') ||
|
|
215
|
+
(newDirection === 'left' && direction !== 'right') ||
|
|
216
|
+
(newDirection === 'right' && direction !== 'left')
|
|
217
|
+
) {
|
|
218
|
+
nextDirection = newDirection;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Increase speed
|
|
223
|
+
function increaseSpeed() {
|
|
224
|
+
if (gameSpeed > 50) {
|
|
225
|
+
gameSpeed -= 5;
|
|
226
|
+
clearInterval(gameLoop);
|
|
227
|
+
if (!isPaused) {
|
|
228
|
+
gameLoop = setInterval(() => {
|
|
229
|
+
update();
|
|
230
|
+
draw();
|
|
231
|
+
}, gameSpeed);
|
|
232
|
+
}
|
|
233
|
+
updateSpeed();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Update score
|
|
238
|
+
function updateScore() {
|
|
239
|
+
scoreDisplay.textContent = score;
|
|
240
|
+
|
|
241
|
+
if (score > highScore) {
|
|
242
|
+
highScore = score;
|
|
243
|
+
localStorage.setItem('snakeHighScore', highScore);
|
|
244
|
+
highScoreDisplay.textContent = highScore;
|
|
245
|
+
} else {
|
|
246
|
+
highScoreDisplay.textContent = highScore;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Update speed display
|
|
251
|
+
function updateSpeed() {
|
|
252
|
+
if (gameSpeed > 100) {
|
|
253
|
+
speedDisplay.textContent = 'Normal';
|
|
254
|
+
} else if (gameSpeed > 60) {
|
|
255
|
+
speedDisplay.textContent = 'Fast';
|
|
256
|
+
} else {
|
|
257
|
+
speedDisplay.textContent = 'Very Fast';
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Game over
|
|
262
|
+
function gameOver() {
|
|
263
|
+
clearInterval(gameLoop);
|
|
264
|
+
gameLoop = null;
|
|
265
|
+
isGameOver = true;
|
|
266
|
+
|
|
267
|
+
messageDisplay.textContent = `Game Over! Final Score: ${score}`;
|
|
268
|
+
messageDisplay.className = 'message show game-over';
|
|
269
|
+
|
|
270
|
+
startBtn.disabled = false;
|
|
271
|
+
pauseBtn.disabled = true;
|
|
272
|
+
pauseBtn.textContent = 'Pause';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Keyboard controls
|
|
276
|
+
document.addEventListener('keydown', (e) => {
|
|
277
|
+
switch (e.key) {
|
|
278
|
+
case 'ArrowUp':
|
|
279
|
+
case 'w':
|
|
280
|
+
case 'W':
|
|
281
|
+
e.preventDefault();
|
|
282
|
+
changeDirection('up');
|
|
283
|
+
break;
|
|
284
|
+
case 'ArrowDown':
|
|
285
|
+
case 's':
|
|
286
|
+
case 'S':
|
|
287
|
+
e.preventDefault();
|
|
288
|
+
changeDirection('down');
|
|
289
|
+
break;
|
|
290
|
+
case 'ArrowLeft':
|
|
291
|
+
case 'a':
|
|
292
|
+
case 'A':
|
|
293
|
+
e.preventDefault();
|
|
294
|
+
changeDirection('left');
|
|
295
|
+
break;
|
|
296
|
+
case 'ArrowRight':
|
|
297
|
+
case 'd':
|
|
298
|
+
case 'D':
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
changeDirection('right');
|
|
301
|
+
break;
|
|
302
|
+
case ' ':
|
|
303
|
+
e.preventDefault();
|
|
304
|
+
if (!gameLoop && !isPaused) {
|
|
305
|
+
startGame();
|
|
306
|
+
} else if (!isGameOver) {
|
|
307
|
+
pauseGame();
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Button controls
|
|
314
|
+
upBtn.addEventListener('click', () => changeDirection('up'));
|
|
315
|
+
downBtn.addEventListener('click', () => changeDirection('down'));
|
|
316
|
+
leftBtn.addEventListener('click', () => changeDirection('left'));
|
|
317
|
+
rightBtn.addEventListener('click', () => changeDirection('right'));
|
|
318
|
+
|
|
319
|
+
startBtn.addEventListener('click', () => {
|
|
320
|
+
if (isGameOver) {
|
|
321
|
+
resetGame();
|
|
322
|
+
}
|
|
323
|
+
startGame();
|
|
324
|
+
});
|
|
325
|
+
pauseBtn.addEventListener('click', pauseGame);
|
|
326
|
+
resetBtn.addEventListener('click', resetGame);
|
|
327
|
+
|
|
328
|
+
// Touch swipe controls
|
|
329
|
+
let touchStartX = 0;
|
|
330
|
+
let touchStartY = 0;
|
|
331
|
+
|
|
332
|
+
canvas.addEventListener('touchstart', (e) => {
|
|
333
|
+
touchStartX = e.touches[0].clientX;
|
|
334
|
+
touchStartY = e.touches[0].clientY;
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
canvas.addEventListener('touchend', (e) => {
|
|
338
|
+
const touchEndX = e.changedTouches[0].clientX;
|
|
339
|
+
const touchEndY = e.changedTouches[0].clientY;
|
|
340
|
+
|
|
341
|
+
const deltaX = touchEndX - touchStartX;
|
|
342
|
+
const deltaY = touchEndY - touchStartY;
|
|
343
|
+
|
|
344
|
+
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
|
345
|
+
if (deltaX > 0) {
|
|
346
|
+
changeDirection('right');
|
|
347
|
+
} else {
|
|
348
|
+
changeDirection('left');
|
|
349
|
+
}
|
|
350
|
+
} else {
|
|
351
|
+
if (deltaY > 0) {
|
|
352
|
+
changeDirection('down');
|
|
353
|
+
} else {
|
|
354
|
+
changeDirection('up');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Initialize on load
|
|
360
|
+
initGame();
|
|
@@ -0,0 +1,246 @@
|
|
|
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, #667eea 0%, #764ba2 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
|
+
.game-card h1 {
|
|
30
|
+
text-align: center;
|
|
31
|
+
color: #333;
|
|
32
|
+
margin-bottom: 20px;
|
|
33
|
+
font-size: 2.5rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.game-info {
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: space-between;
|
|
39
|
+
padding: 15px;
|
|
40
|
+
background: #f3f4f6;
|
|
41
|
+
border-radius: 12px;
|
|
42
|
+
margin-bottom: 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.info-item {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
align-items: center;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.label {
|
|
52
|
+
font-size: 0.9rem;
|
|
53
|
+
color: #6b7280;
|
|
54
|
+
margin-bottom: 5px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.value {
|
|
58
|
+
font-size: 1.3rem;
|
|
59
|
+
font-weight: bold;
|
|
60
|
+
color: #333;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#gameCanvas {
|
|
64
|
+
width: 100%;
|
|
65
|
+
max-width: 400px;
|
|
66
|
+
height: auto;
|
|
67
|
+
display: block;
|
|
68
|
+
margin: 0 auto 20px;
|
|
69
|
+
border-radius: 8px;
|
|
70
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.message {
|
|
74
|
+
text-align: center;
|
|
75
|
+
font-size: 1.1rem;
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
height: 35px;
|
|
78
|
+
display: flex;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
align-items: center;
|
|
81
|
+
margin-bottom: 20px;
|
|
82
|
+
color: #6b7280;
|
|
83
|
+
opacity: 0;
|
|
84
|
+
transition: opacity 0.3s ease;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.message.show {
|
|
88
|
+
opacity: 1;
|
|
89
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.message.game-over {
|
|
93
|
+
color: #ef4444;
|
|
94
|
+
font-size: 1.2rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@keyframes pulse {
|
|
98
|
+
0%, 100% {
|
|
99
|
+
opacity: 1;
|
|
100
|
+
}
|
|
101
|
+
50% {
|
|
102
|
+
opacity: 0.6;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.controls {
|
|
107
|
+
margin-bottom: 20px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.arrow-buttons {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: 5px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.arrow-row {
|
|
118
|
+
display: flex;
|
|
119
|
+
gap: 5px;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.arrow-btn {
|
|
123
|
+
width: 60px;
|
|
124
|
+
height: 60px;
|
|
125
|
+
border: 2px solid #e5e7eb;
|
|
126
|
+
border-radius: 8px;
|
|
127
|
+
background: white;
|
|
128
|
+
font-size: 1.5rem;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
transition: all 0.2s ease;
|
|
131
|
+
color: #333;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.arrow-btn:hover {
|
|
135
|
+
background: #f3f4f6;
|
|
136
|
+
border-color: #9ca3af;
|
|
137
|
+
transform: scale(1.05);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.arrow-btn:active {
|
|
141
|
+
transform: scale(0.95);
|
|
142
|
+
background: #e5e7eb;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.button-group {
|
|
146
|
+
display: flex;
|
|
147
|
+
gap: 10px;
|
|
148
|
+
margin-bottom: 20px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.btn {
|
|
152
|
+
flex: 1;
|
|
153
|
+
padding: 12px 20px;
|
|
154
|
+
border: none;
|
|
155
|
+
border-radius: 8px;
|
|
156
|
+
font-size: 1rem;
|
|
157
|
+
font-weight: 600;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
transition: all 0.3s ease;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.btn:disabled {
|
|
163
|
+
opacity: 0.5;
|
|
164
|
+
cursor: not-allowed;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.btn-success {
|
|
168
|
+
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
|
169
|
+
color: white;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.btn-success:hover:not(:disabled) {
|
|
173
|
+
transform: translateY(-2px);
|
|
174
|
+
box-shadow: 0 5px 15px rgba(16, 185, 129, 0.4);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.btn-warning {
|
|
178
|
+
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
|
179
|
+
color: white;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.btn-warning:hover:not(:disabled) {
|
|
183
|
+
transform: translateY(-2px);
|
|
184
|
+
box-shadow: 0 5px 15px rgba(245, 158, 11, 0.4);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.btn-danger {
|
|
188
|
+
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
|
189
|
+
color: white;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.btn-danger:hover:not(:disabled) {
|
|
193
|
+
transform: translateY(-2px);
|
|
194
|
+
box-shadow: 0 5px 15px rgba(239, 68, 68, 0.4);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.instructions {
|
|
198
|
+
background: #f9fafb;
|
|
199
|
+
border-radius: 8px;
|
|
200
|
+
padding: 15px;
|
|
201
|
+
font-size: 0.9rem;
|
|
202
|
+
color: #6b7280;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.instructions p {
|
|
206
|
+
margin-bottom: 8px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.instructions p:last-child {
|
|
210
|
+
margin-bottom: 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@media (max-width: 480px) {
|
|
214
|
+
.game-card {
|
|
215
|
+
padding: 20px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.game-card h1 {
|
|
219
|
+
font-size: 2rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.game-info {
|
|
223
|
+
flex-direction: column;
|
|
224
|
+
gap: 10px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.info-item {
|
|
228
|
+
flex-direction: row;
|
|
229
|
+
justify-content: space-between;
|
|
230
|
+
width: 100%;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.arrow-btn {
|
|
234
|
+
width: 50px;
|
|
235
|
+
height: 50px;
|
|
236
|
+
font-size: 1.2rem;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.button-group {
|
|
240
|
+
flex-direction: column;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.instructions {
|
|
244
|
+
font-size: 0.85rem;
|
|
245
|
+
}
|
|
246
|
+
}
|