@@ -17,6 +17,9 @@ function getSnakeGameHTML() {
1717 <div class="game-area">
1818 <div id="canvas-wrapper" class="ui-canvas-frame">
1919 <canvas id="snakeCanvas" width="600" height="400"></canvas>
20+ <div id="pause-overlay" class="hidden">
21+ <h1>⏸ PAUSED</h1>
22+ </div>
2023
2124 <div id="game-over-overlay" class="hidden">
2225 <h1>GAME OVER!!</h1>
@@ -39,6 +42,7 @@ function getSnakeGameHTML() {
3942
4043 <div class="button-group">
4144 <button id="startGameBtn" class="btn-primary">Start Game</button>
45+ <button id="pauseGameBtn" class="btn-primary">Pause</button>
4246 <button id="restartSnakeBtn" class="btn-primary">Restart Game</button>
4347 </div>
4448 <div class="instruction-box">
@@ -171,6 +175,23 @@ function getSnakeGameHTML() {
171175 padding: 12px 25px;
172176 cursor: pointer;
173177 }
178+ #pause-overlay {
179+ position: absolute;
180+ top: 0;
181+ left: 0;
182+ width: 100%;
183+ height: 100%;
184+ background: rgba(0,0,0,0.6);
185+ display: flex;
186+ justify-content: center;
187+ align-items: center;
188+ z-index: 9;
189+ color: white;
190+ }
191+
192+ #pause-overlay h1 {
193+ font-size: 3rem;
194+ }
174195 </style>
175196 ` ;
176197}
@@ -181,26 +202,29 @@ let speed = 9; // System baseline operational configuration state
181202let scoreMultiplier = 2 ; // Baseline multiplier scalar state
182203let score = 0 ;
183204let lastPaintTime = 0 ;
205+ let isPaused = false ;
184206let snakeArr = [ { x : 13 , y : 10 } ] ;
185207let food = { x : 6 , y : 7 } ;
186208
187209// Profile configuration mapping matrices
188210const CONFIG_DIFFICULTY = {
189- easy : { speed : 5 , multiplier : 1 } ,
190- medium : { speed : 9 , multiplier : 2 } ,
191- hard : { speed : 14 , multiplier : 3 }
211+ easy : { speed : 5 , multiplier : 1 } ,
212+ medium : { speed : 9 , multiplier : 2 } ,
213+ hard : { speed : 14 , multiplier : 3 }
192214} ;
193215
194216function main ( ctime ) {
195217 const canvas = document . getElementById ( 'snakeCanvas' ) ;
196218 if ( ! canvas ) return ; // Exit loop if the game modal has been closed
197-
219+
198220 window . requestAnimationFrame ( main ) ;
199221 if ( ( ctime - lastPaintTime ) / 1000 < 1 / speed ) {
200222 return ;
201223 }
202224 lastPaintTime = ctime ;
203- gameEngine ( ) ;
225+ if ( ! isPaused ) {
226+ gameEngine ( ) ;
227+ }
204228}
205229
206230function isCollide ( snake ) {
@@ -244,10 +268,10 @@ function gameEngine() {
244268 direction = { x : 0 , y : 0 } ;
245269 document . getElementById ( 'final-score' ) . innerHTML = score ;
246270 document . getElementById ( 'game-over-overlay' ) . classList . remove ( 'hidden' ) ;
247-
271+
248272 // Execute persistent local evaluations
249273 checkAndSaveHighScore ( ) ;
250-
274+
251275 // Restore controls visibility states
252276 const selector = document . getElementById ( 'difficultySelect' ) ;
253277 if ( selector ) selector . disabled = false ;
@@ -297,44 +321,73 @@ function restartGame() {
297321 direction = { x : 1 , y : 0 } ;
298322 snakeArr = [ { x : 13 , y : 10 } ] ;
299323 score = 0 ;
324+ isPaused = false ;
325+
326+ const pauseOverlay = document . getElementById ( 'pause-overlay' ) ;
327+ if ( pauseOverlay ) {
328+ pauseOverlay . classList . add ( 'hidden' ) ;
329+ }
330+
331+ const pauseBtn = document . getElementById ( 'pauseGameBtn' ) ;
332+ if ( pauseBtn ) {
333+ pauseBtn . textContent = 'Pause' ;
334+ }
300335 document . getElementById ( 'score' ) . innerHTML = score ;
301336 food = { x : 6 , y : 7 } ;
337+
338+ }
339+ function togglePause ( ) {
340+ const pauseOverlay = document . getElementById ( 'pause-overlay' ) ;
341+ const pauseBtn = document . getElementById ( 'pauseGameBtn' ) ;
342+
343+ // Don't pause before game starts
344+ if ( direction . x === 0 && direction . y === 0 ) return ;
345+
346+ isPaused = ! isPaused ;
347+
348+ if ( isPaused ) {
349+ pauseOverlay . classList . remove ( 'hidden' ) ;
350+ pauseBtn . textContent = 'Resume' ;
351+ } else {
352+ pauseOverlay . classList . add ( 'hidden' ) ;
353+ pauseBtn . textContent = 'Pause' ;
354+ }
302355}
303356
304357// Initialize execution listeners
305358function initSnakeGame ( ) {
306359 window . requestAnimationFrame ( main ) ;
307-
360+
308361 // Set initial historic rendering metrics
309362 updateBestScoreUI ( ) ;
310363 function restartGame ( ) {
311- // Hide game over overlay
312- document . getElementById ( 'game-over-overlay' ) . classList . add ( 'hidden' ) ;
364+ // Hide game over overlay
365+ document . getElementById ( 'game-over-overlay' ) . classList . add ( 'hidden' ) ;
313366
314- // Reset snake
315- snakeArr = [ { x : 13 , y : 10 } ] ;
367+ // Reset snake
368+ snakeArr = [ { x : 13 , y : 10 } ] ;
316369
317- // Reset score
318- score = 0 ;
319- document . getElementById ( 'score' ) . innerHTML = score ;
370+ // Reset score
371+ score = 0 ;
372+ document . getElementById ( 'score' ) . innerHTML = score ;
320373
321- // Reset direction and start moving
322- direction = { x : 1 , y : 0 } ;
374+ // Reset direction and start moving
375+ direction = { x : 1 , y : 0 } ;
323376
324- // Generate new food
325- food = {
326- x : Math . round ( 2 + ( 16 - 2 ) * Math . random ( ) ) ,
327- y : Math . round ( 2 + ( 16 - 2 ) * Math . random ( ) )
328- } ;
377+ // Generate new food
378+ food = {
379+ x : Math . round ( 2 + ( 16 - 2 ) * Math . random ( ) ) ,
380+ y : Math . round ( 2 + ( 16 - 2 ) * Math . random ( ) )
381+ } ;
329382
330- // Re-enable difficulty selection before start
331- if ( selector ) {
332- selector . disabled = true ;
333- }
383+ // Re-enable difficulty selection before start
384+ if ( selector ) {
385+ selector . disabled = true ;
386+ }
334387
335- // Reset frame timing
336- lastPaintTime = 0 ;
337- }
388+ // Reset frame timing
389+ lastPaintTime = 0 ;
390+ }
338391
339392 // Map difficulty listener parameters
340393 const selector = document . getElementById ( 'difficultySelect' ) ;
@@ -353,7 +406,7 @@ function initSnakeGame() {
353406 } ) ;
354407
355408 document . getElementById ( 'restartSnakeBtn' ) . addEventListener ( 'click' , restartGame ) ;
356-
409+ document . getElementById ( 'pauseGameBtn' ) . addEventListener ( 'click' , togglePause ) ;
357410 document . getElementById ( 'overlayRestartBtn' ) . addEventListener ( 'click' , restartGame ) ;
358411
359412 window . addEventListener ( 'keydown' , e => {
@@ -363,7 +416,12 @@ function initSnakeGame() {
363416 selector . disabled = true ;
364417 }
365418 }
366-
419+ if ( e . code === 'Space' || e . key . toLowerCase ( ) === 'p' ) {
420+ e . preventDefault ( ) ;
421+ togglePause ( ) ;
422+ return ;
423+ }
424+ if ( isPaused ) return ;
367425 switch ( e . key ) {
368426 case "ArrowUp" : if ( direction . y !== 1 ) { direction . x = 0 ; direction . y = - 1 ; } break ;
369427 case "ArrowDown" : if ( direction . y !== - 1 ) { direction . x = 0 ; direction . y = 1 ; } break ;
@@ -386,10 +444,10 @@ function initSnakeGame() {
386444 e . preventDefault ( ) ;
387445 let touchEndX = e . changedTouches [ 0 ] . screenX ;
388446 let touchEndY = e . changedTouches [ 0 ] . screenY ;
389-
447+
390448 let dx = touchEndX - touchStartX ;
391449 let dy = touchEndY - touchStartY ;
392-
450+
393451 if ( Math . abs ( dx ) > Math . abs ( dy ) ) {
394452 if ( dx > 30 && direction . x !== - 1 ) { direction . x = 1 ; direction . y = 0 ; }
395453 else if ( dx < - 30 && direction . x !== 1 ) { direction . x = - 1 ; direction . y = 0 ; }
0 commit comments