@@ -8,6 +8,28 @@ const routes = {
88 "/piano" : "pages/piano.html" ,
99} ;
1010
11+ // Create a PCG random number generator
12+ function createPcgRandom ( seed = 1 ) {
13+ let state = BigInt ( seed ) ;
14+ const multiplier = 6364136223846793005n ;
15+ const increment = 1442695040888963407n ;
16+ const mod = 2n ** 64n ;
17+ const mod32 = 2 ** 32 ;
18+
19+ return function ( ) {
20+ const oldState = state ;
21+ state = ( oldState * multiplier + increment ) % mod ;
22+
23+ const xorshifted = Number ( ( ( oldState >> 18n ) ^ oldState ) >> 27n ) ;
24+ const rot = Number ( oldState >> 59n ) ;
25+ const result = ( xorshifted >>> rot ) | ( xorshifted << ( - rot & 31 ) ) ;
26+
27+ return ( result >>> 0 ) / mod32 ;
28+ } ;
29+ }
30+
31+ const pcg = createPcgRandom ( Date . now ( ) ) ;
32+
1133const app = document . getElementById ( "app" ) ;
1234let currentPage = null ; // To track the current page animation
1335
@@ -167,13 +189,13 @@ const matrixEffect = (canvasId, containerSelector) => {
167189 "lulz" ,
168190 "pwn" ,
169191 ] ;
192+ const matrixLength = matrix . length ;
193+ const sparkleTextLength = sparkleText . length ;
170194
171- const vec2 = ( x , y ) => ( { x, y } ) ;
172195 const font_size = 10 ;
173-
174- const circle_buffer_width = canvas . width / font_size ;
175- const circle_buffer_height = canvas . height / font_size ;
176- const columns = canvas . width / font_size ;
196+ const circle_buffer_width = ( canvas . width / font_size ) | 0 ;
197+ const circle_buffer_height = ( canvas . height / font_size ) | 0 ;
198+ const columns = circle_buffer_width ;
177199 const drops = [ ] ;
178200 const particles = [ ] ;
179201 const lines = [ ] ;
@@ -187,28 +209,28 @@ const matrixEffect = (canvasId, containerSelector) => {
187209 drops [ x ] = 1 ;
188210 }
189211 for ( let i = 0 ; i < drops . length ; i ++ ) {
190- drops [ i ] = canvas . height / font_size ;
212+ drops [ i ] = circle_buffer_height ;
191213 }
192214 for ( let i = 0 ; i < maxParticles ; i ++ ) {
193215 particles . push ( {
194- x : Math . random ( ) * canvas . width ,
195- y : Math . random ( ) * canvas . height ,
196- radius : Math . random ( ) * 170 + 25 ,
197- speed : Math . random ( ) * 6 ,
198- dir : vec2 ( Math . random ( ) - 0.5 , Math . random ( ) - 0.5 ) ,
216+ x : pcg ( ) * canvas . width ,
217+ y : pcg ( ) * canvas . height ,
218+ radius : pcg ( ) * 170 + 25 ,
219+ speed : pcg ( ) * 6 ,
220+ dir : { x : pcg ( ) - 0.5 , y : pcg ( ) - 0.5 } ,
199221 } ) ;
200222 }
201223
202224 function plotPixel ( x , y , v ) {
203- const sx = Math . floor ( x ) | 0 ;
204- const sy = Math . floor ( y ) | 0 ;
205- const index = ( sy * circle_buffer_width + sx ) | 0 ;
225+ const sx = x | 0 ;
226+ const sy = y | 0 ;
206227 if (
207228 sx >= 0 &&
208229 sx < circle_buffer_width &&
209230 sy >= 0 &&
210231 sy < circle_buffer_height
211232 ) {
233+ const index = ( sy * circle_buffer_width + sx ) | 0 ;
212234 circle_buffer [ index ] = v ;
213235 }
214236 }
@@ -225,92 +247,103 @@ const matrixEffect = (canvasId, containerSelector) => {
225247 }
226248
227249 function bresenhamCircle ( centerX , centerY , radius ) {
228- centerX /= font_size ;
229- centerY /= font_size ;
230- radius /= font_size ;
231- centerX = Math . floor ( centerX ) | 0 ;
232- centerY = Math . floor ( centerY ) | 0 ;
233- radius = Math . floor ( radius ) | 0 ;
250+ const cx = ( centerX / font_size ) | 0 ;
251+ const cy = ( centerY / font_size ) | 0 ;
252+ const r = ( radius / font_size ) | 0 ;
253+
234254 let x = 0 | 0 ;
235- let y = radius | 0 ;
236- let d = ( 3 - 2 * radius ) | 0 ;
237- while ( y > x ) {
255+ let y = r | 0 ;
256+ let d = ( 3 - 2 * r ) | 0 ;
257+ while ( y >= x ) {
258+ plotOctants ( x , y , cx , cy ) ;
238259 x ++ ;
239260 if ( d > 0 ) {
240261 y -- ;
241- d = ( d + 4 * ( x - y ) ) | 0 ;
262+ d = d + 4 * ( x - y ) ; // + 10 ;
242263 } else {
243- d = ( d + 4 * x ) | 0 ;
264+ d = d + 4 * x ; // + 6 ;
244265 }
245- plotOctants ( x , y , centerX , centerY ) ;
246266 }
247267 }
248268 const epsilon = 0.01 ;
249269
250270 function line ( x0 , y0 , x1 , y1 ) {
251- x0 /= font_size ;
252- y0 /= font_size ;
253- x1 /= font_size ;
254- y1 /= font_size ;
255- x0 = Math . floor ( x0 ) | 0 ;
256- y0 = Math . floor ( y0 ) | 0 ;
257- x1 = Math . floor ( x1 ) | 0 ;
258- y1 = Math . floor ( y1 ) | 0 ;
259- const dx = Math . abs ( x1 - x0 ) ;
260- const dy = Math . abs ( y1 - y0 ) ;
261- const sx = Math . sign ( x1 - x0 ) ;
262- const sy = Math . sign ( y1 - y0 ) ;
271+ let cx0 = ( x0 / font_size ) | 0 ;
272+ let cy0 = ( y0 / font_size ) | 0 ;
273+ const cx1 = ( x1 / font_size ) | 0 ;
274+ const cy1 = ( y1 / font_size ) | 0 ;
275+
276+ const dx = Math . abs ( cx1 - cx0 ) ;
277+ const dy = Math . abs ( cy1 - cy0 ) ;
278+ const sx = Math . sign ( cx1 - cx0 ) ;
279+ const sy = Math . sign ( cy1 - cy0 ) ;
263280 let err = dx - dy ;
264281
265282 while ( true ) {
266- plotPixel ( x0 , y0 , 2 ) ;
283+ plotPixel ( cx0 , cy0 , 2 ) ;
267284
268- if ( Math . abs ( x0 - x1 ) + Math . abs ( y0 - y1 ) < epsilon ) break ;
285+ if ( Math . abs ( cx0 - cx1 ) < epsilon && Math . abs ( cy0 - cy1 ) < epsilon ) break ;
269286
270287 const e2 = 2 * err ;
271288 if ( e2 > - dy ) {
272289 err -= dy ;
273- x0 += sx ;
290+ cx0 += sx ;
274291 }
275292 if ( e2 < dx ) {
276293 err += dx ;
277- y0 += sy ;
294+ cy0 += sy ;
278295 }
279296 }
280297 }
281298
282299 function drawCicleBuffer ( ) {
300+ const blackFill = "rgba(0, 0, 0, 1)" ;
301+ const redFill = "rgba(122, 5, 5, 1)" ;
302+ const greenFill = "rgba(6, 46, 6, 1)" ;
303+ let currentFill = "" ;
304+
283305 for ( let y = 0 ; y < circle_buffer_height ; y ++ ) {
284306 for ( let x = 0 ; x < circle_buffer_width ; x ++ ) {
285307 const index = ( y * circle_buffer_width + x ) | 0 ;
286- const xx = ( x * font_size ) | 0 ;
287- const yy = ( y * font_size ) | 0 ;
288- if ( circle_buffer [ index ] > 0 ) {
289- ctx . fillStyle = "rgba(0, 0, 0, 1)" ;
308+ const value = circle_buffer [ index ] ;
309+
310+ if ( value > 0 ) {
311+ const xx = ( x * font_size ) | 0 ;
312+ const yy = ( y * font_size ) | 0 ;
313+
314+ if ( currentFill !== blackFill ) {
315+ ctx . fillStyle = blackFill ;
316+ currentFill = blackFill ;
317+ }
290318 ctx . fillRect ( xx , yy , font_size , font_size ) ;
291- if ( circle_buffer [ index ] === 2 ) {
292- ctx . fillStyle = "rgba(122, 5, 5, 1)" ;
319+
320+ if ( value === 2 ) {
321+ if ( currentFill !== redFill ) {
322+ ctx . fillStyle = redFill ;
323+ currentFill = redFill ;
324+ }
293325 } else {
294- ctx . fillStyle = "rgba(6, 46, 6, 1)" ;
326+ if ( currentFill !== greenFill ) {
327+ ctx . fillStyle = greenFill ;
328+ currentFill = greenFill ;
329+ }
295330 }
296331
297- const text = matrix [ Math . floor ( Math . random ( ) * matrix . length ) ] ;
332+ const text = matrix [ ( pcg ( ) * matrixLength ) | 0 ] ;
298333 ctx . fillText ( text , xx , yy + font_size ) ;
299334 }
300335 }
301336 }
302337 }
303338
304339 function rndInt ( min , max ) {
305- return Math . floor ( Math . random ( ) * ( max - min + 1 ) ) + min ;
340+ return ( ( pcg ( ) * ( max - min + 1 ) ) | 0 ) + min ;
306341 }
307342
308343 function draw ( deltaTime ) {
309344 ctx . fillStyle = "rgba(0, 0, 0, 0.05)" ;
310345 ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
311346
312- // Set the fill color to green
313- ctx . fillStyle = "green" ;
314347 ctx . font = font_size + "px arial" ;
315348
316349 circle_buffer . fill ( 0 ) ;
@@ -322,17 +355,19 @@ const matrixEffect = (canvasId, containerSelector) => {
322355 if ( p . x < 0 || p . x > canvas . width ) p . dir . x *= - 1 ;
323356 if ( p . y < 0 || p . y > canvas . height ) p . dir . y *= - 1 ;
324357 bresenhamCircle ( p . x , p . y , p . radius ) ;
325- if ( Math . random ( ) < 0.01 ) {
326- p . dir = vec2 ( Math . random ( ) - 0.5 , Math . random ( ) - 0.5 ) ;
327- p . radius = Math . random ( ) * 100 + 25 ;
358+
359+ if ( pcg ( ) < 0.01 ) {
360+ p . dir . x = pcg ( ) - 0.5 ;
361+ p . dir . y = pcg ( ) - 0.5 ;
362+ p . radius = pcg ( ) * 100 + 25 ;
328363 }
329364 if ( rndInt ( 0 , 1000 ) < 5 ) {
330- p . radius += Math . random ( ) * 50 - 25 ;
365+ p . radius += pcg ( ) * 50 - 25 ;
331366 }
332367
333368 if ( rndInt ( 0 , 1000 ) < 10 ) {
334- ctx . fillStyle = "rgba(140, 213, 239 , 0.75)" ;
335- ctx . fillText ( sparkleText [ rndInt ( 0 , sparkleText . length - 1 ) ] , p . x , p . y ) ;
369+ ctx . fillStyle = "rgba(129, 199, 225 , 0.75)" ;
370+ ctx . fillText ( sparkleText [ rndInt ( 0 , sparkleTextLength - 1 ) ] , p . x , p . y ) ;
336371 }
337372 }
338373
@@ -359,38 +394,46 @@ const matrixEffect = (canvasId, containerSelector) => {
359394
360395 drawCicleBuffer ( ) ;
361396 for ( let i = 0 ; i < drops . length ; i ++ ) {
362- const text = matrix [ Math . floor ( Math . random ( ) * matrix . length ) ] ;
397+ const text = matrix [ ( pcg ( ) * matrixLength ) | 0 ] ;
363398
364399 const tx = i * font_size ;
365400 const ty = drops [ i ] * font_size ;
366401
367402 ctx . fillText ( text , tx , ty ) ;
368403
369- const cx = tx / font_size ;
370- const cy = ty / font_size ;
371- const index = ( cy * circle_buffer_width + cx ) | 0 ;
372- if ( circle_buffer [ index ] === 1 ) {
373- ctx . fillStyle = "rgba(18, 215, 202, 1)" ;
374- ctx . fillText ( sparkleText [ rndInt ( 0 , sparkleText . length - 1 ) ] , tx , ty ) ;
375- ctx . fillText (
376- sparkleText [ rndInt ( 0 , sparkleText . length - 1 ) ] ,
377- tx + font_size ,
378- ty + font_size
379- ) ;
380- ctx . fillText (
381- sparkleText [ rndInt ( 0 , sparkleText . length - 1 ) ] ,
382- tx - font_size ,
383- ty + font_size
384- ) ;
385- }
386- if ( circle_buffer [ index ] === 2 ) {
387- ctx . fillStyle = "rgba(215, 18, 18, 1)" ;
388- ctx . fillText ( "FF" , tx + font_size , ty + font_size ) ;
389- ctx . fillText ( "90" , tx - font_size , ty + font_size ) ;
404+ const cx = ( tx / font_size ) | 0 ;
405+ const cy = ( ty / font_size ) | 0 ;
406+
407+ if (
408+ cx >= 0 &&
409+ cx < circle_buffer_width &&
410+ cy >= 0 &&
411+ cy < circle_buffer_height
412+ ) {
413+ const index = ( cy * circle_buffer_width + cx ) | 0 ;
414+ if ( circle_buffer [ index ] === 1 ) {
415+ ctx . fillStyle = "rgba(18, 215, 202, 1)" ;
416+ ctx . fillText ( sparkleText [ rndInt ( 0 , sparkleTextLength - 1 ) ] , tx , ty ) ;
417+ ctx . fillText (
418+ sparkleText [ rndInt ( 0 , sparkleTextLength - 1 ) ] ,
419+ tx + font_size ,
420+ ty + font_size
421+ ) ;
422+ ctx . fillText (
423+ sparkleText [ rndInt ( 0 , sparkleTextLength - 1 ) ] ,
424+ tx - font_size ,
425+ ty + font_size
426+ ) ;
427+ }
428+ if ( circle_buffer [ index ] === 2 ) {
429+ ctx . fillStyle = "rgba(215, 18, 18, 1)" ;
430+ ctx . fillText ( "FF" , tx + font_size , ty + font_size ) ;
431+ ctx . fillText ( "90" , tx - font_size , ty + font_size ) ;
432+ }
390433 }
391434 ctx . fillStyle = baseCol ;
392435
393- if ( drops [ i ] * font_size > canvas . height && Math . random ( ) > 0.975 ) {
436+ if ( drops [ i ] * font_size > canvas . height && pcg ( ) > 0.975 ) {
394437 drops [ i ] = 0 ;
395438 }
396439 drops [ i ] ++ ;
0 commit comments