@@ -5,22 +5,45 @@ const ctx = canvas.getContext("2d");
55canvas . width = 800 ;
66canvas . height = 600 ;
77
8+
9+ const pauseBtn = document . createElement ( "button" ) ;
10+ pauseBtn . innerText = "⏸️ Pauza" ;
11+ pauseBtn . style . position = "absolute" ;
12+ pauseBtn . style . top = "10px" ;
13+ pauseBtn . style . left = "10px" ;
14+ pauseBtn . style . zIndex = 10 ;
15+ pauseBtn . onclick = ( ) => paused = ! paused ;
16+ document . body . appendChild ( pauseBtn ) ;
17+
18+ const restartBtn = document . createElement ( "button" ) ;
19+ restartBtn . innerText = "🔄 Restart" ;
20+ restartBtn . style . position = "absolute" ;
21+ restartBtn . style . top = "10px" ;
22+ restartBtn . style . left = "100px" ;
23+ restartBtn . style . zIndex = 10 ;
24+ restartBtn . onclick = ( ) => newGame ( ) ;
25+ document . body . appendChild ( restartBtn ) ;
26+
27+
828const playerColors = [ "white" , "lime" , "cyan" , "orange" , "violet" ] ;
929const enemySprites = {
1030 vi : new Image ( ) ,
1131 vim : new Image ( ) ,
1232 neovim : new Image ( )
1333} ;
14- enemySprites . vi . src = "/sprites/vi .png" ;
34+ enemySprites . vi . src = "/sprites/p_vi2._nt .png" ;
1535enemySprites . vim . src = "/sprites/vim.png" ;
1636enemySprites . neovim . src = "/sprites/neovim.png" ;
1737
1838let enemyBullets = [ ] ;
39+ let showStartScreen = true ;
1940let gameOver = false ;
41+ let paused = false ;
2042let level = 1 ;
2143let fireInterval = 1500 ;
2244let fireTimer ;
2345
46+
2447function waitForSprites ( callback ) {
2548 const allLoaded = Object . values ( enemySprites ) . every ( img => img . complete && img . naturalHeight !== 0 ) ;
2649 if ( allLoaded ) callback ( ) ;
@@ -175,12 +198,40 @@ function drawHUD() {
175198 ctx . fillText ( `Level: ${ level } ` , canvas . width / 2 - 30 , 20 ) ;
176199}
177200
201+ function waitForSprites ( callback ) {
202+ const allLoaded = Object . values ( enemySprites ) . every ( img => img . complete && img . naturalHeight !== 0 ) ;
203+ if ( allLoaded ) callback ( ) ;
204+ else setTimeout ( ( ) => waitForSprites ( callback ) , 100 ) ;
205+ }
206+
178207function draw ( ) {
179208 ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
209+
210+ if ( showStartScreen ) {
211+ ctx . fillStyle = "white" ;
212+ ctx . font = "28px sans-serif" ;
213+ ctx . fillText ( "Tap, press, or move to start" , canvas . width / 2 - 180 , canvas . height / 2 ) ;
214+ requestAnimationFrame ( draw ) ;
215+ return ;
216+ }
217+
218+ if ( paused ) {
219+ ctx . fillStyle = "white" ;
220+ ctx . font = "28px sans-serif" ;
221+ ctx . fillText ( "PAUSED" , canvas . width / 2 - 60 , canvas . height / 2 ) ;
222+ requestAnimationFrame ( draw ) ;
223+ return ;
224+ }
225+
180226 if ( gameOver ) {
181227 ctx . fillStyle = "red" ;
182228 ctx . font = "30px sans-serif" ;
183- ctx . fillText ( "GAME OVER" , canvas . width / 2 - 100 , canvas . height / 2 ) ;
229+ ctx . fillText ( "GAME OVER" , canvas . width / 2 - 100 , canvas . height / 2 - 20 ) ;
230+ ctx . fillStyle = "white" ;
231+ ctx . font = "20px sans-serif" ;
232+ ctx . fillText ( `Score P1: ${ player1 . score } | P2: ${ player2 . score } ` , canvas . width / 2 - 110 , canvas . height / 2 + 20 ) ;
233+ ctx . fillText ( "Press shoot or move to restart" , canvas . width / 2 - 150 , canvas . height / 2 + 50 ) ;
234+ requestAnimationFrame ( draw ) ;
184235 return ;
185236 }
186237
@@ -261,22 +312,30 @@ function checkPlayerHit(player) {
261312 }
262313 } ) ;
263314}
315+ function activatePlayer ( player ) {
316+ if ( showStartScreen ) showStartScreen = false ;
317+ if ( gameOver ) {
318+ gameOver = false ;
319+ newGame ( ) ;
320+ }
321+ player . active = true ;
322+ }
264323
265324window . addEventListener ( "keydown" , ( e ) => {
266- if ( e . key === "a" ) { player1 . x -= player1 . speed ; player1 . active = true ; }
267- if ( e . key === "d" ) { player1 . x += player1 . speed ; player1 . active = true ; }
268- if ( e . key === " " ) { player1 . shoot ( ) ; player1 . active = true ; }
269- if ( e . key === "ArrowLeft" ) { player2 . x -= player2 . speed ; player2 . active = true ; }
270- if ( e . key === "ArrowRight" ) { player2 . x += player2 . speed ; player2 . active = true ; }
271- if ( e . key === "ArrowUp" ) { player2 . shoot ( ) ; player2 . active = true ; }
325+ if ( e . key === "a" ) { player1 . x -= player1 . speed ; activatePlayer ( player1 ) ; }
326+ if ( e . key === "d" ) { player1 . x += player1 . speed ; activatePlayer ( player1 ) ; }
327+ if ( e . key === " " ) { player1 . shoot ( ) ; activatePlayer ( player1 ) ; }
328+ if ( e . key === "ArrowLeft" ) { player2 . x -= player2 . speed ; activatePlayer ( player2 ) ; }
329+ if ( e . key === "ArrowRight" ) { player2 . x += player2 . speed ; activatePlayer ( player2 ) ; }
330+ if ( e . key === "ArrowUp" ) { player2 . shoot ( ) ; activatePlayer ( player2 ) ; }
272331 if ( e . key === "r" ) newGame ( ) ;
273332} ) ;
274333
275334canvas . addEventListener ( "touchstart" , ( e ) => {
276335 e . preventDefault ( ) ;
277336 const x = e . touches [ 0 ] . clientX ;
278337 const relX = x - canvas . getBoundingClientRect ( ) . left ;
279- player1 . active = true ;
338+ activatePlayer ( player1 ) ;
280339 if ( relX < canvas . width / 3 ) player1 . x -= player1 . speed ;
281340 else if ( relX > 2 * canvas . width / 3 ) player1 . x += player1 . speed ;
282341 else player1 . shoot ( ) ;
@@ -285,16 +344,16 @@ canvas.addEventListener("touchstart", (e) => {
285344const ws = new WebSocket ( "ws://" + location . hostname + "/ws" ) ;
286345ws . onmessage = ( event ) => {
287346 const data = JSON . parse ( event . data ) ;
288- if ( data . j1x < 1500 ) { player1 . x -= player1 . speed ; player1 . active = true ; }
289- else if ( data . j1x > 3500 ) { player1 . x += player1 . speed ; player1 . active = true ; }
290- if ( data . j1f ) { player1 . shoot ( ) ; player1 . active = true ; }
347+ if ( data . j1x < 1500 ) { player1 . x -= player1 . speed ; activatePlayer ( player1 ) ; }
348+ else if ( data . j1x > 3500 ) { player1 . x += player1 . speed ; activatePlayer ( player1 ) ; }
349+ if ( data . j1f ) { player1 . shoot ( ) ; activatePlayer ( player1 ) ; }
291350
292- if ( data . j2x < 1500 ) { player2 . x -= player2 . speed ; player2 . active = true ; }
293- else if ( data . j2x > 3500 ) { player2 . x += player2 . speed ; player2 . active = true ; }
294- if ( data . j2f ) { player2 . shoot ( ) ; player2 . active = true ; }
351+ if ( data . j2x < 1500 ) { player2 . x -= player2 . speed ; activatePlayer ( player2 ) ; }
352+ else if ( data . j2x > 3500 ) { player2 . x += player2 . speed ; activatePlayer ( player2 ) ; }
353+ if ( data . j2f ) { player2 . shoot ( ) ; activatePlayer ( player2 ) ; }
295354} ;
296355
297356waitForSprites ( ( ) => {
298357 newGame ( ) ;
299358 draw ( ) ;
300- } ) ;
359+ } ) ;
0 commit comments