33< head >
44 < meta charset ="UTF-8 ">
55 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6- < title > Pixel Swirl Version 1.014 </ title >
6+ < title > Pixel Swirl Version 1.015 </ title >
77 < style >
88 body {
99 font-family : Arial, sans-serif;
6060 pointer-events : none; /* Allow mouse events to pass through */
6161 transform : translate (-50% , -50% ); /* Center the ball on the cursor */
6262 z-index : 999 ; /* Ensure it's above the canvas */
63- display : none; /* Hidden by default */
64- opacity : 0.5 ; /* Make it slightly transparent */
63+ display : none; /* Always hidden now */
64+ opacity : 0.0 ; /* Make it completely transparent */
6565 }
6666
6767 .right-panel {
342342 </ div >
343343 </ div >
344344
345+ <!-- New slider for Gravity Field Strength -->
346+ < div class ="controls-row " id ="gravityFieldStrengthGroup ">
347+ < div class ="control-group ">
348+ < label for ="gravityFieldStrengthSlider "> Gravity Field Strength:</ label >
349+ < div class ="slider-with-value ">
350+ < input type ="range " id ="gravityFieldStrengthSlider " min ="1 " max ="200 " value ="1 " step ="0.1 ">
351+ < span id ="gravityFieldStrengthValue "> 1.0</ span >
352+ </ div >
353+ </ div >
354+ </ div >
355+
345356 < div class ="controls-row ">
346357 < div class ="checkbox-group ">
347358 < input type ="checkbox " id ="unlockFreedomCheckbox ">
366377
367378 < div class ="app-info ">
368379 < h2 > Pixel Swirl</ h2 >
369- < span id ="versionNumber "> Version 1.014 </ span >
380+ < span id ="versionNumber "> Version 1.015 </ span >
370381 < span class ="not-mobile "> (Not for Mobile Use)</ span >
371382 < hr >
372383 < br >
@@ -409,8 +420,10 @@ <h2>Pixel Swirl</h2>
409420 const rightPanel = document . querySelector ( '.right-panel' ) ;
410421 const mainContentContainer = document . querySelector ( '.main-content-container' ) ;
411422 const canvasContainer = document . querySelector ( '.canvas-container' ) ;
412- // Get reference to the new mouse follower ball element
413- const mouseFollowerBall = document . getElementById ( 'mouseFollowerBall' ) ;
423+ const mouseFollowerBall = document . getElementById ( 'mouseFollowerBall' ) ; // Reference to the HTML element for the gravity field visualizer
424+ const gravityFieldStrengthSlider = document . getElementById ( 'gravityFieldStrengthSlider' ) ;
425+ const gravityFieldStrengthValueSpan = document . getElementById ( 'gravityFieldStrengthValue' ) ;
426+ const gravityFieldStrengthGroup = document . getElementById ( 'gravityFieldStrengthGroup' ) ;
414427
415428
416429 const PUZZLE_PIECE_SIZES = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 16 , 32 , 64 , 128 , 256 , 512 ] ;
@@ -428,7 +441,9 @@ <h2>Pixel Swirl</h2>
428441 const DEFAULT_REPEL_MAX = 1 ;
429442 const DEFAULT_FREQUENCY_MIN = 0 ;
430443 const DEFAULT_FREQUENCY_MAX = 10 ;
431- const DEFAULT_PIECE_SIZE_INDEX = PUZZLE_PIECE_SIZES . indexOf ( 64 ) ;
444+ const DEFAULT_PIECE_SIZE_INDEX = PUZZLE_PIECE_SIZES . indexOf ( 16 ) ;
445+ const DEFAULT_GRAVITY_FIELD_STRENGTH_MIN = 1 ;
446+ const DEFAULT_GRAVITY_FIELD_STRENGTH_MAX = 200 ;
432447
433448
434449 // Unlocked ranges for sliders
@@ -442,6 +457,8 @@ <h2>Pixel Swirl</h2>
442457 const UNLOCKED_REPEL_MAX = 5 ;
443458 const UNLOCKED_FREQUENCY_MIN = 0 ;
444459 const UNLOCKED_FREQUENCY_MAX = 10 ;
460+ const UNLOCKED_GRAVITY_FIELD_STRENGTH_MIN = 1 ;
461+ const UNLOCKED_GRAVITY_FIELD_STRENGTH_MAX = 2000 ; // Allow even stronger for "unlocked freedom"
445462
446463
447464 let gl = null ;
@@ -463,8 +480,9 @@ <h2>Pixel Swirl</h2>
463480 let gravityBallEnabled = false ;
464481 let gravityBallX = 0 ; // Will be mouseX
465482 let gravityBallY = 0 ; // Will be mouseY
466- let gravityBallRadius = 0 ; // Calculated dynamically
467- const GRAVITY_FIELD_FORCE = 0.5 ; // Increased force for more noticeable effect
483+ let gravityBallRadius = 0 ; // Calculated dynamically (size of the *effect* area)
484+ const BASE_GRAVITY_FIELD_FORCE = 0.5 ; // Base force
485+ let gravityFieldStrength = 1.0 ; // Multiplier for the base force
468486
469487 // WebGL resources for gravity field visualizer (no longer used for drawing the ball itself)
470488 let gravityBallTexture = null ;
@@ -749,7 +767,7 @@ <h2>Pixel Swirl</h2>
749767 // Update gravity ball radius if enabled
750768 if ( gravityBallEnabled ) {
751769 gravityBallRadius = Math . min ( actualCanvasWidth , actualCanvasHeight ) * 0.25 ; // 25% of smaller dimension for radius
752- // Update the HTML element's size
770+ // Update the HTML element's size (though it's invisible now)
753771 mouseFollowerBall . style . width = `${ gravityBallRadius * 2 } px` ;
754772 mouseFollowerBall . style . height = `${ gravityBallRadius * 2 } px` ;
755773 }
@@ -971,7 +989,7 @@ <h2>Pixel Swirl</h2>
971989 gl . bindBuffer ( gl . ARRAY_BUFFER , positionBuffer ) ;
972990 gl . bufferData ( gl . ARRAY_BUFFER , allPositions . byteLength , gl . DYNAMIC_DRAW ) ;
973991
974- console . log ( `Created ${ pieceCount } puzzle pieces (Total GL vertices: ${ numVertices } ) with rendering dimension ${ pieceDimForRendering . toFixed ( 2 ) } x${ pieceDimForRendering . toFixed ( 2 ) } (original texture piece size: ${ originalPieceDim } x${ originalPieceDim } ). Gravity: ${ gravityForce } , Snap Distance: ${ snapDistance } . Repel: ${ repelForce } , Frequency: ${ repelFrequency } . Gravity Field: ${ gravityBallEnabled ? GRAVITY_FIELD_FORCE : 'Off' } . Atlas size: ${ atlasWidth } x${ atlasHeight } ` ) ;
992+ console . log ( `Created ${ pieceCount } puzzle pieces (Total GL vertices: ${ numVertices } ) with rendering dimension ${ pieceDimForRendering . toFixed ( 2 ) } x${ pieceDimForRendering . toFixed ( 2 ) } (original texture piece size: ${ originalPieceDim } x${ originalPieceDim } ). Gravity: ${ gravityForce } , Snap Distance: ${ snapDistance } . Repel: ${ repelForce } , Frequency: ${ repelFrequency } . Gravity Field: ${ gravityBallEnabled ? ( BASE_GRAVITY_FIELD_FORCE * gravityFieldStrength ) : 'Off' } . Atlas size: ${ atlasWidth } x${ atlasHeight } ` ) ;
975993
976994 startAnimation ( ) ;
977995 }
@@ -1020,7 +1038,7 @@ <h2>Pixel Swirl</h2>
10201038 const distance = Math . sqrt ( distanceSq ) ;
10211039
10221040 if ( distance > 0 && distance < gravityBallRadius * 2 ) { // Affects pieces within 2x radius
1023- const forceMagnitude = GRAVITY_FIELD_FORCE / distanceSq ; // Inverse square law
1041+ const forceMagnitude = ( BASE_GRAVITY_FIELD_FORCE * gravityFieldStrength ) / distanceSq ; // Inverse square law, multiplied by strength
10241042 piece . vx += dx * forceMagnitude ;
10251043 piece . vy += dy * forceMagnitude ;
10261044 }
@@ -1135,7 +1153,7 @@ <h2>Pixel Swirl</h2>
11351153
11361154 // Initialize gravity ball radius when a new image is loaded
11371155 gravityBallRadius = Math . min ( actualCanvasWidth , actualCanvasHeight ) * 0.25 ;
1138- // Update the HTML element's size
1156+ // Update the HTML element's size (though it's invisible now)
11391157 mouseFollowerBall . style . width = `${ gravityBallRadius * 2 } px` ;
11401158 mouseFollowerBall . style . height = `${ gravityBallRadius * 2 } px` ;
11411159
@@ -1247,18 +1265,18 @@ <h2>Pixel Swirl</h2>
12471265 gravityBallCheckbox . addEventListener ( 'change' , ( event ) => {
12481266 gravityBallEnabled = event . target . checked ;
12491267 if ( gravityBallEnabled ) {
1250- // Show the HTML element ball
1251- mouseFollowerBall . style . display = 'block' ;
12521268 // Initialize gravity ball radius when enabled, if no image is loaded yet
12531269 if ( ! originalImageObject ) {
12541270 resizeCanvasContainerAndCanvas ( ) ; // Ensure canvas has dimensions
12551271 }
12561272 gravityBallRadius = Math . min ( actualCanvasWidth , actualCanvasHeight ) * 0.25 ;
1273+ // Update the HTML element's size (though it's invisible now)
12571274 mouseFollowerBall . style . width = `${ gravityBallRadius * 2 } px` ;
12581275 mouseFollowerBall . style . height = `${ gravityBallRadius * 2 } px` ;
1276+ gravityFieldStrengthGroup . style . display = 'flex' ; // Show the strength slider
12591277 } else {
1260- // Hide the HTML element ball
1261- mouseFollowerBall . style . display = 'none' ;
1278+ // Hide the strength slider
1279+ gravityFieldStrengthGroup . style . display = 'none' ;
12621280 // Move the internal gravity field coordinates off-screen to ensure no lingering effect
12631281 gravityBallX = - 1000 ;
12641282 gravityBallY = - 1000 ;
@@ -1269,6 +1287,14 @@ <h2>Pixel Swirl</h2>
12691287 }
12701288 } ) ;
12711289
1290+ gravityFieldStrengthSlider . addEventListener ( 'input' , ( event ) => {
1291+ gravityFieldStrength = parseFloat ( event . target . value ) ;
1292+ gravityFieldStrengthValueSpan . textContent = gravityFieldStrength . toFixed ( 1 ) ;
1293+ if ( animationFrameId === null && originalImageObject ) {
1294+ startAnimation ( ) ;
1295+ }
1296+ } ) ;
1297+
12721298 // Event listener for mouse movement on the canvas container
12731299 canvasContainer . addEventListener ( 'mousemove' , ( event ) => {
12741300 if ( gravityBallEnabled ) {
@@ -1277,16 +1303,15 @@ <h2>Pixel Swirl</h2>
12771303 gravityBallX = event . clientX - rect . left ;
12781304 gravityBallY = event . clientY - rect . top ;
12791305
1280- // Update the HTML element's position
1306+ // Update the HTML element's position (though it's invisible now)
12811307 mouseFollowerBall . style . left = `${ gravityBallX } px` ;
12821308 mouseFollowerBall . style . top = `${ gravityBallY } px` ;
12831309 }
12841310 } ) ;
12851311
12861312 // Event listener for mouse leaving the canvas container
12871313 canvasContainer . addEventListener ( 'mouseleave' , ( ) => {
1288- if ( gravityBallEnabled ) { // Only hide if the feature is enabled
1289- mouseFollowerBall . style . display = 'none' ;
1314+ if ( gravityBallEnabled ) { // Only hide the effect if the feature is enabled
12901315 // Move the internal gravity field coordinates off-screen
12911316 gravityBallX = - 1000 ;
12921317 gravityBallY = - 1000 ;
@@ -1311,6 +1336,8 @@ <h2>Pixel Swirl</h2>
13111336 repelSlider . max = checked ? UNLOCKED_REPEL_MAX : DEFAULT_REPEL_MAX ;
13121337 frequencySlider . min = checked ? UNLOCKED_FREQUENCY_MIN : DEFAULT_FREQUENCY_MIN ;
13131338 frequencySlider . max = checked ? UNLOCKED_FREQUENCY_MAX : DEFAULT_FREQUENCY_MAX ;
1339+ gravityFieldStrengthSlider . min = checked ? UNLOCKED_GRAVITY_FIELD_STRENGTH_MIN : DEFAULT_GRAVITY_FIELD_STRENGTH_MIN ;
1340+ gravityFieldStrengthSlider . max = checked ? UNLOCKED_GRAVITY_FIELD_STRENGTH_MAX : DEFAULT_GRAVITY_FIELD_STRENGTH_MAX ;
13141341
13151342
13161343 speedSlider . value = Math . min ( Math . max ( parseFloat ( speedSlider . value ) , parseFloat ( speedSlider . min ) ) , parseFloat ( speedSlider . max ) ) ;
@@ -1327,6 +1354,9 @@ <h2>Pixel Swirl</h2>
13271354
13281355 frequencySlider . value = Math . min ( Math . max ( parseFloat ( frequencySlider . value ) , parseFloat ( frequencySlider . min ) ) , parseFloat ( frequencySlider . max ) ) ;
13291356 frequencySlider . dispatchEvent ( new Event ( 'input' ) ) ;
1357+
1358+ gravityFieldStrengthSlider . value = Math . min ( Math . max ( parseFloat ( gravityFieldStrengthSlider . value ) , parseFloat ( gravityFieldStrengthSlider . min ) ) , parseFloat ( gravityFieldStrengthSlider . max ) ) ;
1359+ gravityFieldStrengthSlider . dispatchEvent ( new Event ( 'input' ) ) ;
13301360 } ) ;
13311361
13321362
@@ -1341,11 +1371,12 @@ <h2>Pixel Swirl</h2>
13411371 } ) ;
13421372
13431373 defaultsButton . addEventListener ( 'click' , ( ) => {
1344- speedSlider . value = DEFAULT_SPEED_MIN ;
1374+ speedSlider . value = 1.0 ;
13451375 gravitySlider . value = DEFAULT_GRAVITY_MIN ;
13461376 snapDistanceSlider . value = DEFAULT_SNAP_MIN ;
13471377 repelSlider . value = DEFAULT_REPEL_MIN ;
13481378 frequencySlider . value = DEFAULT_FREQUENCY_MIN ;
1379+ gravityFieldStrengthSlider . value = DEFAULT_GRAVITY_FIELD_STRENGTH_MIN ; // Reset gravity field strength
13491380 maxPiecesInput . value = 100000 ;
13501381 pixelSizeSlider . value = DEFAULT_PIECE_SIZE_INDEX ;
13511382 lastSetPuzzlePieceSizeIndex = DEFAULT_PIECE_SIZE_INDEX ;
@@ -1360,10 +1391,11 @@ <h2>Pixel Swirl</h2>
13601391 snapDistanceSlider . dispatchEvent ( new Event ( 'input' ) ) ;
13611392 repelSlider . dispatchEvent ( new Event ( 'input' ) ) ;
13621393 frequencySlider . dispatchEvent ( new Event ( 'input' ) ) ;
1394+ gravityFieldStrengthSlider . dispatchEvent ( new Event ( 'input' ) ) ; // Dispatch event for new slider
13631395 maxPiecesInput . dispatchEvent ( new Event ( 'change' ) ) ;
13641396 pixelSizeSlider . dispatchEvent ( new Event ( 'input' ) ) ;
13651397 unlockPieceSizeCheckbox . dispatchEvent ( new Event ( 'change' ) ) ;
1366- gravityBallCheckbox . dispatchEvent ( new Event ( 'change' ) ) ;
1398+ gravityBallCheckbox . dispatchEvent ( new Event ( 'change' ) ) ; // This will hide the strength slider group
13671399
13681400 console . log ( "All settings reset to defaults." ) ;
13691401 } ) ;
@@ -1389,6 +1421,10 @@ <h2>Pixel Swirl</h2>
13891421
13901422 gravityBallCheckbox . checked = Math . random ( ) < 0.5 ;
13911423 gravityBallCheckbox . dispatchEvent ( new Event ( 'change' ) ) ;
1424+ if ( gravityBallCheckbox . checked ) { // Only randomize strength if gravity field is enabled
1425+ gravityFieldStrengthSlider . value = getRandomValue ( parseFloat ( gravityFieldStrengthSlider . min ) , parseFloat ( gravityFieldStrengthSlider . max ) , parseFloat ( gravityFieldStrengthSlider . step ) ) ;
1426+ gravityFieldStrengthSlider . dispatchEvent ( new Event ( 'input' ) ) ;
1427+ }
13921428
13931429 console . log ( "Sliders randomized!" ) ;
13941430 } ) ;
@@ -1401,7 +1437,7 @@ <h2>Pixel Swirl</h2>
14011437 } ) ;
14021438
14031439 // App Versioning
1404- const APP_VERSION = 1.014 ;
1440+ const APP_VERSION = 1.015 ;
14051441
14061442 // Initialize on load
14071443 window . onload = ( ) => {
@@ -1411,7 +1447,7 @@ <h2>Pixel Swirl</h2>
14111447 unlockFreedomCheckbox . checked = false ;
14121448 unlockFreedomCheckbox . dispatchEvent ( new Event ( 'change' ) ) ;
14131449
1414- animationSpeed = DEFAULT_SPEED_MIN ;
1450+ animationSpeed = 1.0 ;
14151451 speedSlider . value = animationSpeed ;
14161452 speedValueSpan . textContent = animationSpeed . toFixed ( 1 ) ;
14171453
@@ -1440,6 +1476,10 @@ <h2>Pixel Swirl</h2>
14401476
14411477 gravityBallEnabled = false ;
14421478 gravityBallCheckbox . checked = false ;
1479+ gravityFieldStrength = DEFAULT_GRAVITY_FIELD_STRENGTH_MIN ; // Initialize strength
1480+ gravityFieldStrengthSlider . value = gravityFieldStrength ;
1481+ gravityFieldStrengthValueSpan . textContent = gravityFieldStrength . toFixed ( 1 ) ;
1482+ gravityFieldStrengthGroup . style . display = 'none' ; // Hide by default
14431483
14441484
14451485 maxPiecesInput . value = TARGET_MAX_PIECES ;
0 commit comments