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/README.md +11 -7
- package/assets/packman-demo.png +0 -0
- package/dist/pacman-contribution-graph.js +372 -341
- package/dist/pacman-contribution-graph.js.map +1 -1
- package/dist/pacman-contribution-graph.min.js +1 -1
- package/embeded/canvas.html +41 -0
- package/embeded/svg.html +18 -0
- package/index.html +79 -47
- package/package.json +3 -2
- package/server/api/contributions/route.ts.z +31 -0
- package/server/page.zts.z +13 -0
- package/src/assets/images/ghosts/blinky.png +0 -0
- package/src/assets/images/ghosts/clyde.png +0 -0
- package/src/assets/images/ghosts/inky.png +0 -0
- package/src/assets/images/ghosts/pinky.png +0 -0
- package/src/assets/images/ghosts/scared.png +0 -0
- package/src/canvas.ts +82 -94
- package/src/constants.ts +29 -2
- package/src/game.ts +144 -121
- package/src/index.ts +38 -23
- package/src/music-player.ts +13 -7
- package/src/store.ts +3 -2
- package/src/svg.ts +69 -78
- package/src/types.ts +7 -4
- package/src/utils.ts +7 -5
package/src/game.ts
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
import { Canvas } from './canvas';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DELTA_TIME,
|
|
4
|
+
GHOST_NAMES,
|
|
5
|
+
GHOSTS,
|
|
6
|
+
GRID_HEIGHT,
|
|
7
|
+
GRID_WIDTH,
|
|
8
|
+
MONTHS,
|
|
9
|
+
PACMAN_DEATH_DURATION,
|
|
10
|
+
PACMAN_POWERUP_DURATION
|
|
11
|
+
} from './constants';
|
|
3
12
|
import { MusicPlayer, Sound } from './music-player';
|
|
4
|
-
import { Store } from './store';
|
|
5
13
|
import { SVG } from './svg';
|
|
14
|
+
import { StoreType } from './types';
|
|
6
15
|
|
|
7
|
-
const initializeGrid = () => {
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
const initializeGrid = (store: StoreType) => {
|
|
17
|
+
store.pacman.points = 0;
|
|
18
|
+
store.pacman.totalPoints = 0;
|
|
19
|
+
store.grid = Array.from({ length: GRID_HEIGHT }, () => Array.from({ length: GRID_WIDTH }, () => ({ commitsCount: 0, intensity: 0 })));
|
|
20
|
+
store.monthLabels = Array(GRID_WIDTH).fill('');
|
|
10
21
|
let maxCommits = 1;
|
|
11
22
|
|
|
12
23
|
const now = new Date();
|
|
13
24
|
const startOfCurrentWeek = new Date(now);
|
|
14
25
|
startOfCurrentWeek.setDate(now.getDate() - now.getDay());
|
|
15
26
|
|
|
16
|
-
|
|
27
|
+
store.contributions.forEach((contribution) => {
|
|
17
28
|
const contributionDate = new Date(contribution.date);
|
|
18
29
|
const dayOfWeek = contributionDate.getDay();
|
|
19
30
|
const weeksAgo = Math.floor((+startOfCurrentWeek - +contributionDate) / (1000 * 60 * 60 * 24 * 7));
|
|
20
31
|
|
|
21
32
|
if (weeksAgo >= 0 && weeksAgo < GRID_WIDTH && dayOfWeek >= 0 && dayOfWeek < GRID_HEIGHT) {
|
|
22
|
-
|
|
33
|
+
store.grid[dayOfWeek][GRID_WIDTH - 1 - weeksAgo] = { commitsCount: contribution.count, intensity: 0 };
|
|
23
34
|
if (contribution.count > maxCommits) maxCommits = contribution.count;
|
|
24
35
|
}
|
|
25
36
|
});
|
|
26
37
|
|
|
27
38
|
for (let x = 0; x < GRID_HEIGHT; x++) {
|
|
28
39
|
for (let y = 0; y < GRID_WIDTH; y++) {
|
|
29
|
-
if (
|
|
30
|
-
|
|
40
|
+
if (store.grid[x][y].commitsCount > 0) {
|
|
41
|
+
store.grid[x][y].intensity = store.grid[x][y].commitsCount / maxCommits;
|
|
31
42
|
}
|
|
32
43
|
}
|
|
33
44
|
}
|
|
@@ -36,63 +47,66 @@ const initializeGrid = () => {
|
|
|
36
47
|
const weeksAgo = GRID_WIDTH - 1 - y;
|
|
37
48
|
const columnDate = new Date(startOfCurrentWeek);
|
|
38
49
|
columnDate.setDate(columnDate.getDate() - weeksAgo * 7);
|
|
39
|
-
|
|
50
|
+
store.monthLabels[y] = MONTHS[columnDate.getMonth()];
|
|
40
51
|
}
|
|
41
52
|
};
|
|
42
53
|
|
|
43
|
-
const placePacman = () => {
|
|
54
|
+
const placePacman = (store: StoreType) => {
|
|
44
55
|
let validCells = [];
|
|
45
56
|
for (let x = 0; x < GRID_HEIGHT; x++) {
|
|
46
57
|
for (let y = 0; y < GRID_WIDTH; y++) {
|
|
47
|
-
if (
|
|
58
|
+
if (store.grid[x][y].intensity > 0) validCells.push({ x, y });
|
|
48
59
|
}
|
|
49
60
|
}
|
|
50
61
|
if (validCells.length > 0) {
|
|
51
62
|
const randomCell = validCells[Math.floor(Math.random() * validCells.length)];
|
|
52
|
-
|
|
63
|
+
store.pacman = {
|
|
53
64
|
x: randomCell.x,
|
|
54
65
|
y: randomCell.y,
|
|
55
66
|
direction: 'right',
|
|
56
67
|
points: 0,
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
totalPoints: 0,
|
|
69
|
+
deadRemainingDuration: 0,
|
|
70
|
+
powerupRemainingDuration: 0
|
|
59
71
|
};
|
|
60
72
|
}
|
|
61
|
-
if (
|
|
73
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawPacman(store);
|
|
62
74
|
};
|
|
63
75
|
|
|
64
|
-
const placeGhosts = () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// Create 4 ghosts
|
|
76
|
+
const placeGhosts = (store: StoreType) => {
|
|
77
|
+
store.ghosts = [];
|
|
78
|
+
store.scaredGhostsDestinations = [];
|
|
68
79
|
for (let i = 0; i < 4; i++) {
|
|
69
|
-
const color = GHOST_COLORS[i % GHOST_COLORS.length];
|
|
70
80
|
let x, y;
|
|
71
81
|
do {
|
|
72
82
|
x = Math.floor(Math.random() * GRID_HEIGHT);
|
|
73
83
|
y = Math.floor(Math.random() * GRID_WIDTH);
|
|
74
|
-
} while (
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
} while (store.grid[x][y].intensity === 0);
|
|
85
|
+
store.ghosts.push({ x, y, name: GHOST_NAMES[i], scared: false, target: undefined });
|
|
86
|
+
store.scaredGhostsDestinations.push({ x: 0, y: 0 });
|
|
77
87
|
}
|
|
78
|
-
if (
|
|
88
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawGhosts(store);
|
|
79
89
|
};
|
|
80
90
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
const stopGame = async (store: StoreType) => {
|
|
92
|
+
clearInterval(store.gameInterval);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const startGame = async (store: StoreType) => {
|
|
96
|
+
if (store.config.outputFormat == 'canvas') {
|
|
97
|
+
store.config.canvas = store.config.canvas;
|
|
98
|
+
Canvas.resizeCanvas(store);
|
|
99
|
+
Canvas.listenToSoundController(store);
|
|
86
100
|
}
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
store.frameCount = 0;
|
|
103
|
+
store.ghosts.forEach((ghost) => (ghost.scared = false));
|
|
90
104
|
|
|
91
|
-
initializeGrid();
|
|
92
|
-
if (
|
|
105
|
+
initializeGrid(store);
|
|
106
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawGrid(store);
|
|
93
107
|
|
|
94
|
-
if (
|
|
95
|
-
if (!
|
|
108
|
+
if (store.config.outputFormat == 'canvas') {
|
|
109
|
+
if (!store.config.enableSounds) {
|
|
96
110
|
MusicPlayer.getInstance().mute();
|
|
97
111
|
}
|
|
98
112
|
await MusicPlayer.getInstance().preloadSounds();
|
|
@@ -100,103 +114,109 @@ const startGame = async () => {
|
|
|
100
114
|
await MusicPlayer.getInstance().play(Sound.BEGINNING);
|
|
101
115
|
}
|
|
102
116
|
|
|
103
|
-
placePacman();
|
|
104
|
-
placeGhosts();
|
|
117
|
+
placePacman(store);
|
|
118
|
+
placeGhosts(store);
|
|
119
|
+
|
|
120
|
+
GHOSTS.blinky.img.src = GHOSTS.blinky.imgDate;
|
|
121
|
+
GHOSTS.clyde.img.src = GHOSTS.clyde.imgDate;
|
|
122
|
+
GHOSTS.inky.img.src = GHOSTS.inky.imgDate;
|
|
123
|
+
GHOSTS.pinky.img.src = GHOSTS.pinky.imgDate;
|
|
124
|
+
GHOSTS.scared.img.src = GHOSTS.scared.imgDate;
|
|
105
125
|
|
|
106
|
-
if (
|
|
107
|
-
const remainingCells = () =>
|
|
126
|
+
if (store.config.outputFormat == 'svg') {
|
|
127
|
+
const remainingCells = () => store.grid.some((row) => row.some((cell) => cell.intensity > 0));
|
|
108
128
|
while (remainingCells()) {
|
|
109
|
-
await updateGame();
|
|
129
|
+
await updateGame(store);
|
|
110
130
|
}
|
|
111
131
|
// One more time to generate svg
|
|
112
|
-
await updateGame();
|
|
132
|
+
await updateGame(store);
|
|
113
133
|
} else {
|
|
114
|
-
clearInterval(
|
|
115
|
-
|
|
134
|
+
clearInterval(store.gameInterval);
|
|
135
|
+
store.gameInterval = setInterval(async () => await updateGame(store), DELTA_TIME);
|
|
116
136
|
}
|
|
117
137
|
};
|
|
118
138
|
|
|
119
|
-
const updateGame = async () => {
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
pacman: { ...
|
|
124
|
-
ghosts:
|
|
125
|
-
grid:
|
|
139
|
+
const updateGame = async (store: StoreType) => {
|
|
140
|
+
store.frameCount++;
|
|
141
|
+
if (store.frameCount % store.config.gameSpeed !== 0) {
|
|
142
|
+
store.gameHistory.push({
|
|
143
|
+
pacman: { ...store.pacman },
|
|
144
|
+
ghosts: store.ghosts.map((ghost) => ({ ...ghost })),
|
|
145
|
+
grid: store.grid.map((row) => [...row.map((col) => col.intensity)])
|
|
126
146
|
});
|
|
127
147
|
return;
|
|
128
148
|
}
|
|
129
149
|
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
if (!
|
|
150
|
+
if (store.pacman.deadRemainingDuration) {
|
|
151
|
+
store.pacman.deadRemainingDuration--;
|
|
152
|
+
if (!store.pacman.deadRemainingDuration) {
|
|
133
153
|
// IT'S ALIVE!
|
|
134
|
-
if (
|
|
154
|
+
if (store.config.outputFormat == 'canvas')
|
|
135
155
|
MusicPlayer.getInstance()
|
|
136
156
|
.play(Sound.GAME_OVER)
|
|
137
157
|
.then(() => MusicPlayer.getInstance().startDefaultSound());
|
|
138
158
|
}
|
|
139
159
|
}
|
|
140
160
|
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
if (!
|
|
144
|
-
|
|
145
|
-
|
|
161
|
+
if (store.pacman.powerupRemainingDuration) {
|
|
162
|
+
store.pacman.powerupRemainingDuration--;
|
|
163
|
+
if (!store.pacman.powerupRemainingDuration) {
|
|
164
|
+
store.ghosts.forEach((ghost) => (ghost.scared = false));
|
|
165
|
+
store.pacman.points = 0;
|
|
146
166
|
}
|
|
147
167
|
}
|
|
148
168
|
|
|
149
|
-
const remainingCells =
|
|
169
|
+
const remainingCells = store.grid.some((row) => row.some((cell) => cell.intensity > 0));
|
|
150
170
|
if (!remainingCells) {
|
|
151
|
-
if (
|
|
152
|
-
clearInterval(
|
|
153
|
-
if (
|
|
154
|
-
Canvas.renderGameOver();
|
|
171
|
+
if (store.config.outputFormat == 'canvas') {
|
|
172
|
+
clearInterval(store.gameInterval);
|
|
173
|
+
if (store.config.outputFormat == 'canvas') {
|
|
174
|
+
Canvas.renderGameOver(store);
|
|
155
175
|
MusicPlayer.getInstance()
|
|
156
176
|
.play(Sound.BEGINNING)
|
|
157
177
|
.then(() => MusicPlayer.getInstance().stopDefaultSound());
|
|
158
178
|
}
|
|
159
179
|
}
|
|
160
180
|
|
|
161
|
-
if (
|
|
162
|
-
const animatedSVG = SVG.generateAnimatedSVG();
|
|
181
|
+
if (store.config.outputFormat == 'svg') {
|
|
182
|
+
const animatedSVG = SVG.generateAnimatedSVG(store);
|
|
163
183
|
const svgBlob = new Blob([animatedSVG], {
|
|
164
184
|
type: 'image/svg+xml;charset=utf-8'
|
|
165
185
|
});
|
|
166
186
|
const svgUrl = URL.createObjectURL(svgBlob);
|
|
167
|
-
|
|
187
|
+
store.config.svgCallback(svgUrl);
|
|
168
188
|
}
|
|
169
189
|
|
|
170
|
-
|
|
190
|
+
store.config.gameOverCallback();
|
|
171
191
|
return;
|
|
172
192
|
}
|
|
173
193
|
|
|
174
|
-
movePacman();
|
|
175
|
-
moveGhosts();
|
|
176
|
-
checkCollisions();
|
|
194
|
+
movePacman(store);
|
|
195
|
+
moveGhosts(store);
|
|
196
|
+
checkCollisions(store);
|
|
177
197
|
|
|
178
|
-
|
|
198
|
+
store.pacmanMouthOpen = !store.pacmanMouthOpen;
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
pacman: { ...
|
|
182
|
-
ghosts:
|
|
183
|
-
grid:
|
|
200
|
+
store.gameHistory.push({
|
|
201
|
+
pacman: { ...store.pacman },
|
|
202
|
+
ghosts: store.ghosts.map((ghost) => ({ ...ghost })),
|
|
203
|
+
grid: store.grid.map((row) => [...row.map((col) => col.intensity)])
|
|
184
204
|
});
|
|
185
205
|
|
|
186
|
-
if (
|
|
187
|
-
if (
|
|
188
|
-
if (
|
|
189
|
-
if (
|
|
206
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawGrid(store);
|
|
207
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawPacman(store);
|
|
208
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawGhosts(store);
|
|
209
|
+
if (store.config.outputFormat == 'canvas') Canvas.drawSoundController(store);
|
|
190
210
|
};
|
|
191
211
|
|
|
192
|
-
const movePacman = () => {
|
|
193
|
-
if (
|
|
212
|
+
const movePacman = (store: StoreType) => {
|
|
213
|
+
if (store.pacman.deadRemainingDuration) {
|
|
194
214
|
return;
|
|
195
215
|
}
|
|
196
216
|
let targetCells: { x: number; y: number; distance: number }[] = [];
|
|
197
217
|
|
|
198
|
-
if (
|
|
199
|
-
targetCells =
|
|
218
|
+
if (store.pacman.powerupRemainingDuration) {
|
|
219
|
+
targetCells = store.ghosts.map((ghost) => ({
|
|
200
220
|
x: ghost.x,
|
|
201
221
|
y: ghost.y,
|
|
202
222
|
distance: Infinity
|
|
@@ -204,7 +224,7 @@ const movePacman = () => {
|
|
|
204
224
|
} else {
|
|
205
225
|
for (let x = 0; x < GRID_HEIGHT; x++) {
|
|
206
226
|
for (let y = 0; y < GRID_WIDTH; y++) {
|
|
207
|
-
if (
|
|
227
|
+
if (store.grid[x][y].intensity > 0) targetCells.push({ x, y, distance: Infinity });
|
|
208
228
|
}
|
|
209
229
|
}
|
|
210
230
|
}
|
|
@@ -213,33 +233,35 @@ const movePacman = () => {
|
|
|
213
233
|
|
|
214
234
|
const closest = targetCells.reduce(
|
|
215
235
|
(closest, cell) => {
|
|
216
|
-
const distance = Math.abs(cell.x -
|
|
236
|
+
const distance = Math.abs(cell.x - store.pacman.x) + Math.abs(cell.y - store.pacman.y);
|
|
217
237
|
return distance < closest.distance ? { ...cell, distance } : closest;
|
|
218
238
|
},
|
|
219
|
-
{ x:
|
|
239
|
+
{ x: store.pacman.x, y: store.pacman.y, distance: Infinity }
|
|
220
240
|
);
|
|
221
241
|
|
|
222
|
-
const dx = closest.x -
|
|
223
|
-
const dy = closest.y -
|
|
242
|
+
const dx = closest.x - store.pacman.x;
|
|
243
|
+
const dy = closest.y - store.pacman.y;
|
|
224
244
|
|
|
225
245
|
if (Math.abs(dx) > Math.abs(dy)) {
|
|
226
|
-
|
|
227
|
-
|
|
246
|
+
store.pacman.x += Math.sign(dx);
|
|
247
|
+
store.pacman.direction = dx > 0 ? 'down' : 'up';
|
|
228
248
|
} else {
|
|
229
|
-
|
|
230
|
-
|
|
249
|
+
store.pacman.y += Math.sign(dy);
|
|
250
|
+
store.pacman.direction = dy > 0 ? 'right' : 'left';
|
|
231
251
|
}
|
|
232
252
|
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
|
|
253
|
+
if (store.grid[store.pacman.x][store.pacman.y].intensity > 0) {
|
|
254
|
+
store.pacman.totalPoints += store.grid[store.pacman.x][store.pacman.y].commitsCount;
|
|
255
|
+
store.pacman.points++;
|
|
256
|
+
store.config.pointsIncreasedCallback(store.pacman.totalPoints);
|
|
257
|
+
store.grid[store.pacman.x][store.pacman.y].intensity = 0;
|
|
236
258
|
|
|
237
|
-
if (
|
|
259
|
+
if (store.pacman.points >= 30) activatePowerUp(store);
|
|
238
260
|
}
|
|
239
261
|
};
|
|
240
262
|
|
|
241
|
-
const moveGhosts = () => {
|
|
242
|
-
|
|
263
|
+
const moveGhosts = (store: StoreType) => {
|
|
264
|
+
store.ghosts.forEach((ghost, index) => {
|
|
243
265
|
if (ghost.scared) {
|
|
244
266
|
if (!ghost.target) {
|
|
245
267
|
ghost.target = getRandomDestination(ghost.x, ghost.y);
|
|
@@ -271,7 +293,7 @@ const moveGhosts = () => {
|
|
|
271
293
|
const [dx, dy] = directions[Math.floor(Math.random() * directions.length)];
|
|
272
294
|
|
|
273
295
|
// If Pacman has the power-up, ghosts move slower (move every other frame)
|
|
274
|
-
if (
|
|
296
|
+
if (store.pacman.powerupRemainingDuration && Math.random() < 0.5) return;
|
|
275
297
|
|
|
276
298
|
const newX = ghost.x + dx;
|
|
277
299
|
const newY = ghost.y + dy;
|
|
@@ -294,22 +316,22 @@ const getRandomDestination = (x: number, y: number) => {
|
|
|
294
316
|
};
|
|
295
317
|
};
|
|
296
318
|
|
|
297
|
-
const checkCollisions = () => {
|
|
298
|
-
if (
|
|
319
|
+
const checkCollisions = (store: StoreType) => {
|
|
320
|
+
if (store.pacman.deadRemainingDuration) return;
|
|
299
321
|
|
|
300
|
-
|
|
301
|
-
if (ghost.x ===
|
|
302
|
-
if (
|
|
303
|
-
respawnGhost(index);
|
|
304
|
-
|
|
305
|
-
if (
|
|
322
|
+
store.ghosts.forEach((ghost, index) => {
|
|
323
|
+
if (ghost.x === store.pacman.x && ghost.y === store.pacman.y) {
|
|
324
|
+
if (store.pacman.powerupRemainingDuration && ghost.scared) {
|
|
325
|
+
respawnGhost(store, index);
|
|
326
|
+
store.pacman.points += 10;
|
|
327
|
+
if (store.config.outputFormat == 'canvas') {
|
|
306
328
|
MusicPlayer.getInstance().play(Sound.EAT_GHOST);
|
|
307
329
|
}
|
|
308
330
|
} else {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if (
|
|
331
|
+
store.pacman.points = 0;
|
|
332
|
+
store.pacman.powerupRemainingDuration = 0;
|
|
333
|
+
store.pacman.deadRemainingDuration = PACMAN_DEATH_DURATION;
|
|
334
|
+
if (store.config.outputFormat == 'canvas') {
|
|
313
335
|
MusicPlayer.getInstance()
|
|
314
336
|
.play(Sound.GAME_OVER)
|
|
315
337
|
.then(() => MusicPlayer.getInstance().stopDefaultSound());
|
|
@@ -319,26 +341,27 @@ const checkCollisions = () => {
|
|
|
319
341
|
});
|
|
320
342
|
};
|
|
321
343
|
|
|
322
|
-
const respawnGhost = (ghostIndex: number) => {
|
|
344
|
+
const respawnGhost = (store: StoreType, ghostIndex: number) => {
|
|
323
345
|
let x, y;
|
|
324
346
|
do {
|
|
325
347
|
x = Math.floor(Math.random() * GRID_HEIGHT);
|
|
326
348
|
y = Math.floor(Math.random() * GRID_WIDTH);
|
|
327
|
-
} while ((Math.abs(x -
|
|
328
|
-
|
|
349
|
+
} while ((Math.abs(x - store.pacman.x) <= 2 && Math.abs(y - store.pacman.y) <= 2) || store.grid[x][y].intensity === 0);
|
|
350
|
+
store.ghosts[ghostIndex] = {
|
|
329
351
|
x,
|
|
330
352
|
y,
|
|
331
|
-
|
|
353
|
+
name: GHOST_NAMES[ghostIndex % GHOST_NAMES.length],
|
|
332
354
|
scared: false,
|
|
333
355
|
target: undefined
|
|
334
356
|
};
|
|
335
357
|
};
|
|
336
358
|
|
|
337
|
-
const activatePowerUp = () => {
|
|
338
|
-
|
|
339
|
-
|
|
359
|
+
const activatePowerUp = (store: StoreType) => {
|
|
360
|
+
store.pacman.powerupRemainingDuration = PACMAN_POWERUP_DURATION;
|
|
361
|
+
store.ghosts.forEach((ghost) => (ghost.scared = true));
|
|
340
362
|
};
|
|
341
363
|
|
|
342
364
|
export const Game = {
|
|
343
|
-
startGame
|
|
365
|
+
startGame,
|
|
366
|
+
stopGame
|
|
344
367
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
import { Game } from './game';
|
|
2
2
|
import { Store } from './store';
|
|
3
|
-
import { Config } from './types';
|
|
3
|
+
import { Config, StoreType } from './types';
|
|
4
4
|
import { Utils } from './utils';
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
username: '',
|
|
10
|
-
canvas: undefined as unknown as HTMLCanvasElement,
|
|
11
|
-
outputFormat: 'svg',
|
|
12
|
-
svgCallback: (_: string) => {},
|
|
13
|
-
gameOverCallback: () => () => {},
|
|
14
|
-
gameTheme: 'github',
|
|
15
|
-
gameSpeed: 1,
|
|
16
|
-
enableSounds: true
|
|
17
|
-
};
|
|
18
|
-
Store.config = { ...defaultConfing, ...conf };
|
|
6
|
+
export class PacmanRenderer {
|
|
7
|
+
store: StoreType;
|
|
8
|
+
conf: Config;
|
|
19
9
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
constructor(conf: Config) {
|
|
11
|
+
this.store = { ...Store };
|
|
12
|
+
this.conf = { ...conf };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async start() {
|
|
16
|
+
const defaultConfing: Config = {
|
|
17
|
+
platform: 'github',
|
|
18
|
+
username: '',
|
|
19
|
+
canvas: undefined as unknown as HTMLCanvasElement,
|
|
20
|
+
outputFormat: 'svg',
|
|
21
|
+
svgCallback: (_: string) => {},
|
|
22
|
+
gameOverCallback: () => () => {},
|
|
23
|
+
gameTheme: 'github',
|
|
24
|
+
gameSpeed: 1,
|
|
25
|
+
enableSounds: true,
|
|
26
|
+
pointsIncreasedCallback: (_: number) => {}
|
|
27
|
+
};
|
|
28
|
+
this.store.config = { ...defaultConfing, ...this.conf };
|
|
29
|
+
|
|
30
|
+
switch (this.conf.platform) {
|
|
31
|
+
case 'gitlab':
|
|
32
|
+
this.store.contributions = await Utils.getGitlabContribution(this.conf.username);
|
|
33
|
+
break;
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
case 'github':
|
|
36
|
+
this.store.contributions = await Utils.getGithubContribution(this.conf.username);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Game.startGame(this.store);
|
|
28
41
|
}
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
public stop() {
|
|
44
|
+
Game.stopGame(this.store);
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/music-player.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export enum Sound {
|
|
2
|
-
DEFAULT = '/src/assets/sounds/pacman_chomp.wav',
|
|
3
|
-
BEGINNING = '/src/assets/sounds/pacman_beginning.wav',
|
|
4
|
-
GAME_OVER = '/src/assets/sounds/pacman_death.wav',
|
|
5
|
-
EAT_GHOST = '/src/assets/sounds/pacman_eatghost.wav'
|
|
2
|
+
DEFAULT = 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.2/src/assets/sounds/pacman_chomp.wav',
|
|
3
|
+
BEGINNING = 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.2/src/assets/sounds/pacman_beginning.wav',
|
|
4
|
+
GAME_OVER = 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.2/src/assets/sounds/pacman_death.wav',
|
|
5
|
+
EAT_GHOST = 'https://cdn.jsdelivr.net/gh/abozanona/pacman-contribution-graph@1.0.2/src/assets/sounds/pacman_eatghost.wav'
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class MusicPlayer {
|
|
@@ -38,7 +38,9 @@ export class MusicPlayer {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
if (this.currentSource) {
|
|
41
|
-
|
|
41
|
+
try {
|
|
42
|
+
this.currentSource.stop();
|
|
43
|
+
} catch (ex) {}
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
const buffer = this.sounds.get(sound);
|
|
@@ -65,7 +67,9 @@ export class MusicPlayer {
|
|
|
65
67
|
|
|
66
68
|
public startDefaultSound(): void {
|
|
67
69
|
if (this.defaultSource) {
|
|
68
|
-
|
|
70
|
+
try {
|
|
71
|
+
this.defaultSource.stop();
|
|
72
|
+
} catch (ex) {}
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
const buffer = this.sounds.get(Sound.DEFAULT);
|
|
@@ -86,7 +90,9 @@ export class MusicPlayer {
|
|
|
86
90
|
|
|
87
91
|
public stopDefaultSound(): void {
|
|
88
92
|
if (this.defaultSource) {
|
|
89
|
-
|
|
93
|
+
try {
|
|
94
|
+
this.defaultSource.stop();
|
|
95
|
+
} catch (ex) {}
|
|
90
96
|
this.defaultSource = null;
|
|
91
97
|
}
|
|
92
98
|
}
|
package/src/store.ts
CHANGED