pacman-contribution-graph 1.0.0 → 1.0.2

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/index.html CHANGED
@@ -3,6 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="google-site-verification" content="ETILrgmBZ33RjlxJh-ybUFcIlIyKXyefMvxbxC6LmOU" />
6
7
  <title>GitLab Contributions Pac-Man</title>
7
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" />
8
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
@@ -45,7 +46,7 @@
45
46
  <body>
46
47
  <nav class="navbar navbar-expand-lg fixed-top">
47
48
  <div class="container">
48
- <a class="navbar-brand" href="#">Pac-Man Contributions</a>
49
+ <a class="navbar-brand" href="https://abozanona.github.io/pacman-contribution-graph/">Pac-Man Contributions</a>
49
50
  <button
50
51
  class="navbar-toggler"
51
52
  type="button"
@@ -60,7 +61,7 @@
60
61
  <div class="collapse navbar-collapse" id="navbarNav">
61
62
  <ul class="navbar-nav ms-auto">
62
63
  <li class="nav-item">
63
- <a class="nav-link" href="https://abozanona.github.io/pacman-contribution-graph/" target="_blank"
64
+ <a class="nav-link" href="https://github.com/abozanona/pacman-contribution-graph/" target="_blank"
64
65
  ><i class="fab fa-github"></i> GitHub</a
65
66
  >
66
67
  </li>
@@ -148,10 +149,6 @@
148
149
  </div>
149
150
  </div>
150
151
  <button id="generate" class="btn btn-primary">Generate</button>
151
- <div class="alert alert-info my-2">
152
- <strong>Note:</strong> You might need to refresh the page after eachtime you change configuration. This is a known issue
153
- that we're working on it
154
- </div>
155
152
  </div>
156
153
 
157
154
  <div class="section">
@@ -162,6 +159,7 @@
162
159
  <br />
163
160
  <button id="downloadSvg" class="btn btn-success mt-3" style="display: none">Download SVG</button>
164
161
  </div>
162
+ <div>Commits count: <span id="points">0</span></div>
165
163
  </div>
166
164
 
167
165
  <div class="section">
@@ -229,49 +227,43 @@
229
227
  <h3>Method 1: NPM Package</h3>
230
228
  <pre><code>npm install pacman-contribution-graph
231
229
 
232
- import { renderContributions } from 'pacman-contribution-graph';
230
+ import { PacmanRenderer } from 'pacman-contribution-graph';
233
231
 
234
- renderContributions({
232
+ const pr = new PacmanRenderer({
235
233
  platform: 'github',
236
234
  username: 'yourusername',
237
235
  canvas: document.getElementById('canvas'),
238
236
  outputFormat: 'canvas',
239
237
  gameTheme: 'github'
240
- });</code></pre>
238
+ });
239
+ pr.start();
240
+ </code></pre>
241
241
 
242
242
  <h3>Method 2: Script loading</h3>
243
243
  <pre><code>&lt;script type="module"&gt;
244
- import { renderContributions } from 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.1/dist/pacman-contribution-graph.min.js';
245
- const canvas = document.getElementById('pacmancanvas');
246
- const initializeGameCanvas = () =>
247
- renderContributions({
248
- platform: "gitlab",
249
- username: "yourusername",
250
- canvas: canvas,
251
- output: 'canvas',
252
- gameOverCallback: () => {
253
- console.log('GAME OVER');
254
- setTimeout(() => {
255
- console.log('Restarting');
256
- initializeGameCanvas();
257
- }, 3000);
258
- }
259
- });
260
- initializeGameCanvas();
244
+ import { PacmanRenderer } from 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.1/dist/pacman-contribution-graph.min.js';
245
+ const pr = new PacmanRenderer({
246
+ platform: 'github',
247
+ username: 'yourusername',
248
+ canvas: document.getElementById('canvas'),
249
+ outputFormat: 'canvas',
250
+ gameTheme: 'github'
251
+ });
252
+ pr.start();
261
253
  &lt;/script&gt;</code></pre>
262
254
 
263
255
  <h3>Method 3: Iframe/Image Embedding</h3>
