pacman-contribution-graph 1.0.14 → 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/README.md +59 -9
- package/dist/pacman-contribution-graph.min.js +1 -1
- package/package.json +44 -26
- package/.prettierrc +0 -8
- package/.vscode/extensions.json +0 -5
- package/.vscode/settings.json +0 -6
- package/assets/packman-demo.png +0 -0
- package/dist/pacman-contribution-graph.js +0 -1776
- package/dist/pacman-contribution-graph.js.map +0 -1
- package/embeded/canvas.html +0 -41
- package/github-action/action.yml +0 -16
- package/github-action/dist/index.js +0 -26901
- package/github-action/package.json +0 -14
- package/github-action/pnpm-lock.yaml +0 -77
- package/github-action/src/index.js +0 -47
- package/index.html +0 -528
- package/pacman.abozanona.me/index.js +0 -47
- package/pacman.abozanona.me/package.json +0 -8
- package/server/api/contributions/route.ts.z +0 -31
- package/server/page.zts.z +0 -13
- 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/assets/sounds/pacman_beginning.wav +0 -0
- package/src/assets/sounds/pacman_chomp.wav +0 -0
- package/src/assets/sounds/pacman_death.wav +0 -0
- package/src/assets/sounds/pacman_eatghost.wav +0 -0
- package/src/canvas.ts +0 -244
- package/src/constants.ts +0 -102
- package/src/game.ts +0 -231
- package/src/grid.ts +0 -127
- package/src/index.ts +0 -48
- package/src/movement/ghosts-movement.ts +0 -183
- package/src/movement/movement-utils.ts +0 -40
- package/src/movement/pacman-movement.ts +0 -230
- package/src/music-player.ts +0 -119
- package/src/store.ts +0 -23
- package/src/svg.ts +0 -254
- package/src/types.ts +0 -78
- package/src/utils.ts +0 -81
- package/tsconfig.json +0 -11
- package/webpack.common.js +0 -19
- package/webpack.dev.js +0 -23
- package/webpack.prod.js +0 -18
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import http from 'http';
|
|
2
|
-
import { PacmanRenderer } from 'pacman-contribution-graph';
|
|
3
|
-
import querystring from 'querystring';
|
|
4
|
-
import url from 'url';
|
|
5
|
-
|
|
6
|
-
const githubToken = process.env.GITHUB_ACCESS_TOKEN;
|
|
7
|
-
|
|
8
|
-
const generateSvg = async (userName) => {
|
|
9
|
-
return new Promise((resolve) => {
|
|
10
|
-
const conf = {
|
|
11
|
-
platform: "github",
|
|
12
|
-
username: userName,
|
|
13
|
-
outputFormat: "svg",
|
|
14
|
-
gameSpeed: 1,
|
|
15
|
-
gameTheme: "github-dark",
|
|
16
|
-
githubSettings: {
|
|
17
|
-
accessToken: githubToken
|
|
18
|
-
},
|
|
19
|
-
svgCallback: (animatedSVG) => resolve(animatedSVG)
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const pr = new PacmanRenderer(conf);
|
|
23
|
-
pr.start();
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const server = http.createServer(async (req, res) => {
|
|
28
|
-
const parsedUrl = url.parse(req.url);
|
|
29
|
-
const queryParams = querystring.parse(parsedUrl.query);
|
|
30
|
-
const username = queryParams.username || 'abozanona';
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const svg = await generateSvg(username);
|
|
34
|
-
res.writeHead(200, {
|
|
35
|
-
'Content-Type': 'image/svg+xml',
|
|
36
|
-
'Cache-Control': 'no-store, no-cache, must-revalidate',
|
|
37
|
-
'Pragma': 'no-cache',
|
|
38
|
-
'Expires': '0'
|
|
39
|
-
});
|
|
40
|
-
res.end(svg.replace("Generated with ", "Generated with " + username + " "));
|
|
41
|
-
} catch (error) {
|
|
42
|
-
res.end('Error generating SVG');
|
|
43
|
-
throw error;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
server.listen();
|
|
@@ -1,31 +0,0 @@
|
|
|
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
|
-
}
|
package/server/page.zts.z
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
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
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/canvas.ts
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CELL_SIZE,
|
|
3
|
-
GAP_SIZE,
|
|
4
|
-
GHOSTS,
|
|
5
|
-
GRID_HEIGHT,
|
|
6
|
-
GRID_WIDTH,
|
|
7
|
-
PACMAN_COLOR,
|
|
8
|
-
PACMAN_COLOR_DEAD,
|
|
9
|
-
PACMAN_COLOR_POWERUP,
|
|
10
|
-
WALLS
|
|
11
|
-
} from './constants';
|
|
12
|
-
import { MusicPlayer } from './music-player';
|
|
13
|
-
import { StoreType } from './types';
|
|
14
|
-
import { Utils } from './utils';
|
|
15
|
-
|
|
16
|
-
const resizeCanvas = (store: StoreType) => {
|
|
17
|
-
const canvasWidth = GRID_WIDTH * (CELL_SIZE + GAP_SIZE);
|
|
18
|
-
const canvasHeight = GRID_HEIGHT * (CELL_SIZE + GAP_SIZE) + 20; // Adding some space for months on top
|
|
19
|
-
|
|
20
|
-
store.config.canvas.width = canvasWidth;
|
|
21
|
-
store.config.canvas.height = canvasHeight;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const drawGrid = (store: StoreType) => {
|
|
25
|
-
const ctx = store.config.canvas.getContext('2d')!;
|
|
26
|
-
ctx.fillStyle = Utils.getCurrentTheme(store).gridBackground;
|
|
27
|
-
ctx.fillRect(0, 0, store.config.canvas.width, store.config.canvas.height);
|
|
28
|
-
|
|
29
|
-
for (let x = 0; x < GRID_WIDTH; x++) {
|
|
30
|
-
for (let y = 0; y < GRID_HEIGHT; y++) {
|
|
31
|
-
const intensity = store.grid[x][y].intensity;
|
|
32
|
-
if (intensity > 0) {
|
|
33
|
-
const adjustedIntensity = intensity < 0.2 ? 0.3 : intensity;
|
|
34
|
-
const color = Utils.hexToRGBA(Utils.getCurrentTheme(store).contributionBoxColor, adjustedIntensity);
|
|
35
|
-
ctx.fillStyle = color;
|
|
36
|
-
} else {
|
|
37
|
-
ctx.fillStyle = Utils.getCurrentTheme(store).emptyContributionBoxColor;
|
|
38
|
-
}
|
|
39
|
-
ctx.beginPath();
|
|
40
|
-
store.config.canvas
|
|
41
|
-
.getContext('2d')!
|
|
42
|
-
.roundRect(x * (CELL_SIZE + GAP_SIZE), y * (CELL_SIZE + GAP_SIZE) + 15, CELL_SIZE, CELL_SIZE, 5);
|
|
43
|
-
ctx.fill();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
ctx.fillStyle = Utils.getCurrentTheme(store).wallColor;
|
|
48
|
-
for (let x = 0; x <= GRID_WIDTH; x++) {
|
|
49
|
-
for (let y = 0; y <= GRID_HEIGHT; y++) {
|
|
50
|
-
// Draw horizontal walls
|
|
51
|
-
if (WALLS.horizontal[x][y].active) {
|
|
52
|
-
ctx.fillRect(
|
|
53
|
-
x * (CELL_SIZE + GAP_SIZE) - GAP_SIZE,
|
|
54
|
-
y * (CELL_SIZE + GAP_SIZE) - GAP_SIZE + 15,
|
|
55
|
-
CELL_SIZE + GAP_SIZE,
|
|
56
|
-
GAP_SIZE
|
|
57
|
-
);
|
|
58
|
-
// // TODO: For debug only
|
|
59
|
-
// ctx.fillStyle = '#000';
|
|
60
|
-
// ctx.fillText(WALLS.horizontal[x][y].id, x * (GAP_SIZE + CELL_SIZE), y * (GAP_SIZE + CELL_SIZE));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Draw vertical walls
|
|
64
|
-
if (WALLS.vertical[x][y].active) {
|
|
65
|
-
ctx.fillRect(
|
|
66
|
-
x * (CELL_SIZE + GAP_SIZE) - GAP_SIZE,
|
|
67
|
-
y * (CELL_SIZE + GAP_SIZE) - GAP_SIZE + 15,
|
|
68
|
-
GAP_SIZE,
|
|
69
|
-
CELL_SIZE + GAP_SIZE
|
|
70
|
-
);
|
|
71
|
-
// // TODO: For debug only
|
|
72
|
-
// ctx.fillStyle = '#000';
|
|
73
|
-
// ctx.fillText(WALLS.vertical[x][y].id, x * (GAP_SIZE + CELL_SIZE), (y + 1) * (GAP_SIZE + CELL_SIZE));
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
ctx.fillStyle = Utils.getCurrentTheme(store).textColor;
|
|
79
|
-
ctx.font = '10px Arial';
|
|
80
|
-
ctx.textAlign = 'center';
|
|
81
|
-
|
|
82
|
-
let lastMonth = '';
|
|
83
|
-
|
|
84
|
-
for (let x = 0; x < GRID_WIDTH; x++) {
|
|
85
|
-
if (store.monthLabels[x] !== lastMonth) {
|
|
86
|
-
const xPos = x * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
|
|
87
|
-
ctx.fillText(store.monthLabels[x], xPos, 10);
|
|
88
|
-
lastMonth = store.monthLabels[x];
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const drawPacman = (store: StoreType) => {
|
|
94
|
-
const ctx = store.config.canvas.getContext('2d')!;
|
|
95
|
-
const x = store.pacman.x * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2;
|
|
96
|
-
const y = store.pacman.y * (CELL_SIZE + GAP_SIZE) + CELL_SIZE / 2 + 15;
|
|
97
|
-
const radius = CELL_SIZE / 2;
|
|
98
|
-
|
|
99
|
-
// Change Pac-Man's color to red if he's on power-up, dead, else yellow
|
|
100
|
-
if (store.pacman.deadRemainingDuration) {
|
|
101
|
-
ctx.fillStyle = PACMAN_COLOR_DEAD;
|
|
102
|
-
} else if (store.pacman.powerupRemainingDuration) {
|
|
103
|
-
ctx.fillStyle = PACMAN_COLOR_POWERUP;
|
|
104
|
-
} else {
|
|
105
|
-
ctx.fillStyle = PACMAN_COLOR;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const mouthAngle = store.pacmanMouthOpen ? 0.35 * Math.PI : 0.1 * Math.PI;
|
|
109
|
-
|
|
110
|
-
let startAngle, endAngle;
|
|
111
|
-
switch (store.pacman.direction) {
|
|
112
|
-
case 'up':
|
|
113
|
-
startAngle = 1.5 * Math.PI + mouthAngle;
|
|
114
|
-
endAngle = 1.5 * Math.PI - mouthAngle;
|
|
115
|
-
break;
|
|
116
|
-
case 'down':
|
|
117
|
-
startAngle = 0.5 * Math.PI + mouthAngle;
|
|
118
|
-
endAngle = 0.5 * Math.PI - mouthAngle;
|
|
119
|
-
break;
|
|
120
|
-
case 'left':
|
|
121
|
-
startAngle = Math.PI + mouthAngle;
|
|
122
|
-
endAngle = Math.PI - mouthAngle;
|
|
123
|
-
break;
|
|
124
|
-
case 'right':
|
|
125
|
-
default:
|
|
126
|
-
startAngle = 0 + mouthAngle;
|
|
127
|
-
endAngle = 2 * Math.PI - mouthAngle;
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
ctx.beginPath();
|
|
132
|
-
ctx.arc(x, y, radius, startAngle, endAngle);
|
|
133
|
-
ctx.lineTo(x, y);
|
|
134
|
-
ctx.fill();
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const preloadedImages: { [key: string]: HTMLImageElement } = {};
|
|
138
|
-
const getLoadedImage = (key: string, imgDate: string): HTMLImageElement => {
|
|
139
|
-
if (!preloadedImages[key]) {
|
|
140
|
-
const image = new Image();
|
|
141
|
-
image.src = imgDate;
|
|
142
|
-
preloadedImages[key] = image;
|
|
143
|
-
}
|
|
144
|
-
return preloadedImages[key];
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const drawGhosts = (store: StoreType) => {
|
|
148
|
-
store.ghosts.forEach((ghost) => {
|
|
149
|
-
const x = ghost.x * (CELL_SIZE + GAP_SIZE);
|
|
150
|
-
const y = ghost.y * (CELL_SIZE + GAP_SIZE) + 15;
|
|
151
|
-
const size = CELL_SIZE;
|
|
152
|
-
|
|
153
|
-
const ctx = store.config.canvas.getContext('2d')!;
|
|
154
|
-
if (ghost.scared) {
|
|
155
|
-
ctx.drawImage(getLoadedImage('scared', GHOSTS['scared'].imgDate), x, y, size, size);
|
|
156
|
-
} else {
|
|
157
|
-
ctx.drawImage(getLoadedImage(ghost.name, GHOSTS[ghost.name].imgDate), x, y, size, size);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const renderGameOver = (store: StoreType) => {
|
|
163
|
-
const ctx = store.config.canvas.getContext('2d')!;
|
|
164
|
-
ctx.fillStyle = Utils.getCurrentTheme(store).textColor;
|
|
165
|
-
ctx.font = '20px Arial';
|
|
166
|
-
ctx.textAlign = 'center';
|
|
167
|
-
ctx.fillText('Game Over', store.config.canvas.width / 2, store.config.canvas.height / 2);
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
const drawSoundController = (store: StoreType) => {
|
|
171
|
-
if (!store.config.enableSounds) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const ctx = store.config.canvas.getContext('2d')!;
|
|
175
|
-
|
|
176
|
-
const width = 30,
|
|
177
|
-
height = 30,
|
|
178
|
-
left = store.config.canvas.width - width - 10,
|
|
179
|
-
top = 10;
|
|
180
|
-
ctx.fillStyle = `rgba(0, 0, 0, ${MusicPlayer.getInstance().isMuted ? 0.3 : 0.5})`;
|
|
181
|
-
ctx.beginPath();
|
|
182
|
-
ctx.moveTo(left + 10, top + 10);
|
|
183
|
-
ctx.lineTo(left + 20, top + 5);
|
|
184
|
-
ctx.lineTo(left + 20, top + 25);
|
|
185
|
-
ctx.lineTo(left + 10, top + 20);
|
|
186
|
-
ctx.closePath();
|
|
187
|
-
ctx.fill();
|
|
188
|
-
|
|
189
|
-
if (!MusicPlayer.getInstance().isMuted) {
|
|
190
|
-
ctx.strokeStyle = `rgba(0, 0, 0, 0.4)`;
|
|
191
|
-
ctx.lineWidth = 2;
|
|
192
|
-
|
|
193
|
-
// First wave
|
|
194
|
-
ctx.beginPath();
|
|
195
|
-
ctx.arc(left + 25, top + 15, 5, 0, Math.PI * 2);
|
|
196
|
-
ctx.stroke();
|
|
197
|
-
|
|
198
|
-
// Second wave
|
|
199
|
-
ctx.beginPath();
|
|
200
|
-
ctx.arc(left + 25, top + 15, 8, 0, Math.PI * 2);
|
|
201
|
-
ctx.stroke();
|
|
202
|
-
} else {
|
|
203
|
-
// Mute line
|
|
204
|
-
ctx.strokeStyle = 'rgba(255, 0, 0, 0.6)';
|
|
205
|
-
ctx.lineWidth = 3;
|
|
206
|
-
ctx.beginPath();
|
|
207
|
-
ctx.moveTo(left + 25, top + 5);
|
|
208
|
-
ctx.lineTo(left + 5, top + 25);
|
|
209
|
-
ctx.stroke();
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const listenToSoundController = (store: StoreType) => {
|
|
214
|
-
if (!store.config.enableSounds) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
store.config.canvas.addEventListener('click', function (event) {
|
|
218
|
-
const rect = store.config.canvas.getBoundingClientRect();
|
|
219
|
-
const x = event.clientX - rect.left,
|
|
220
|
-
y = event.clientY - rect.top;
|
|
221
|
-
const width = 30,
|
|
222
|
-
height = 30,
|
|
223
|
-
left = store.config.canvas.width - width - 10,
|
|
224
|
-
top = 10;
|
|
225
|
-
|
|
226
|
-
if (x >= left && x <= left + this.width && y >= top && y <= top + this.height) {
|
|
227
|
-
if (MusicPlayer.getInstance().isMuted) {
|
|
228
|
-
MusicPlayer.getInstance().unmute();
|
|
229
|
-
} else {
|
|
230
|
-
MusicPlayer.getInstance().mute();
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
export const Canvas = {
|
|
237
|
-
resizeCanvas,
|
|
238
|
-
drawGrid,
|
|
239
|
-
drawPacman,
|
|
240
|
-
drawGhosts,
|
|
241
|
-
renderGameOver,
|
|
242
|
-
drawSoundController,
|
|
243
|
-
listenToSoundController
|
|
244
|
-
};
|
package/src/constants.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { GameTheme, GhostName, ThemeKeys } from './types';
|
|
2
|
-
|
|
3
|
-
export const CELL_SIZE = 20;
|
|
4
|
-
export const GAP_SIZE = 2;
|
|
5
|
-
export const GRID_WIDTH = 52;
|
|
6
|
-
export const GRID_HEIGHT = 7;
|
|
7
|
-
export const PACMAN_COLOR = 'yellow';
|
|
8
|
-
export const PACMAN_COLOR_POWERUP = 'red';
|
|
9
|
-
export const PACMAN_COLOR_DEAD = '#80808064';
|
|
10
|
-
export const GHOST_NAMES: GhostName[] = ['blinky', 'clyde', 'inky', 'pinky'];
|
|
11
|
-
export const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
12
|
-
export const DELTA_TIME = 200;
|
|
13
|
-
export const PACMAN_DEATH_DURATION = 10;
|
|
14
|
-
export const PACMAN_POWERUP_DURATION = 15;
|
|
15
|
-
export const GAME_THEMES: { [key in ThemeKeys]: GameTheme } = {
|
|
16
|
-
github: {
|
|
17
|
-
textColor: '#586069',
|
|
18
|
-
gridBackground: '#ffffff',
|
|
19
|
-
contributionBoxColor: '#9be9a8',
|
|
20
|
-
emptyContributionBoxColor: '#ebedf0',
|
|
21
|
-
wallColor: '#000000'
|
|
22
|
-
},
|
|
23
|
-
'github-dark': {
|
|
24
|
-
textColor: '#8b949e',
|
|
25
|
-
gridBackground: '#0d1117',
|
|
26
|
-
contributionBoxColor: '#26a641',
|
|
27
|
-
emptyContributionBoxColor: '#161b22',
|
|
28
|
-
wallColor: '#FFFFFF'
|
|
29
|
-
},
|
|
30
|
-
gitlab: {
|
|
31
|
-
textColor: '#626167',
|
|
32
|
-
gridBackground: '#ffffff',
|
|
33
|
-
contributionBoxColor: '#7992f5',
|
|
34
|
-
emptyContributionBoxColor: '#ececef',
|
|
35
|
-
wallColor: '#000000'
|
|
36
|
-
},
|
|
37
|
-
'gitlab-dark': {
|
|
38
|
-
textColor: '#999999',
|
|
39
|
-
gridBackground: '#1f1f1f',
|
|
40
|
-
contributionBoxColor: '#2e7db1',
|
|
41
|
-
emptyContributionBoxColor: '#2d2d2d',
|
|
42
|
-
wallColor: '#FFFFFF'
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
export const GHOSTS: { [key in GhostName | 'scared']: { imgDate: string } } = {
|
|
46
|
-
blinky: {
|
|
47
|
-
imgDate:
|
|
48
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfUlEQVQ4T+2TUQ7AIAhDy/0PzQIRAqxmLtnn/DJPWypBAVkKKOMCyOQN7IRElLrcnIrDLNK4wVtxNbkb6Hq+jOcSbim6QVzKEstkw92gxVeFrMpqokix4wA+NvCOnvfArvcEbHoe2G9QmmhDMUc65p3xYC6q3zQPxtdl3NgF5QpL/b/rs3IAAAAASUVORK5CYIIA'
|
|
49
|
-
},
|
|
50
|
-
clyde: {
|
|
51
|
-
imgDate:
|
|
52
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgUlEQVQ4T+2T0Q6AIAhFLx9sH1MfTIPCAeLKrcd8PHqP4JBQLN7BFacNlHkAs+AQcqIueBs2mVWjgtWwl4yCdrd/pHYLLlVEgR2yK0wy4SoI5TcGXU4wM+AEJQfwsUCuXngDOR4rqKbngf0C94gyFHmkbd4rbkxD/pv2jfR1Ky7sBNrzXbHpnBX+AAAAAElFTkSuQmCC'
|
|
53
|
-
},
|
|
54
|
-
inky: {
|
|
55
|
-
imgDate:
|
|
56
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAg0lEQVQ4T+WTWxKAIAhFuQvK/a+jFoT5QAVxypn+6vMEx6sDIO/jk12OAMs1WDVOXV3UBW+bRVbTFMFu8yCZBExH/g26VHCXI0AJpKgdUCUrTlkwxE+FECdzS7HiJemXgvyeO29gE7jD8wDVFX4vSLNtR1q2z+OVlaZxTaXYrq7HbxYBS8VgMVrqzkEAAAAASUVORK5CYIIA'
|
|
57
|
-
},
|
|
58
|
-
pinky: {
|
|
59
|
-
imgDate:
|
|
60
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVQ4T+2T0Q2AIAwF281wC50Qt9DNagoptqVESfyUz4N3vJCCECxaD4o47gt6bsAo2IWUqAnehkUmbYpgNqwlvSCnur+dtnnAuYUVyCGJimTAi8DUzwmwOoGI7hYjDgAfC/jqiTfg47ZBND0P7BeoR+Sh8CMt8x5xYSWkv2nbcF834swuA/9u49Yy5bgAAAAASUVORK5CYIIA'
|
|
61
|
-
},
|
|
62
|
-
scared: {
|
|
63
|
-
imgDate:
|
|
64
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAeUlEQVQ4T82TUQ6AMAhD7UX0/sdyF0GREVmDmTN+bH9r6Bs0A0t2VpFULwDrrfBkZFcA3YC3ZodViAFGzQHyP0B2w2NrB0/1AoDbHwLoQ5/nrw1OBuD5e/crbM9Aiz35njHWzpSB/m3+0r40mV41M8U19WJe3Uw/tQOKt08pUUbBEQAAAABJRU5ErkJgggAA'
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
export const WALLS: {
|
|
68
|
-
horizontal: { active: boolean; id: string }[][];
|
|
69
|
-
vertical: { active: boolean; id: string }[][];
|
|
70
|
-
} = {
|
|
71
|
-
horizontal: Array(GRID_WIDTH + 1)
|
|
72
|
-
.fill(null)
|
|
73
|
-
.map(() => Array(GRID_HEIGHT + 1).fill({ active: false, id: '' })),
|
|
74
|
-
vertical: Array(GRID_WIDTH + 1)
|
|
75
|
-
.fill(null)
|
|
76
|
-
.map(() => Array(GRID_HEIGHT + 1).fill({ active: false, id: '' }))
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export const setWall = (x: number, y: number, direction: 'horizontal' | 'vertical', lineId: string) => {
|
|
80
|
-
if (direction === 'horizontal') {
|
|
81
|
-
if (x >= 0 && x < WALLS.horizontal.length && y >= 0 && y < WALLS.horizontal[0].length) {
|
|
82
|
-
WALLS.horizontal[x][y] = { active: true, id: lineId };
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
if (x >= 0 && x < WALLS.vertical.length && y >= 0 && y < WALLS.vertical[0].length) {
|
|
86
|
-
WALLS.vertical[x][y] = { active: true, id: lineId };
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const hasWall = (x: number, y: number, direction: 'up' | 'down' | 'left' | 'right'): boolean => {
|
|
92
|
-
switch (direction) {
|
|
93
|
-
case 'up':
|
|
94
|
-
return WALLS.horizontal[x][y].active;
|
|
95
|
-
case 'down':
|
|
96
|
-
return WALLS.horizontal[x + 1][y].active;
|
|
97
|
-
case 'left':
|
|
98
|
-
return WALLS.vertical[x][y].active;
|
|
99
|
-
case 'right':
|
|
100
|
-
return WALLS.vertical[x][y + 1].active;
|
|
101
|
-
}
|
|
102
|
-
};
|