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,413 @@
1
+ // Game constants
2
+ const ROWS = 6;
3
+ const COLS = 7;
4
+ const PLAYER1 = 1;
5
+ const PLAYER2 = 2;
6
+
7
+ // Game state
8
+ let gameState = {
9
+ board: [],
10
+ currentPlayer: PLAYER1,
11
+ gameOver: false,
12
+ gameMode: 'pvp', // 'pvp' or 'pvc'
13
+ difficulty: 'medium',
14
+ score1: parseInt(localStorage.getItem('connect4Score1')) || 0,
15
+ score2: parseInt(localStorage.getItem('connect4Score2')) || 0,
16
+ isAnimating: false
17
+ };
18
+
19
+ // Initialize board
20
+ function initBoard() {
21
+ gameState.board = Array(ROWS).fill().map(() => Array(COLS).fill(0));
22
+ gameState.currentPlayer = PLAYER1;
23
+ gameState.gameOver = false;
24
+ renderBoard();
25
+ updateTurnIndicator();
26
+ }
27
+
28
+ // Render board
29
+ function renderBoard() {
30
+ const boardElement = document.getElementById('gameBoard');
31
+ boardElement.innerHTML = '';
32
+
33
+ for (let col = 0; col < COLS; col++) {
34
+ const column = document.createElement('div');
35
+ column.className = 'column';
36
+ column.dataset.col = col;
37
+
38
+ // Add hover effect
39
+ column.addEventListener('mouseenter', () => {
40
+ if (!gameState.gameOver && !gameState.isAnimating) {
41
+ column.classList.add('hover');
42
+ }
43
+ });
44
+
45
+ column.addEventListener('mouseleave', () => {
46
+ column.classList.remove('hover');
47
+ });
48
+
49
+ column.addEventListener('click', () => handleColumnClick(col));
50
+
51
+ for (let row = 0; row < ROWS; row++) {
52
+ const cell = document.createElement('div');
53
+ cell.className = 'cell';
54
+ cell.dataset.row = row;
55
+ cell.dataset.col = col;
56
+
57
+ const disc = document.createElement('div');
58
+ disc.className = 'disc';
59
+
60
+ const value = gameState.board[row][col];
61
+ if (value === PLAYER1) {
62
+ disc.classList.add('player1');
63
+ } else if (value === PLAYER2) {
64
+ disc.classList.add('player2');
65
+ }
66
+
67
+ cell.appendChild(disc);
68
+ column.appendChild(cell);
69
+ }
70
+
71
+ boardElement.appendChild(column);
72
+ }
73
+ }
74
+
75
+ // Handle column click
76
+ async function handleColumnClick(col) {
77
+ if (gameState.gameOver || gameState.isAnimating) return;
78
+
79
+ const row = getLowestEmptyRow(col);
80
+ if (row === -1) return; // Column is full
81
+
82
+ gameState.isAnimating = true;
83
+
84
+ // Place disc with animation
85
+ await placeDisc(row, col, gameState.currentPlayer);
86
+
87
+ // Check for win or draw
88
+ if (checkWin(row, col)) {
89
+ await highlightWinningDiscs();
90
+ endGame(gameState.currentPlayer);
91
+ gameState.isAnimating = false;
92
+ return;
93
+ }
94
+
95
+ if (isBoardFull()) {
96
+ endGame(0); // Draw
97
+ gameState.isAnimating = false;
98
+ return;
99
+ }
100
+
101
+ // Switch player
102
+ gameState.currentPlayer = gameState.currentPlayer === PLAYER1 ? PLAYER2 : PLAYER1;
103
+ updateTurnIndicator();
104
+
105
+ gameState.isAnimating = false;
106
+
107
+ // Computer's turn
108
+ if (gameState.gameMode === 'pvc' && gameState.currentPlayer === PLAYER2) {
109
+ await computerMove();
110
+ }
111
+ }
112
+
113
+ // Get lowest empty row in column
114
+ function getLowestEmptyRow(col) {
115
+ for (let row = ROWS - 1; row >= 0; row--) {
116
+ if (gameState.board[row][col] === 0) {
117
+ return row;
118
+ }
119
+ }
120
+ return -1;
121
+ }
122
+
123
+ // Place disc with animation
124
+ function placeDisc(row, col, player) {
125
+ return new Promise((resolve) => {
126
+ gameState.board[row][col] = player;
127
+
128
+ const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
129
+ const disc = cell.querySelector('.disc');
130
+
131
+ // Add class for animation
132
+ disc.classList.add(player === PLAYER1 ? 'player1' : 'player2');
133
+ disc.classList.add('dropping');
134
+
135
+ // Calculate drop distance
136
+ const dropDistance = (ROWS - row) * 70; // 70px per row
137
+ disc.style.setProperty('--drop-distance', `${dropDistance}px`);
138
+
139
+ setTimeout(() => {
140
+ disc.classList.remove('dropping');
141
+ resolve();
142
+ }, 500);
143
+ });
144
+ }
145
+
146
+ // Check win
147
+ function checkWin(row, col) {
148
+ const player = gameState.board[row][col];
149
+
150
+ // Check horizontal
151
+ if (checkDirection(row, col, 0, 1, player) ||
152
+ checkDirection(row, col, 0, -1, player)) {
153
+ return true;
154
+ }
155
+
156
+ // Check vertical
157
+ if (checkDirection(row, col, 1, 0, player)) {
158
+ return true;
159
+ }
160
+
161
+ // Check diagonal /
162
+ if (checkDirection(row, col, 1, 1, player) ||
163
+ checkDirection(row, col, -1, -1, player)) {
164
+ return true;
165
+ }
166
+
167
+ // Check diagonal \
168
+ if (checkDirection(row, col, 1, -1, player) ||
169
+ checkDirection(row, col, -1, 1, player)) {
170
+ return true;
171
+ }
172
+
173
+ return false;
174
+ }
175
+
176
+ // Check direction
177
+ function checkDirection(row, col, dRow, dCol, player) {
178
+ let count = 1; // Count current disc
179
+ const winningDiscs = [[row, col]];
180
+
181
+ // Check positive direction
182
+ for (let i = 1; i < 4; i++) {
183
+ const newRow = row + dRow * i;
184
+ const newCol = col + dCol * i;
185
+
186
+ if (newRow < 0 || newRow >= ROWS || newCol < 0 || newCol >= COLS) break;
187
+ if (gameState.board[newRow][newCol] !== player) break;
188
+
189
+ count++;
190
+ winningDiscs.push([newRow, newCol]);
191
+ }
192
+
193
+ // Check negative direction
194
+ for (let i = 1; i < 4; i++) {
195
+ const newRow = row - dRow * i;
196
+ const newCol = col - dCol * i;
197
+
198
+ if (newRow < 0 || newRow >= ROWS || newCol < 0 || newCol >= COLS) break;
199
+ if (gameState.board[newRow][newCol] !== player) break;
200
+
201
+ count++;
202
+ winningDiscs.push([newRow, newCol]);
203
+ }
204
+
205
+ if (count >= 4) {
206
+ gameState.winningDiscs = winningDiscs;
207
+ return true;
208
+ }
209
+
210
+ return false;
211
+ }
212
+
213
+ // Highlight winning discs
214
+ function highlightWinningDiscs() {
215
+ return new Promise((resolve) => {
216
+ gameState.winningDiscs.forEach(([row, col]) => {
217
+ const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
218
+ const disc = cell.querySelector('.disc');
219
+ disc.classList.add('winning');
220
+ });
221
+
222
+ setTimeout(resolve, 500);
223
+ });
224
+ }
225
+
226
+ // Check if board is full
227
+ function isBoardFull() {
228
+ return gameState.board[0].every(cell => cell !== 0);
229
+ }
230
+
231
+ // Computer move
232
+ async function computerMove() {
233
+ gameState.isAnimating = true;
234
+
235
+ // Add thinking delay
236
+ await new Promise(resolve => setTimeout(resolve, 500));
237
+
238
+ let col;
239
+
240
+ switch (gameState.difficulty) {
241
+ case 'easy':
242
+ col = getRandomMove();
243
+ break;
244
+ case 'medium':
245
+ col = Math.random() < 0.5 ? getBestMove() : getRandomMove();
246
+ break;
247
+ case 'hard':
248
+ col = getBestMove();
249
+ break;
250
+ }
251
+
252
+ const row = getLowestEmptyRow(col);
253
+ if (row === -1) {
254
+ gameState.isAnimating = false;
255
+ return computerMove(); // Try again
256
+ }
257
+
258
+ await placeDisc(row, col, PLAYER2);
259
+
260
+ if (checkWin(row, col)) {
261
+ await highlightWinningDiscs();
262
+ endGame(PLAYER2);
263
+ gameState.isAnimating = false;
264
+ return;
265
+ }
266
+
267
+ if (isBoardFull()) {
268
+ endGame(0);
269
+ gameState.isAnimating = false;
270
+ return;
271
+ }
272
+
273
+ gameState.currentPlayer = PLAYER1;
274
+ updateTurnIndicator();
275
+ gameState.isAnimating = false;
276
+ }
277
+
278
+ // Get random move
279
+ function getRandomMove() {
280
+ const availableCols = [];
281
+ for (let col = 0; col < COLS; col++) {
282
+ if (getLowestEmptyRow(col) !== -1) {
283
+ availableCols.push(col);
284
+ }
285
+ }
286
+ return availableCols[Math.floor(Math.random() * availableCols.length)];
287
+ }
288
+
289
+ // Get best move (simple AI)
290
+ function getBestMove() {
291
+ // Try to win
292
+ for (let col = 0; col < COLS; col++) {
293
+ const row = getLowestEmptyRow(col);
294
+ if (row !== -1) {
295
+ gameState.board[row][col] = PLAYER2;
296
+ if (checkWin(row, col)) {
297
+ gameState.board[row][col] = 0;
298
+ return col;
299
+ }
300
+ gameState.board[row][col] = 0;
301
+ }
302
+ }
303
+
304
+ // Block opponent's win
305
+ for (let col = 0; col < COLS; col++) {
306
+ const row = getLowestEmptyRow(col);
307
+ if (row !== -1) {
308
+ gameState.board[row][col] = PLAYER1;
309
+ if (checkWin(row, col)) {
310
+ gameState.board[row][col] = 0;
311
+ return col;
312
+ }
313
+ gameState.board[row][col] = 0;
314
+ }
315
+ }
316
+
317
+ // Prefer center column
318
+ if (getLowestEmptyRow(3) !== -1) {
319
+ return 3;
320
+ }
321
+
322
+ // Random move
323
+ return getRandomMove();
324
+ }
325
+
326
+ // End game
327
+ function endGame(winner) {
328
+ gameState.gameOver = true;
329
+
330
+ if (winner === PLAYER1) {
331
+ gameState.score1++;
332
+ localStorage.setItem('connect4Score1', gameState.score1);
333
+ updateScore();
334
+ showMessage('🎉 שחקן 1 ניצח!', 'player1');
335
+ } else if (winner === PLAYER2) {
336
+ gameState.score2++;
337
+ localStorage.setItem('connect4Score2', gameState.score2);
338
+ updateScore();
339
+ const message = gameState.gameMode === 'pvc' ? '🤖 המחשב ניצח!' : '🎉 שחקן 2 ניצח!';
340
+ showMessage(message, 'player2');
341
+ } else {
342
+ showMessage('🤝 תיקו!', 'draw');
343
+ }
344
+ }
345
+
346
+ // Show message
347
+ function showMessage(text, type) {
348
+ const turnIndicator = document.getElementById('turnIndicator');
349
+ turnIndicator.textContent = text;
350
+ turnIndicator.className = `message ${type}`;
351
+ }
352
+
353
+ // Update turn indicator
354
+ function updateTurnIndicator() {
355
+ const turnIndicator = document.getElementById('turnIndicator');
356
+ if (gameState.currentPlayer === PLAYER1) {
357
+ turnIndicator.textContent = 'תור שחקן 1';
358
+ turnIndicator.className = 'player1-turn';
359
+ } else {
360
+ const text = gameState.gameMode === 'pvc' ? 'תור המחשב' : 'תור שחקן 2';
361
+ turnIndicator.textContent = text;
362
+ turnIndicator.className = 'player2-turn';
363
+ }
364
+ }
365
+
366
+ // Update score
367
+ function updateScore() {
368
+ document.getElementById('score1').textContent = gameState.score1;
369
+ document.getElementById('score2').textContent = gameState.score2;
370
+ }
371
+
372
+ // New game
373
+ function newGame() {
374
+ initBoard();
375
+ }
376
+
377
+ // Reset score
378
+ function resetScore() {
379
+ gameState.score1 = 0;
380
+ gameState.score2 = 0;
381
+ localStorage.setItem('connect4Score1', 0);
382
+ localStorage.setItem('connect4Score2', 0);
383
+ updateScore();
384
+ }
385
+
386
+ // Game mode change
387
+ document.querySelectorAll('input[name="gameMode"]').forEach(radio => {
388
+ radio.addEventListener('change', (e) => {
389
+ gameState.gameMode = e.target.value;
390
+ const difficultySelector = document.querySelector('.difficulty-selector');
391
+
392
+ if (gameState.gameMode === 'pvc') {
393
+ difficultySelector.style.display = 'flex';
394
+ } else {
395
+ difficultySelector.style.display = 'none';
396
+ }
397
+
398
+ newGame();
399
+ });
400
+ });
401
+
402
+ // Difficulty change
403
+ document.getElementById('difficulty').addEventListener('change', (e) => {
404
+ gameState.difficulty = e.target.value;
405
+ });
406
+
407
+ // Event listeners
408
+ document.getElementById('newGameBtn').addEventListener('click', newGame);
409
+ document.getElementById('resetScoreBtn').addEventListener('click', resetScore);
410
+
411
+ // Initialize
412
+ updateScore();
413
+ initBoard();