264
256
  <pre>
265
257
  &lt;!-- For canvas --&gt;
266
- <code>&lt;iframe src="https://abozanona.github.io/pacman-contribution-graph/?username=yourusername&platform=github"
258
+ <code>&lt;iframe src="https://abozanona.github.io/pacman-contribution-graph/embeded/canvas.html?username=yourusername&platform=github"
267
259
  width="800" height="600" frameborder="0"&gt;&lt;/iframe&gt;</code>
268
260
  &lt;!-- For SVG --&gt;
269
- <code>&lt;img src="https://abozanona.github.io/pacman-contribution-graph/?username=yourusername&platform=github" /&gt;</code>
261
+ <code>&lt;img src="https://abozanona.github.io/pacman-contribution-graph/embeded/svg.html?username=yourusername&platform=github" /&gt;</code>
270
262
  </pre>
271
263
  </div>
272
264
  </div>
273
265
 
274
- <footer class="bg-light py-3 mt-5">
266
+ <footer class="bg-light py-3 mt-5 invisible">
275
267
  <div class="container text-center">
276
268
  <div>
277
269
  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
@@ -284,7 +276,7 @@ initializeGameCanvas();
284
276
 
285
277
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
286
278
  <script type="module">
287
- import { renderContributions } from './dist/pacman-contribution-graph.js';
279
+ import { PacmanRenderer } from './dist/pacman-contribution-graph.js';
288
280
 
289
281
  const generateButton = document.getElementById('generate');
290
282
  const usernameInput = document.getElementById('username');
@@ -300,6 +292,7 @@ initializeGameCanvas();
300
292
  const downloadSvgButton = document.getElementById('downloadSvg');
301
293
  const userAvatar = document.getElementById('userAvatar');
302
294
  const userNotFound = document.getElementById('userNotFound');
295
+ const points = document.getElementById('points');
303
296
 
304
297
  generateButton.disabled = true;
305
298
 
@@ -310,6 +303,7 @@ initializeGameCanvas();
310
303
  });
311
304
 
312
305
  usernameInput.addEventListener('input', debounce(checkUser, 500));
306
+ platformSelect.addEventListener('input', debounce(checkUser, 500));
313
307
 
314
308
  function debounce(func, wait) {
315
309
  let timeout;
@@ -333,24 +327,48 @@ initializeGameCanvas();
333
327
  return;
334
328
  }
335
329
 
