11const GAME_COLOR_BG = 'lightblue'
22const GAME_COLOR_CEILING = '#335'
33const GAME_COLOR_FLOOR = '#335'
4+ const GAME_COLOR_LEADERS = [ '#fd0' , '#abc' , '#a50' , 'grey' , 'grey' ]
45const GAME_CELL_SIZE = 32
56const GAME_PADDING = 2
6- const GAME_FLOOR = H - GAME_CELL_SIZE * GAME_PADDING
77const GAME_CEILING = GAME_CELL_SIZE * GAME_PADDING
8+ const GAME_FLOOR = H - GAME_CELL_SIZE * GAME_PADDING + ( GAME_CELL_SIZE - H % GAME_CELL_SIZE + 1 ) % GAME_CELL_SIZE
89const GAME_LEFT_LIMIT = GAME_CELL_SIZE * GAME_PADDING
910const GAME_RIGHT_LIMIT = W / 2
1011const GAME_SPEED_H = 8
@@ -28,18 +29,20 @@ const patterns = {
2829 [ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ] ,
2930 ] ,
3031 [
31- [ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ] ,
32- [ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ] ,
33- [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ,
34- [ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 ] ,
35- [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
32+ [ 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ] ,
33+ [ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ] ,
34+ [ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ] ,
35+ [ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ] ,
36+ [ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 ] ,
37+ [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
3638 ] ,
3739 [
38- [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
39- [ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 ] ,
40- [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ,
41- [ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ] ,
42- [ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ] ,
40+ [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
41+ [ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 ] ,
42+ [ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ] ,
43+ [ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ] ,
44+ [ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ] ,
45+ [ 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ] ,
4346 ] ,
4447 [
4548 [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ,
@@ -62,10 +65,9 @@ const patterns = {
6265 [ 1 ] ,
6366 [ 1 ] ,
6467 [ 1 ] ,
65- [ 1 ] ,
6668 ] ,
6769 [
68- [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ,
70+ [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ,
6971 ] ,
7072 [
7173 [ 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 ] ,
@@ -75,22 +77,28 @@ const patterns = {
7577 [ 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 ] ,
7678 ] ,
7779 [
78- [ 1 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
79- [ 0 , 1 , 0 , 0 , 0 , 0 , 0 ] ,
80- [ 0 , 0 , 1 , 0 , 0 , 0 , 0 ] ,
81- [ 0 , 0 , 0 , 1 , 0 , 0 , 0 ] ,
82- [ 0 , 0 , 0 , 0 , 1 , 0 , 0 ] ,
83- [ 0 , 0 , 0 , 0 , 0 , 1 , 0 ] ,
84- [ 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
80+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
81+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
82+ [ 1 , 0 , 0 , 0 , 0 , 0 ] ,
83+ [ 0 , 1 , 0 , 0 , 0 , 0 ] ,
84+ [ 0 , 0 , 1 , 0 , 0 , 0 ] ,
85+ [ 0 , 0 , 0 , 1 , 0 , 0 ] ,
86+ [ 0 , 0 , 0 , 0 , 1 , 0 ] ,
87+ [ 0 , 0 , 0 , 0 , 0 , 1 ] ,
88+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
89+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
8590 ] ,
8691 [
87- [ 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ,
88- [ 0 , 0 , 0 , 0 , 0 , 1 , 0 ] ,
89- [ 0 , 0 , 0 , 0 , 1 , 0 , 0 ] ,
90- [ 0 , 0 , 0 , 1 , 0 , 0 , 0 ] ,
91- [ 0 , 0 , 1 , 0 , 0 , 0 , 0 ] ,
92- [ 0 , 1 , 0 , 0 , 0 , 0 , 0 ] ,
93- [ 1 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
92+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
93+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
94+ [ 0 , 0 , 0 , 0 , 0 , 1 ] ,
95+ [ 0 , 0 , 0 , 0 , 1 , 0 ] ,
96+ [ 0 , 0 , 0 , 1 , 0 , 0 ] ,
97+ [ 0 , 0 , 1 , 0 , 0 , 0 ] ,
98+ [ 0 , 1 , 0 , 0 , 0 , 0 ] ,
99+ [ 1 , 0 , 0 , 0 , 0 , 0 ] ,
100+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
101+ [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
94102 ] ,
95103 ] ,
96104}
@@ -198,6 +206,7 @@ const game = {
198206 entities :[ ] ,
199207 speed_h :0 ,
200208 pos_bg :0 ,
209+ top_scores :[ ] ,
201210}
202211
203212function gameSceneInit ( ) {
@@ -209,9 +218,10 @@ function gameSceneInit() {
209218 game . player = new Player ( GAME_CELL_SIZE * 2 , GAME_FLOOR - GAME_PLAYER_H )
210219 game . entities = [ ]
211220 game . speed_h = GAME_SPEED_H
212- game . speed_bg = GAME_SPEED_BG
221+ // game.speed_bg = GAME_SPEED_BG
213222 game . pos_bg = 0
214223 game . show_debug = false
224+ game . top_scores = [ ]
215225}
216226
217227function gameChangeState ( state ) {
@@ -220,16 +230,31 @@ function gameChangeState(state) {
220230 soundStop ( 'jetpack' )
221231 soundPlay ( 'death' )
222232 }
233+ if ( state == 'leaderboard' ) {
234+ let name = prompt ( 'Enter your name' ) || '<UNNAMED>'
235+ if ( name . length > 9 ) name = name . slice ( 0 , 9 ) + '\u{2026}'
236+ for ( k in keys ) keys [ k ] . pressed = false
237+ game . top_scores = JSON . parse ( localStorage . getItem ( 'top_scores' ) ) || [ ]
238+ game . top_scores . push ( [ name , game . score ] )
239+ game . top_scores = game . top_scores . sort ( ( a , b ) => b [ 1 ] - a [ 1 ] ) . slice ( 0 , 5 )
240+ localStorage . setItem ( 'top_scores' , JSON . stringify ( game . top_scores ) )
241+ }
223242}
224243
225244function gameSceneKeyPress ( key ) {
226245 if ( game . state == 'running' ) {
227246 if ( key == 'l' ) gameChangeState ( 'lose' )
228247 if ( key == 'm' ) musicPlay ( )
229- if ( key == 'g' ) game . show_debug = ! game . show_debug
230248 if ( key == 'ArrowUp' || key == 'w' || key == ' ' ) soundPlay ( 'jetpack' )
249+ if ( key == 'g' ) {
250+ game . show_debug = ! game . show_debug
251+ console . log ( localStorage )
252+ }
231253 }
232- if ( game . state == 'lose' ) {
254+ else if ( game . state == 'lose' ) {
255+ if ( key == ' ' ) gameChangeState ( 'leaderboard' )
256+ }
257+ else if ( game . state == 'leaderboard' ) {
233258 if ( key == ' ' ) sceneChange ( 'game' , { type :'bars' , sleep :500 } )
234259 if ( key == 'm' ) sceneChange ( 'menu' , { type :'circle' , sleep :500 } )
235260 }
@@ -277,9 +302,6 @@ function gameSceneLoop() {
277302 renderRect ( 0 , 0 , W , GAME_CEILING , GAME_COLOR_CEILING )
278303 renderRect ( 0 , GAME_FLOOR , W , H - GAME_FLOOR , GAME_COLOR_FLOOR )
279304 renderText ( 'v ' + VERSION , 10 , H - 10 , 'green' , { font :'Emulogic' , size :0.4 } )
280- if ( game . show_debug ) {
281- renderText ( 'Speed: ' + game . speed_h , W * 2 / 3 , GAME_CEILING * 3 / 4 , 'green' , { font :'emulogic' , size :0.8 } )
282- }
283305 }
284306 function renderLoseScreen ( ) {
285307 renderRect (
@@ -289,19 +311,62 @@ function gameSceneLoop() {
289311 H * GAME_LOSESCREEN_SIZE ,
290312 'rgba(0,0,0,0.8)'
291313 )
292- renderText ( 'GAME OVER' , W / 2 , H * 2 / 5 , 'white' , { centered :true , font :'emulogic' } )
293- renderText ( 'Your score is ' + game . score , W / 2 , H * 3 / 5 , 'white' , { centered :true , font :'emulogic' , size :0.6 } )
294- renderText ( 'Press space to retry' , W / 2 , H * 2 / 3 , 'yellow' , { centered :true , font :'emulogic' , size :0.5 } )
314+ renderText ( 'GAME OVER' , W / 2 , H * 2 / 5 , 'white' , { align :'center' , font :'emulogic' } )
315+ renderText ( 'Your score is ' + game . score , W / 2 , H * 3 / 5 , 'white' , { align :'center' , font :'emulogic' , size :0.6 } )
316+ renderText ( 'Press space to continue' , W / 2 , H * 2 / 3 , 'yellow' , { align :'center' , font :'emulogic' , size :0.5 } )
317+ }
318+ function renderLeaderboard ( ) {
319+ renderRect (
320+ W / 2 * ( 1 - GAME_LOSESCREEN_SIZE ) ,
321+ H / 2 * ( 1 - GAME_LOSESCREEN_SIZE * 1.2 ) ,
322+ W * GAME_LOSESCREEN_SIZE ,
323+ H * GAME_LOSESCREEN_SIZE * 1.2 ,
324+ 'rgba(0,0,0,0.8)'
325+ )
326+ renderText ( 'LEADERBOARD' , W / 2 , H * 1 / 4 , 'white' , { align :'center' , font :'emulogic' } )
327+ // for(let i=0;i<5;i++)
328+ // renderText(
329+ // i+1+'.',
330+ // W/3,H*2/5-20+i*36,
331+ // GAME_COLOR_LEADERS[i],{align:'center',font:'emulogic',size:0.8}
332+ // )
333+ game . top_scores . forEach ( ( entry , i ) => {
334+ renderText (
335+ i + 1 + '.' ,
336+ W / 3 , H * 2 / 5 - 20 + i * 36 ,
337+ GAME_COLOR_LEADERS [ i ] , { align :'center' , font :'emulogic' , size :0.8 }
338+ )
339+ renderText (
340+ entry [ 0 ] + ': ' ,
341+ W * 3 / 5 , H * 2 / 5 - 20 + i * 36 ,
342+ GAME_COLOR_LEADERS [ i ] , { align :'right' , font :'emulogic' , size :0.6 }
343+ )
344+ renderText (
345+ entry [ 1 ] ,
346+ W * 3 / 5 , H * 2 / 5 - 20 + i * 36 ,
347+ GAME_COLOR_LEADERS [ i ] , { align :'left' , font :'emulogic' , size :0.6 }
348+ )
349+ } )
350+ renderText ( 'Press space to retry' , W / 2 , H * 4 / 5 - 30 , 'yellow' , { align :'center' , font :'emulogic' , size :0.5 } )
351+ renderText ( 'Press M to Menu' , W / 2 , H * 4 / 5 , 'yellow' , { align :'center' , font :'emulogic' , size :0.5 } )
295352 }
296353 function renderScore ( ) {
297354 renderText ( 'Score: ' + game . score , 16 , GAME_CEILING * 3 / 4 , 'green' , { font :'emulogic' } )
355+ if ( game . show_debug )
356+ renderText ( 'Speed: ' + game . speed_h , W * 2 / 3 , GAME_CEILING * 3 / 4 , 'green' , { font :'emulogic' , size :0.8 } )
357+ }
358+ function renderGrid ( ) {
359+ for ( let i = 0 ; i < H / GAME_CELL_SIZE ; i ++ ) renderRect ( 0 , i * GAME_CELL_SIZE , W , 1 , 'black' )
360+ for ( let j = 0 ; j < W / GAME_CELL_SIZE ; j ++ ) renderRect ( j * GAME_CELL_SIZE , 0 , 1 , H , 'black' )
298361 }
299362 /* Render pipeline */
300363 /* 0 */ renderBG ( )
301364 /* 1 */ game . entities . forEach ( e => e . render ( ) )
302365 /* 2 */ game . player . render ( )
366+ /* 6 */ if ( game . show_debug ) renderGrid ( )
303367 /* 3 */ if ( game . state == 'lose' ) renderLoseScreen ( )
304- /* 4 */ if ( game . state == 'running' ) renderScore ( )
368+ /* 4 */ if ( game . state == 'leaderboard' ) renderLeaderboard ( )
369+ /* 5 */ if ( game . state == 'running' ) renderScore ( )
305370 }
306371 function update ( ) {
307372 if ( game . state == 'running' ) {
0 commit comments