336
- try {
337
- const response = await fetch(`https://api.${platform}.com/users/${username}`);
338
- if (response.ok) {
339
- const data = await response.json();
340
- userAvatar.src = data.avatar_url;
341
- userAvatar.style.display = 'inline';
342
- userNotFound.style.display = 'none';
343
- generateButton.disabled = false;
344
- } else {
345
- throw new Error('User not found');
330
+ if (platform == 'github') {
331
+ try {
332
+ const response = await fetch(`https://api.github.com/users/${username}`);
333
+ if (response.ok) {
334
+ const data = await response.json();
335
+ userAvatar.src = data.avatar_url;
336
+ userAvatar.style.display = 'inline';
337
+ userNotFound.style.display = 'none';
338
+ generateButton.disabled = false;
339
+ } else {
340
+ throw new Error('User not found');
341
+ }
342
+ } catch (error) {
343
+ userAvatar.style.display = 'none';
344
+ userNotFound.style.display = 'block';
345
+ generateButton.disabled = true;
346
+ }
347
+ } else {
348
+ try {
349
+ const response = await fetch(`https://gitlab.com/api/v4/users?username=${username}`);
350
+ if (response.ok) {
351
+ const data = await response.json();
352
+ if (!data.length) {
353
+ throw new Error('User not found');
354
+ }
355
+ userAvatar.src = data[0].avatar_url;
356
+ userAvatar.style.display = 'inline';
357
+ userNotFound.style.display = 'none';
358
+ generateButton.disabled = false;
359
+ } else {
360
+ throw new Error('User not found');
361
+ }
362
+ } catch (error) {
363
+ userAvatar.style.display = 'none';
364
+ userNotFound.style.display = 'block';
365
+ generateButton.disabled = true;
346
366
  }
347
- } catch (error) {
348
- userAvatar.style.display = 'none';
349
- userNotFound.style.display = 'block';
350
- generateButton.disabled = true;
351
367
  }
352
368
  }
353
369
 
370
+ let pr = undefined;
371
+
354
372
  generateButton.addEventListener('click', () => {
355
373
  const config = {
356
374
  platform: platformSelect.value,
@@ -365,19 +383,29 @@ initializeGameCanvas();
365
383
  canvas.style.display = 'block';
366
384
  svgContainer.style.display = 'none';
367
385
  downloadSvgButton.style.display = 'none';
368
- renderContributions({
386
+ if (pr !== undefined) {
387
+ pr.stop();
388
+ }
389
+ pr = new PacmanRenderer({
369
390
  ...config,
370
391
  canvas: canvas,
371
392
  gameOverCallback: () => {
372
393
  console.log('Game Over');
373
- setTimeout(() => renderContributions({ ...config, canvas: canvas }), 3000);
394
+ setTimeout(() => pr.start(), 3000);
395
+ },
396
+ pointsIncreasedCallback: (pointsSum) => {
397
+ points.innerText = pointsSum;
374
398
  }
375
399
  });
400
+ pr.start();
376
401
  } else {
377
402
  canvas.style.display = 'none';
378
403
  svgContainer.style.display = 'block';
379
404
  downloadSvgButton.style.display = 'inline-block';
380
- renderContributions({
405
+ if (pr !== undefined) {
406
+ pr.stop();
407
+ }
408
+ pr = new PacmanRenderer({
381
409
  ...config,
382
410
  svgCallback: (blobUrl) => {
383
411
  svgHolder.src = blobUrl;
@@ -385,8 +413,12 @@ initializeGameCanvas();
385
413
  },
386
414
  gameOverCallback: () => {
387
415
  console.log('Game Over');
416
+ },
417
+ pointsIncreasedCallback: (pointsSum) => {
418
+ points.innerText = pointsSum;
388
419
  }
389
420
  });
421
+ pr.start();
390
422
  }
391
423
  });
392
424
 
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "pacman-contribution-graph",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Generates a pacman game from a github or gitlab user contributions grid",
5
5
  "repository": "github:abozanona/pacman-contribution-graph",
6
+ "homepage": "https://abozanona.github.io/pacman-contribution-graph/",
6
7
  "type": "module",
7
- "main": "index.js",
8
+ "main": "dist/pacman-contribution-graph.min.js",
8
9
  "scripts": {
9
10
  "build": "webpack --config webpack.prod.js",
10
11
  "dev": "webpack --progress --config webpack.dev.js"
@@ -0,0 +1,31 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ export async function GET(request: Request) {
4
+ const { searchParams } = new URL(request.url);
5
+ const username = searchParams.get('username');
6
+
7
+ if (!username) {
8
+ return NextResponse.json({ error: 'Username is required' }, { status: 400 });
9
+ }
10
+
11
+ try {
12
+ const response = await fetch(`https://gitlab.com/users/${username}/calendar.json`);
13
+
14
+ if (!response.ok) {
15
+ throw new Error('Failed to fetch contributions from GitLab');
16
+ }
17
+
18
+ const contributionsList = await response.json();
19
+
20
+ // Create a new response with CORS headers
21
+ const corsResponse = NextResponse.json(contributionsList);
22
+ corsResponse.headers.set('Access-Control-Allow-Origin', '*');
23
+ corsResponse.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
24
+ corsResponse.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
25
+
26
+ return corsResponse;
27
+ } catch (error) {
28
+ console.error('Error fetching contributions:', error);
29
+ return NextResponse.json({ error: 'Failed to fetch contributions' }, { status: 500 });
30
+ }
31
+ }
@@ -0,0 +1,13 @@
1
+ //
2
+ export default function Home() {
3
+ return (
4
+ <div className="p-8">
5
+ <h1 className="text-3xl font-bold mb-4">GitHub and GitLab API Routes</h1>
6
+ <p className="mb-4">Use the following API routes:</p>
7
+ <ul className="list-disc pl-8">
8
+ <li>/api/contributions?username=USERNAME</li>
9
+ </ul>
10
+ <p className="mt-4">Replace 'USERNAME' with an actual GitLab username.</p>
11
+ </div>
12
+ );
13
+ }
package/src/canvas.ts CHANGED
@@ -1,70 +1,70 @@
1
- import { CELL_SIZE, GAP_SIZE, GRID_HEIGHT, GRID_WIDTH, PACMAN_COLOR, PACMAN_COLOR_DEAD, PACMAN_COLOR_POWERUP } from './constants';
1
+ import { CELL_SIZE, GAP_SIZE, GHOSTS, GRID_HEIGHT, GRID_WIDTH, PACMAN_COLOR, PACMAN_COLOR_DEAD, PACMAN_COLOR_POWERUP } from './constants';
2
2
  import { MusicPlayer } from './music-player';
3
- import { Store } from './store';
3
+ import { StoreType } from './types';
4
4
  import { Utils } from './utils';
5
5
 
6
- const resizeCanvas = () => {
6
+ const resizeCanvas = (store: StoreType) => {
7
7
  const canvasWidth = GRID_WIDTH * (CELL_SIZE + GAP_SIZE);
8
8
  const canvasHeight = GRID_HEIGHT * (CELL_SIZE + GAP_SIZE) + 20; // Adding some space for months on top
9
9
 
10
- Store.config.canvas.width = canvasWidth;
11
- Store.config.canvas.height = canvasHeight;
10
+ store.config.canvas.width = canvasWidth;
11
+ store.config.canvas.height = canvasHeight;
12
12
  };
13
13
 
14
- const drawGrid = () => {
15
- Store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme().gridBackground;
16
- Store.config.canvas.getContext('2d')!.fillRect(0, 0, Store.config.canvas.width, Store.config.canvas.height);
14
+ const drawGrid = (store: StoreType) => {
15
+ store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme(store).gridBackground;
16
+ store.config.canvas.getContext('2d')!.fillRect(0, 0, store.config.canvas.width, store.config.canvas.height);
17
17
 
18
18
  for (let x = 0; x < GRID_HEIGHT; x++) {
19
19
  for (let y = 0; y < GRID_WIDTH; y++) {
20
- const intensity = Store.grid[x][y];
20
+ const intensity = store.grid[x][y].intensity;
21
21
  if (intensity > 0) {
22
22
  const adjustedIntensity = intensity < 0.2 ? 0.3 : intensity;
23
- const color = Utils.hexToRGBA(Utils.getCurrentTheme().contributionBoxColor, adjustedIntensity);
24
- Store.config.canvas.getContext('2d')!.fillStyle = color;
23
+ const color = Utils.hexToRGBA(Utils.getCurrentTheme(store).contributionBoxColor, adjustedIntensity);
24
+ store.config.canvas.getContext('2d')!.fillStyle = color;
25
25
  } else {
26
- Store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme().emptyContributionBoxColor;
26
+ store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme(store).emptyContributionBoxColor;
27
27
  }
28
- Store.config.canvas.getContext('2d')!.beginPath();
29
- Store.config.canvas
28
+ store.config.canvas.getContext('2d')!.beginPath();
29
+ store.config.canvas
30
30
  .getContext('2d')!
31
31
  .roundRect(y * (CELL_SIZE + GAP_SIZE), x * (CELL_SIZE + GAP_SIZE) + 15, CELL_SIZE, CELL_SIZE, 5);
32
- Store.config.canvas.getContext('2d')!.fill();
32
+ store.config.canvas.getContext('2d')!.fill();
33
33
  }
34
34
  }
35
35
 
36
- Store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme().textColor;
37
- Store.config.canvas.getContext('2d')!.font = '10px Arial';
38
- Store.config.canvas.getContext('2d')!.textAlign = 'center';
36
+ store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme(store).textColor;
37
+ store.config.canvas.getContext('2d')!.font = '10px Arial';
38
+ store.config.canvas.getContext('2d')!.textAlign = 'center';
39
39
 
40
40
  let lastMonth = '';
41
41
  for (let y = 0; y < GRID_WIDTH; y++) {
42
- if (Store.monthLabels[y] !== lastMonth) {
42
+ if (store.monthLabels[y] !== lastMonth) {
43
43
  const xPos = y * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
44
- Store.config.canvas.getContext('2d')!.fillText(Store.monthLabels[y], xPos, 10);
45
- lastMonth = Store.monthLabels[y];
44
+ store.config.canvas.getContext('2d')!.fillText(store.monthLabels[y], xPos, 10);
45
+ lastMonth = store.monthLabels[y];
46
46
  }
47
47
  }
48
48
  };
49
49
 
50
- const drawPacman = () => {
51
- const x = Store.pacman.y * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
52
- const y = Store.pacman.x * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2 + 15;
50
+ const drawPacman = (store: StoreType) => {
51
+ const x = store.pacman.y * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
52
+ const y = store.pacman.x * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2 + 15;
53
53
  const radius = CELL_SIZE / 2;
54
54
 
55
55
  // Change Pac-Man's color to red if he's on power-up, dead, else yellow
56
- if (Store.pacman.deadReaminingDuration) {
57
- Store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR_DEAD;
58
- } else if (Store.pacman.powerupReaminingDuration) {
59
- Store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR_POWERUP;
56
+ if (store.pacman.deadRemainingDuration) {
57
+ store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR_DEAD;
58
+ } else if (store.pacman.powerupRemainingDuration) {
59
+ store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR_POWERUP;
60
60
  } else {
61
- Store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR;
61
+ store.config.canvas.getContext('2d')!.fillStyle = PACMAN_COLOR;
62
62
  }
63
63
 
64
- const mouthAngle = Store.pacmanMouthOpen ? 0.35 * Math.PI : 0.1 * Math.PI;
64
+ const mouthAngle = store.pacmanMouthOpen ? 0.35 * Math.PI : 0.1 * Math.PI;
65
65
 
66
66
  let startAngle, endAngle;
67
- switch (Store.pacman.direction) {
67
+ switch (store.pacman.direction) {
68
68
  case 'up':
69
69
  startAngle = 1.5 * Math.PI + mouthAngle;
70
70
  endAngle = 1.5 * Math.PI - mouthAngle;
@@ -84,99 +84,87 @@ const drawPacman = () => {
84
84
  break;
85
85
  }
86
86
 
87
- Store.config.canvas.getContext('2d')!.beginPath();
88
- Store.config.canvas.getContext('2d')!.arc(x, y, radius, startAngle, endAngle);
89
- Store.config.canvas.getContext('2d')!.lineTo(x, y);
90
- Store.config.canvas.getContext('2d')!.fill();
87
+ store.config.canvas.getContext('2d')!.beginPath();
88
+ store.config.canvas.getContext('2d')!.arc(x, y, radius, startAngle, endAngle);
89
+ store.config.canvas.getContext('2d')!.lineTo(x, y);
90
+ store.config.canvas.getContext('2d')!.fill();
91
91
  };
92
92
 
93
- const drawGhosts = () => {
94
- Store.ghosts.forEach((ghost) => {
95
- const x = ghost.y * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
96
- const y = ghost.x * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2 + 15;
97
- const radius = CELL_SIZE / 2;
98
-
99
- Store.config.canvas.getContext('2d')!.fillStyle = ghost.scared ? 'blue' : ghost.color;
100
- Store.config.canvas.getContext('2d')!.beginPath();
101
- Store.config.canvas.getContext('2d')!.arc(x, y, radius, 0, Math.PI);
102
- Store.config.canvas.getContext('2d')!.rect(x - radius, y, radius * 2, radius);
103
- Store.config.canvas.getContext('2d')!.fill();
104
-
105
- Store.config.canvas.getContext('2d')!.fillStyle = 'white';
106
- Store.config.canvas.getContext('2d')!.beginPath();
107
- Store.config.canvas.getContext('2d')!.arc(x - radius / 3, y - radius / 3, radius / 4, 0, Math.PI * 2);
108
- Store.config.canvas.getContext('2d')!.arc(x + radius / 3, y - radius / 3, radius / 4, 0, Math.PI * 2);
109
- Store.config.canvas.getContext('2d')!.fill();
110
-
111
- Store.config.canvas.getContext('2d')!.fillStyle = 'black';
112
- Store.config.canvas.getContext('2d')!.beginPath();
113
- Store.config.canvas.getContext('2d')!.arc(x - radius / 3, y - radius / 3, radius / 8, 0, Math.PI * 2);
114
- Store.config.canvas.getContext('2d')!.arc(x + radius / 3, y - radius / 3, radius / 8, 0, Math.PI * 2);
115
- Store.config.canvas.getContext('2d')!.fill();
93
+ const drawGhosts = (store: StoreType) => {
94
+ store.ghosts.forEach((ghost) => {
95
+ const x = ghost.y * (CELL_SIZE + GAP_SIZE);
96
+ const y = ghost.x * (CELL_SIZE + GAP_SIZE) + 15;
97
+ const size = CELL_SIZE;
98
+
99
+ const ctx = store.config.canvas.getContext('2d')!;
100
+ if (ghost.scared) {
101
+ ctx.drawImage(GHOSTS['scared'].img, x, y, size, size);
102
+ } else {
103
+ ctx.drawImage(GHOSTS[ghost.name].img, x, y, size, size);
104
+ }
116
105
  });
117
106
  };
118
107
 
119
- const renderGameOver = () => {
120
- Store.config.canvas.getContext('2d')!.fillStyle = 'black';
121
- Store.config.canvas.getContext('2d')!.font = '20px Arial';
122
- Store.config.canvas.getContext('2d')!.textAlign = 'center';
123
- Store.config.canvas.getContext('2d')!.fillText('Game Over', Store.config.canvas.width / 2, Store.config.canvas.height / 2);
108
+ const renderGameOver = (store: StoreType) => {
109
+ store.config.canvas.getContext('2d')!.fillStyle = Utils.getCurrentTheme(store).textColor;
110
+ store.config.canvas.getContext('2d')!.font = '20px Arial';
111
+ store.config.canvas.getContext('2d')!.textAlign = 'center';
112
+ store.config.canvas.getContext('2d')!.fillText('Game Over', store.config.canvas.width / 2, store.config.canvas.height / 2);
124
113
  };
125
114
 
126
- const drawSoundController = () => {
127
- if (!Store.config.enableSounds) {
128
- console.log('vvvv');
115
+ const drawSoundController = (store: StoreType) => {
116
+ if (!store.config.enableSounds) {
129
117
  return;
130
118
  }
131
119
 
132
120
  const width = 30,
133
121
  height = 30,
134
- left = Store.config.canvas.width - width - 10,
122
+ left = store.config.canvas.width - width - 10,
135
123
  top = 10;
136
- Store.config.canvas.getContext('2d')!.fillStyle = `rgba(0, 0, 0, ${MusicPlayer.getInstance().isMuted ? 0.3 : 0.5})`;
137
- Store.config.canvas.getContext('2d')!.beginPath();
138
- Store.config.canvas.getContext('2d')!.moveTo(left + 10, top + 10);
139
- Store.config.canvas.getContext('2d')!.lineTo(left + 20, top + 5);
140
- Store.config.canvas.getContext('2d')!.lineTo(left + 20, top + 25);
141
- Store.config.canvas.getContext('2d')!.lineTo(left + 10, top + 20);
142
- Store.config.canvas.getContext('2d')!.closePath();
143
- Store.config.canvas.getContext('2d')!.fill();
124
+ store.config.canvas.getContext('2d')!.fillStyle = `rgba(0, 0, 0, ${MusicPlayer.getInstance().isMuted ? 0.3 : 0.5})`;
125
+ store.config.canvas.getContext('2d')!.beginPath();
126
+ store.config.canvas.getContext('2d')!.moveTo(left + 10, top + 10);
127
+ store.config.canvas.getContext('2d')!.lineTo(left + 20, top + 5);
128
+ store.config.canvas.getContext('2d')!.lineTo(left + 20, top + 25);
129
+ store.config.canvas.getContext('2d')!.lineTo(left + 10, top + 20);
130
+ store.config.canvas.getContext('2d')!.closePath();
131
+ store.config.canvas.getContext('2d')!.fill();
144
132
 
145
133
  if (!MusicPlayer.getInstance().isMuted) {
146
- Store.config.canvas.getContext('2d')!.strokeStyle = `rgba(0, 0, 0, 0.4)`;
147
- Store.config.canvas.getContext('2d')!.lineWidth = 2;
134
+ store.config.canvas.getContext('2d')!.strokeStyle = `rgba(0, 0, 0, 0.4)`;
135
+ store.config.canvas.getContext('2d')!.lineWidth = 2;
148
136
 
149
137
  // First wave
150
- Store.config.canvas.getContext('2d')!.beginPath();
151
- Store.config.canvas.getContext('2d')!.arc(left + 25, top + 15, 5, 0, Math.PI * 2);
152
- Store.config.canvas.getContext('2d')!.stroke();
138
+ store.config.canvas.getContext('2d')!.beginPath();
139
+ store.config.canvas.getContext('2d')!.arc(left + 25, top + 15, 5, 0, Math.PI * 2);
140
+ store.config.canvas.getContext('2d')!.stroke();
153
141
 
154
142
  // Second wave
155
- Store.config.canvas.getContext('2d')!.beginPath();
156
- Store.config.canvas.getContext('2d')!.arc(left + 25, top + 15, 8, 0, Math.PI * 2);
157
- Store.config.canvas.getContext('2d')!.stroke();
143
+ store.config.canvas.getContext('2d')!.beginPath();
144
+ store.config.canvas.getContext('2d')!.arc(left + 25, top + 15, 8, 0, Math.PI * 2);
145
+ store.config.canvas.getContext('2d')!.stroke();
158
146
  } else {
159
147
  // Mute line
160
- Store.config.canvas.getContext('2d')!.strokeStyle = 'rgba(255, 0, 0, 0.6)';
161
- Store.config.canvas.getContext('2d')!.lineWidth = 3;
162
- Store.config.canvas.getContext('2d')!.beginPath();
163
- Store.config.canvas.getContext('2d')!.moveTo(left + 25, top + 5);
164
- Store.config.canvas.getContext('2d')!.lineTo(left + 5, top + 25);
165
- Store.config.canvas.getContext('2d')!.stroke();
148
+ store.config.canvas.getContext('2d')!.strokeStyle = 'rgba(255, 0, 0, 0.6)';
149
+ store.config.canvas.getContext('2d')!.lineWidth = 3;
150
+ store.config.canvas.getContext('2d')!.beginPath();
151
+ store.config.canvas.getContext('2d')!.moveTo(left + 25, top + 5);
152
+ store.config.canvas.getContext('2d')!.lineTo(left + 5, top + 25);
153
+ store.config.canvas.getContext('2d')!.stroke();
166
154
  }
167
155
  };
168
156
 
169
- const listenToSoundController = () => {
170
- if (!Store.config.enableSounds) {
157
+ const listenToSoundController = (store: StoreType) => {
158
+ if (!store.config.enableSounds) {
171
159
  return;
172
160
  }
173
- Store.config.canvas.addEventListener('click', function (event) {
174
- const rect = Store.config.canvas.getBoundingClientRect();
161
+ store.config.canvas.addEventListener('click', function (event) {
162
+ const rect = store.config.canvas.getBoundingClientRect();
175
163
  const x = event.clientX - rect.left,
176
164
  y = event.clientY - rect.top;
177
165
  const width = 30,
178
166
  height = 30,
179
- left = Store.config.canvas.width - width - 10,
167
+ left = store.config.canvas.width - width - 10,
180
168
  top = 10;
181
169
 
182
170
  if (x >= left && x <= left + this.width && y >= top && y <= top + this.height) {
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GameTheme, ThemeKeys } from './types';
1
+ import { GameTheme, GhostName, ThemeKeys } from './types';
2
2
 
3
3
  export const CELL_SIZE = 20;
4
4
  export const GAP_SIZE = 2;
@@ -7,7 +7,7 @@ export const GRID_HEIGHT = 7;
7
7
  export const PACMAN_COLOR = 'yellow';
8
8
  export const PACMAN_COLOR_POWERUP = 'red';
9
9
  export const PACMAN_COLOR_DEAD = '#80808064';
10
- export const GHOST_COLORS = ['red', 'pink', 'cyan', 'orange'];
10
+ export const GHOST_NAMES: GhostName[] = ['blinky', 'clyde', 'inky', 'pinky'];
11
11
  export const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
12
12
  export const DELTA_TIME = 250;
13
13
  export const PACMAN_DEATH_DURATION = 10;
@@ -38,3 +38,30 @@ export const GAME_THEMES: { [key in ThemeKeys]: GameTheme } = {
38
38
  emptyContributionBoxColor: '#2d2d2d'
39
39
  }
40
40
  };
41
+ export const GHOSTS: { [key in GhostName | 'scared']: { imgDate: string; img: HTMLImageElement } } = {
42
+ blinky: {
43
+ imgDate:
44
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfUlEQVQ4T+2TUQ7AIAhDy/0PzQIRAqxmLtnn/DJPWypBAVkKKOMCyOQN7IRElLrcnIrDLNK4wVtxNbkb6Hq+jOcSbim6QVzKEstkw92gxVeFrMpqokix4wA+NvCOnvfArvcEbHoe2G9QmmhDMUc65p3xYC6q3zQPxtdl3NgF5QpL/b/rs3IAAAAASUVORK5CYIIA',
45
+ img: new Image()
46
+ },
47
+ clyde: {
48
+ imgDate:
49
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgUlEQVQ4T+2T0Q6AIAhFLx9sH1MfTIPCAeLKrcd8PHqP4JBQLN7BFacNlHkAs+AQcqIueBs2mVWjgtWwl4yCdrd/pHYLLlVEgR2yK0wy4SoI5TcGXU4wM+AEJQfwsUCuXngDOR4rqKbngf0C94gyFHmkbd4rbkxD/pv2jfR1Ky7sBNrzXbHpnBX+AAAAAElFTkSuQmCC',
50
+ img: new Image()
51
+ },
52
+ inky: {
53
+ imgDate:
54
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAg0lEQVQ4T+WTWxKAIAhFuQvK/a+jFoT5QAVxypn+6vMEx6sDIO/jk12OAMs1WDVOXV3UBW+bRVbTFMFu8yCZBExH/g26VHCXI0AJpKgdUCUrTlkwxE+FECdzS7HiJemXgvyeO29gE7jD8wDVFX4vSLNtR1q2z+OVlaZxTaXYrq7HbxYBS8VgMVrqzkEAAAAASUVORK5CYIIA',
55
+ img: new Image()
56
+ },
57
+ pinky: {
58
+ imgDate:
59
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVQ4T+2T0Q2AIAwF281wC50Qt9DNagoptqVESfyUz4N3vJCCECxaD4o47gt6bsAo2IWUqAnehkUmbYpgNqwlvSCnur+dtnnAuYUVyCGJimTAi8DUzwmwOoGI7hYjDgAfC/jqiTfg47ZBND0P7BeoR+Sh8CMt8x5xYSWkv2nbcF834swuA/9u49Yy5bgAAAAASUVORK5CYIIA',
60
+ img: new Image()
61
+ },
62
+ scared: {
63
+ imgDate:
64
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAeUlEQVQ4T82TUQ6AMAhD7UX0/sdyF0GREVmDmTN+bH9r6Bs0A0t2VpFULwDrrfBkZFcA3YC3ZodViAFGzQHyP0B2w2NrB0/1AoDbHwLoQ5/nrw1OBuD5e/crbM9Aiz35njHWzpSB/m3+0r40mV41M8U19WJe3Uw/tQOKt08pUUbBEQAAAABJRU5ErkJgggAA',
65
+ img: new Image()
66
+ }
67
+ };