C:\__todo__\tecaj.www\src\Epsilon_02\GameCanvas.java
  1  /**
  2   *  GameCanvas contains the Canvas for the Epsilon game.
  3   *  Epsilon is a simple space-shooter-vertical-scroller game.
  4   *
  5   *  Epsilon is available for non-commercial use only!
  6   *  You can learn from this sources and you can modify them
  7   *  for learning purposes.
  8   * 
  9   *  @author      Ziga Hajdukovic
 10   *  @version     1.0
 11   *
 12   *  CHANGES (01 --> 02)
 13   *  + new player sprite, p.png
 14   *  + added boss sprite boss1.png
 15   *  + added tileset t04.png
 16   *  + added enemy sprites e1.png, e2.png, e3.png
 17   *  + added fire.png, removed pf.png
 18   *  + added explosion sprite, exp.png
 19   *  + moved Image objects for sprites to spriteImage array
 20   *  + added tileImage
 21   *  + moved image loading to loadImages()
 22   *  + setClip in paintSprite
 23   *  + player sprite frames for left and right movement
 24   *  + multiple fire sprites + fire_cooldown_wait_frames
 25   *  + 20 FPS fixed frame rate
 26   *  + Vector explosionSprites
 27   *  + updateExplosionSprites()
 28   *  + doCollision() -> add explosion on collision
 29   *  + paint explosionSprites
 30   *  + Level class
 31   *  + loadLevel(), tile map, and sprite positions
 32   *  + space and tiles y and vy
 33   *  + load sprites positions
 34   *  + level paint
 35   *  +   (scrolling background space layer)
 36   *  +   (scrolling tile layer)
 37   *  + new (but still random) enemies
 38   *  + player game over explosion
 39   *  
 40  */
 41 
 42 import java.util.*;
 43 
 44 import javax.microedition.lcdui.*;
 45 
 46 //import com.nokia.mid.ui.FullCanvas;
 47 //
 48 //class GameCanvas extends FullCanvas implements Runnable
 49 class GameCanvas extends Canvas implements Runnable
 50 {
 51         private final Game midlet;
 52         
 53         public static int canvasWidth;
 54         public static int canvasHeight;
 55 
 56         public static boolean gameRunning;
 57 
 58         public static final int SOFTKEY_1 = -6;
 59         public static final int SOFTKEY_2 = -7;
 60         
 61         public static boolean menu_command_1;
 62         public static boolean menu_command_2;
 63         
 64         public static boolean command_up;
 65         public static boolean command_down;
 66         public static boolean command_left;
 67         public static boolean command_right;
 68         public static boolean command_fire;
 69         
 70         public static byte mode;
 71         public static final byte MODE_INTRO = 0;
 72         public static final byte MODE_GAME = 1;
 73         public static final byte MODE_MENU = 2;
 74         
 75         public static int loadingCounter;
 76 
 77         public static Image imgIntro;
 78         public static Image imgBackground;
 79 
 80         public static Image[] spriteImages;
 81         public static final byte SPRITE_IMAGE_PLAYER = 0;
 82         public static final byte SPRITE_IMAGE_FIRE = 1;
 83         public static final byte SPRITE_IMAGE_BOSS1 = 2;
 84         public static final byte SPRITE_IMAGE_ENEMY1 = 3;
 85         public static final byte SPRITE_IMAGE_ENEMY2 = 4;
 86         public static final byte SPRITE_IMAGE_ENEMY3 = 5;
 87         public static final byte SPRITE_IMAGE_EXPLOSION = 6;
 88         public static final byte SPRITE_IMAGE_MAX = 7;
 89         
 90         public static final byte SPRITE_FRAME_PLAYER_LEFT = 0;
 91         public static final byte SPRITE_FRAME_PLAYER_CENTER = 1;
 92         public static final byte SPRITE_FRAME_PLAYER_RIGHT = 2;
 93         
 94         public static final byte FIRE_COOLDOWN_WAIT_FRAMES = 10;
 95         public static byte fire_cooldown_wait_frames_counter;
 96         
 97         public static Image tileImage;
 98 
 99         public static int menuScreen;
100         public static final byte MENU_SCR_MAIN = 0; 
101         public static final byte MENU_SCR_TEXT_ABOUT = 1;
102         public static final byte MENU_SCR_TEXT_HELP = 2;
103         public static final byte MENU_SCR_TEXT_GAME_OVER = 3;
104 
105         public static int menuSelectedOption;
106         public static final byte MENU_OPTION_MAIN_NEW_GAME = 0;
107         public static final byte MENU_OPTION_MAIN_ABOUT = 1;
108         public static final byte MENU_OPTION_MAIN_HELP = 2;
109         public static final byte MENU_OPTION_MAIN_MAX = 2;
110         
111         public static final String[] menuScreenMainOptions = { "New game", "About", "Help"};
112         
113         public static final String[][] menuScreensTextLines = {
114                 { "" },
115                 { "About", "", "Epsilon v0.1", "(c) 2005 zigah." },
116                 { "Help", "", "Press LEFT, RIGHT, ", "UP or DOWN", "to move and", "FIRE to shoot." },
117                 { "Game Over", "", "Well done!"},
118         };
119         
120         public static GameSprite player;
121         public static Vector playerFireSprites;
122         public static int player_score;
123         public static int player_gameover_explosion_counter;
124         public static int PLAYER_GAMEOVER_EXPLOSION_COUNTER = 40;
125 
126         public static final byte MAX_ENERGY_PLAYER = 100;
127         public static final byte MAX_ENERGY_PLAYER_FIRE = 10;
128         public static final byte MAX_ENERGY_ENEMY = 10;
129         
130         public static Vector enemySprites;
131         
132         public static Vector explosionSprites;
133 
134         public static byte max_enemy_sprites = 3;
135         
136         public static final short FIXED_FRAME_TIME = 60;
137 
138         public static int global_frame_counter;
139         
140         public static Random random = new Random();
141         
142         GameCanvas(Game midlet)
143         {
144                 this.midlet = midlet;
145 
146                 canvasWidth = this.getWidth();
147                 canvasHeight = this.getHeight();
148 
149                 loadingCounter = 0;
150                 menuScreen = MENU_SCR_MAIN;
151                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
152                 mode = MODE_INTRO;
153                 gameRunning = true;
154         }
155 
156         public void run()
157         {
158                 while(gameRunning)
159                 {
160                         long frameStartTime = System.currentTimeMillis();
161                         global_frame_counter++;
162                         
163                         repaint();
164                         serviceRepaints();
165 
166                         switch (mode) {
167                         case MODE_INTRO:
168 
169                                 try
170                                 {
171                                         if (loadingCounter == 0)
172                                         {
173                                                 imgIntro = Image.createImage("/intro.png");
174                                         }
175                                         else if (loadingCounter == 1)
176                                         {
177                                                 loadImages();
178                                         }
179                                         else
180                                         {
181                                                 // view the intro splash image for a while
182                                                 // it would be better to let user skip intro by pressing a key
183                                                 // but, in a full game project, loading would take forever, anyway, so...
184                                                 try     {
185                                                         Thread.sleep(1000);
186                                                 } catch (Exception e) {};
187                                                 // switch mode
188                                                 mode = MODE_MENU;
189                                         }
190                                         loadingCounter++;
191                                 }
192                                 catch (Exception e)     {
193                                         // ignore loading exception     
194                                 };
195                                 break;
196                                 
197                         case MODE_MENU:
198 
199                                 if (command_up) {
200                                         command_up = false;
201                                         menuSelectedOption--;
202                                         if (menuSelectedOption < 0)
203                                                 menuSelectedOption = 0;
204                                 }
205                                 if (command_down) {
206                                         command_down = false;
207                                         menuSelectedOption++;
208                                         if ((menuScreen == MENU_SCR_MAIN) &&
209                                                         (menuSelectedOption > MENU_OPTION_MAIN_MAX))
210                                                 menuSelectedOption = MENU_OPTION_MAIN_MAX;
211                                 }
212                                 
213                                 if (menu_command_1)
214                                 {
215                                         menu_command_1 = false;
216                                         if (menuScreen == MENU_SCR_MAIN)
217                                         {
218                                                 switch(menuSelectedOption)
219                                                 {
220                                                 case MENU_OPTION_MAIN_NEW_GAME:
221                                                         startGame();
222                                                         break;
223                                                         
224                                                 case MENU_OPTION_MAIN_ABOUT:
225                                                         menuScreen = MENU_SCR_TEXT_ABOUT;
226                                                         break;
227                                                         
228                                                 case MENU_OPTION_MAIN_HELP:
229                                                         menuScreen = MENU_SCR_TEXT_HELP;
230                                                         break;
231                                                 }
232                                         } else {
233                                                 // all other menu screens go to main menu when OK is selected
234                                                 menuScreen = MENU_SCR_MAIN;
235                                         }
236                                 }
237                                 if (menu_command_2)
238                                 {
239                                         menu_command_2 = false;
240                                         
241                                         // exit when in main menu
242                                         if (menuScreen == MENU_SCR_MAIN)
243                                                 midlet.exitRequested();
244                                 }
245 
246                                 // delay, so the keypress events get their turn...
247                                 try     {
248                                         Thread.sleep(40);
249                                 } catch (Exception e) {};
250                                 break;
251                                 
252                         case MODE_GAME:
253 
254                                 // scroll space and tile background
255                                 Level.space_scroll_y += Level.space_scroll_vy;
256                                 Level.tiles_scroll_y += Level.tiles_scroll_vy;
257 
258                                 // top of the level (boss) reached, stop scrolling
259                                 if (Level.tiles_scroll_y < 0)
260                                         Level.tiles_scroll_y = 0;
261                                 
262                                 int tiles_scroll_x_range = (Level.LEVEL_WIDTH * Level.TILE_SIZE - canvasWidth);
263                                 int player_x_range = canvasWidth - player.w;
264                                 Level.tiles_scroll_x = player.x * tiles_scroll_x_range / player_x_range;
265 //                              System.out.print("tx: "+Level.tiles_scroll_x);
266 //                              System.out.println(", ty: "+Level.tiles_scroll_y);
267                                 
268                                 updateEnemySprites();
269 
270                                 updatePlayerSprite();
271                                 
272                                 updatePlayerFireSprites();
273                                 
274                                 updateExplosionSprites();
275                                 
276                                 // check player <-> enemy <-> player fire collision
277                                 doCollision();
278                                 
279                                 // check for game end
280                                 if (menu_command_2 || 
281                                                 ( (player.energy <= 0) &&
282                                                                 (player_gameover_explosion_counter == 0))
283                                                 )
284                                 {
285                                         menu_command_2 = false;
286                                         // on softkey_2 end game and return to main menu..
287                                         endGame();
288                                 }
289 
290                                 // calc. delay
291                                 long frameTime = System.currentTimeMillis() - frameStartTime;
292                                 if (frameTime < FIXED_FRAME_TIME)
293                                 {
294                                         try     {
295                                                 Thread.sleep( FIXED_FRAME_TIME - frameTime );
296                                         } catch (Exception e) {};
297                                 }
298                                 break;
299                         }
300                 }
301         }
302         
303         public void paint(Graphics g)
304         {
305                 switch(mode)
306                 {
307                 case MODE_INTRO:
308 
309                         g.setColor(0x000000);
310                         g.fillRect(0, 0, canvasWidth, canvasHeight);
311                         if (imgIntro != null) {
312                                 g.drawImage(imgIntro, canvasWidth/2, canvasHeight/2, Graphics.VCENTER | Graphics.HCENTER);
313                         }
314 
315 //                      g.setColor(0xFFFFFF);
316 //                      g.drawString(""+loadingCounter,0,0,Graphics.LEFT | Graphics.TOP);
317 
318                         break;
319                         
320                 case MODE_MENU:
321 
322                         Level.paintSpaceBackground(g);
323 
324                         switch(menuScreen)
325                         {
326                         case MENU_SCR_MAIN:
327                                 paintMainMenu(g);
328                                 break;
329                                 
330                         case MENU_SCR_TEXT_ABOUT:
331                         case MENU_SCR_TEXT_HELP:
332                         case MENU_SCR_TEXT_GAME_OVER:
333                                 paintTextMenu(g, menuScreen);
334                                 break;
335                         }
336                         break;
337                         
338                 case MODE_GAME:
339                         
340                         Level.paintSpaceBackground(g);
341                         Level.paintTiles(g);
342                         
343                         paintSprite( g, player );
344                         
345                         for (int i=0; i < playerFireSprites.size(); i++)
346                                 paintSprite( g, (GameSprite) playerFireSprites.elementAt(i));
347                         
348                         for (int i=0; i < enemySprites.size(); i++)
349                                 paintSprite( g, (GameSprite) enemySprites.elementAt(i) );
350                         
351                         for (int i=0; i < explosionSprites.size(); i++)
352                                 paintSprite( g, (GameSprite) explosionSprites.elementAt(i) );
353 
354                         paintStatusBars(g);
355                         
356                         break;          
357                 }
358         }
359         
360         public void keyPressed(int key)
361         {
362                 switch(key) {
363                 case SOFTKEY_1:
364                         menu_command_1 = true;
365                         break;
366                         
367                 case SOFTKEY_2:
368                         menu_command_2 = true;
369                         break;
370                 }
371                 
372                 int game_action = getGameAction(key);
373                 
374                 switch(game_action)
375                 {
376                 case UP:
377                         command_up = true;
378                         break;
379 
380                 case DOWN:
381                         command_down = true;
382                         break;
383 
384                 case LEFT:
385                         command_left = true;
386                         break;
387 
388                 case RIGHT:
389                         command_right = true;
390                         break;
391 
392                 case FIRE:
393                         command_fire = true;
394                         menu_command_1 = true;
395                         break;
396                 }
397         }
398         
399         public void keyReleased(int key)
400         {
401                 int game_action = getGameAction(key);
402 
403                 switch(game_action)
404                 {
405                 case UP:
406                         command_up = false;
407                         break;
408 
409                 case DOWN:
410                         command_down = false;
411                         break;
412 
413                 case LEFT:
414                         command_left = false;
415                         break;
416 
417                 case RIGHT:
418                         command_right = false;
419                         break;
420 
421                 case FIRE:
422                         command_fire = false;
423                         menu_command_1 = false;
424                         break;
425                 }
426         }
427 
428         public void paintMainMenu(Graphics g)
429         {
430                 // init font
431                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE));
432                 int menu_y = canvasHeight/2 - 45;
433                 for(int i=0; i <= MENU_OPTION_MAIN_MAX; i++)
434                 {
435                         // paint the main menu options
436                         if (i == menuSelectedOption) {
437                                 g.setColor(0xFFCC00);
438                         } else {
439                                 g.setColor(0xFFFFFF);
440                         }
441                         
442                         g.drawString(menuScreenMainOptions[i], canvasWidth/2, menu_y, Graphics.HCENTER | Graphics.TOP);
443                         
444                         menu_y += 30;
445                 }
446                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
447                 g.setColor(0xFFFFFF);
448                 // paint softkey_1 label
449                 g.drawString("Select", 2, canvasHeight-2, Graphics.LEFT | Graphics.BOTTOM);
450                 // paint softkey_2 label
451                 g.drawString("Exit", canvasWidth-2, canvasHeight-2, Graphics.RIGHT | Graphics.BOTTOM);
452         }
453 
454         public void paintTextMenu(Graphics g, int screen)
455         {
456                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
457                 g.setColor(0xFFFFFF);
458                 int text_line_y = 10;
459                 for(int line=0; line < menuScreensTextLines[screen].length; line++)
460                 {
461                         // paint all the lines of text in this menu screen
462                         g.drawString(menuScreensTextLines[screen][line], canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
463                         
464                         text_line_y += 15;
465                 }
466                 if (screen == MENU_SCR_TEXT_GAME_OVER)
467                 {
468                         // print score in the game over screen
469                         text_line_y += 15;
470                         g.drawString("Score: "+ player_score, canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
471                 }
472 
473                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
474                 // paint softkey_1 label
475                 g.drawString("Ok", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
476         }
477 
478         public static void paintSprite(Graphics g, GameSprite spr)
479         {
480                 // set the clip window
481                 int cx = spr.x;
482                 int cy = spr.y;
483                 int cw = GameSprite.spriteImageFrameWidths[spr.imageId];
484                 int ch = spr.h;
485                 g.setClip(cx, cy, cw, ch);
486                 
487                 // calculate the x coordinate of where to start the image paint, so our frame will be seen through the clip window
488                 int dx = spr.x - spr.frameId * GameSprite.spriteImageFrameWidths[spr.imageId];
489                 
490                 // paint the sprites image at the calculated coordinates
491                 g.drawImage(spriteImages[spr.imageId], dx, spr.y, Graphics.TOP | Graphics.LEFT);
492 
493                 // restore the clip window
494                 g.setClip(0, 0, canvasWidth, canvasHeight);
495         }
496 
497         public static void paintStatusBars(Graphics g)
498         {
499                 int max_energy_bar_width = canvasWidth/2;
500 
501                 // paint the energy bar
502                 g.setColor(0xFFFFFF);
503                 g.drawRect(5, 10, max_energy_bar_width + 1, 4);
504                 g.setColor(0xFFCC00);
505                 g.fillRect(6, 11, player.energy * max_energy_bar_width / player.energyMax, 3);
506                 
507                 // paint the score count
508                 g.setColor(0xFFFFFF);
509                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
510                 g.drawString(""+player_score, canvasWidth-4, 8, Graphics.TOP | Graphics.RIGHT);
511         }
512 
513         public void startGame()
514         {
515                 // switch to game mode
516                 mode = MODE_GAME;
517 
518                 player_score = 0;
519                 player_gameover_explosion_counter = -1;
520                 
521                 // initialize the enemy sprites list
522                 enemySprites = new Vector();
523 
524                 // initialize the explosion sprite list
525                 explosionSprites = new Vector();
526                 
527                 // initialize the player fire list
528                 playerFireSprites = new Vector();
529 
530                 Level.loadLevel((byte) 1);
531 
532                 // init level tiles position to horizontal center and vertical bottom
533                 Level.tiles_scroll_x = Level.LEVEL_WIDTH * Level.TILE_SIZE / 2 - canvasWidth /2;
534                 Level.tiles_scroll_y = Level.LEVEL_HEIGHT * Level.TILE_SIZE - canvasHeight - 1;
535                 
536         }
537         
538         public void endGame()
539         {
540                 // back to menu mode, set the game over text screen
541                 mode = MODE_MENU;
542                 menuScreen = MENU_SCR_TEXT_GAME_OVER;
543 
544                 // clean up
545                 player = null;
546                 enemySprites = null;
547         }
548 
549         public void updateEnemySprites()
550         {
551                 // check if a new enemy has to be generated
552                 if( enemySprites.size() < max_enemy_sprites )
553                 {
554                         GameSprite new_enemy;
555                         
556                         // create a new enemy
557                         // which one?
558                         byte img_id = (byte) (SPRITE_IMAGE_ENEMY1 + Math.abs(random.nextInt() % 3));
559                         
560                         new_enemy = new GameSprite(img_id, MAX_ENERGY_ENEMY);
561                         switch (img_id)
562                         {
563                         case SPRITE_IMAGE_ENEMY1:
564                                 new_enemy.vx = 0;
565                                 new_enemy.vy = 3;
566                                 break;
567                         case SPRITE_IMAGE_ENEMY2:
568                                 new_enemy.vx = 0;
569                                 new_enemy.vy = 6;
570                                 break;
571                         case SPRITE_IMAGE_ENEMY3:
572                                 new_enemy.vx = random.nextInt() % 2;
573                                 new_enemy.vy = 3 + random.nextInt() % 2;
574                                 break;
575                         }
576                         new_enemy.x = Math.abs(random.nextInt()) % canvasWidth;
577                         new_enemy.y = -new_enemy.h;
578                         
579                         // add the new enemy to the enemy sprites list
580                         enemySprites.addElement(new_enemy);
581                 }
582 
583                 // move enemy sprites
584                 for (int i=0; i < enemySprites.size(); i++)
585                 {
586                         GameSprite enemy = (GameSprite) enemySprites.elementAt(i);
587 
588                         // animate sprite to next sprite frame every 3 frames
589                         if (global_frame_counter % 3 == 0)
590                                 enemy.frameId = (byte) ( (enemy.frameId + 1) % (enemy.frameIdMax+1));
591                         
592                         // move the enemy
593                         enemy.x += enemy.vx;
594                         enemy.y += enemy.vy;
595                         
596                         // if enemy is out of screen
597                         if ( (enemy.x > canvasWidth) || (enemy.x+enemy.w < 0) ||
598                                  (enemy.y > canvasHeight) || (enemy.y+enemy.h < 0) )
599                         {
600                                 enemySprites.removeElementAt(i);
601                         }
602                 }
603         }
604 
605         public void updatePlayerSprite()
606         {
607                 if (player_gameover_explosion_counter > 0)
608                 {
609                         player_gameover_explosion_counter--;
610                 }
611                 else
612                 {
613                         // move player sprite on command, and check player <-> screen edge collision
614                         if (command_up)
615                         {
616                                 player.y -= player.vy;
617                                 if (player.y < 0)
618                                         player.y = 0;
619                         }
620                         if (command_down)
621                         {       
622                                 player.y += player.vy;
623                                 if (player.y > canvasHeight - player.h)
624                                         player.y = canvasHeight - player.h;
625                         }
626                         player.frameId = SPRITE_FRAME_PLAYER_CENTER;
627                         if (command_left)
628                         {       
629                                 player.x -= player.vx;
630                                 if (player.x < 0)
631                                         player.x = 0;
632                                 player.frameId = SPRITE_FRAME_PLAYER_LEFT;
633                         }
634                         if (command_right)
635                         {       
636                                 player.x += player.vx;
637                                 if (player.x > canvasWidth - player.w)
638                                         player.x = canvasWidth - player.w;
639                                 player.frameId = SPRITE_FRAME_PLAYER_RIGHT;
640                         }
641                         if (command_fire)
642                         {
643                                 if (fire_cooldown_wait_frames_counter <= 0)
644                                 {
645                                         GameSprite fire = new GameSprite(SPRITE_IMAGE_FIRE, MAX_ENERGY_PLAYER_FIRE);
646                                         fire.x = player.x + player.w/2 - fire.w/2;
647                                         fire.y = player.y;
648                                         fire.vy = -4;
649                                         playerFireSprites.addElement(fire);
650         
651                                         fire_cooldown_wait_frames_counter = FIRE_COOLDOWN_WAIT_FRAMES;
652                                 }
653                         }
654                         if (fire_cooldown_wait_frames_counter > 0)
655                                 fire_cooldown_wait_frames_counter--;
656                 }
657         }
658 
659         public void doCollision()
660         {
661                 
662                 int i = 0;
663                 while (i < enemySprites.size())
664                 {
665                         GameSprite enemy = (GameSprite) enemySprites.elementAt(i);
666                         
667                         // check player <-> enemy collision
668                         if (player.collidesWith(enemy))
669                         {
670                                 // add explosion
671                                 addExplosion(enemy);
672                                 addExplosion(player);
673 
674                                 // player loses energy
675                                 player.energy -= player.energyMax/4;
676                                 if (player.energy <= 0 && player_gameover_explosion_counter < 0)
677                                 {
678                                         player_gameover_explosion_counter = PLAYER_GAMEOVER_EXPLOSION_COUNTER;
679                                 }
680 
681                                 // enemy sprite is destroyed
682                                 enemySprites.removeElementAt(i);
683                                 // only increase counter, if not removed from list
684                                 i--;
685 
686                         }
687                         i++;
688                 }
689 
690                 i = 0;
691                 while (i < enemySprites.size())
692                 {
693                         GameSprite enemy = (GameSprite) enemySprites.elementAt(i);
694 
695                         // check the player fire sprites <-> enemy collision
696                         int j = 0;
697                         while (j < playerFireSprites.size())
698                         {
699                                 GameSprite fire = (GameSprite) playerFireSprites.elementAt(j);
700                                 if (fire.collidesWith(enemy) && i < enemySprites.size())
701                                 {
702                                         // add explosions
703                                         addExplosion(enemy);
704 
705                                         // destroy player fire
706                                         playerFireSprites.removeElementAt(j);
707                                         // only increase counter, if not removed from list
708                                         j--;
709 
710                                         // enemy sprite is destroyed
711                                         enemySprites.removeElementAt(i);
712                                         // only increase counter, if not removed from list
713                                         i--;
714                                 
715                                         // increase player score
716                                         player_score += 10;
717                                 }
718                                 j++;
719                         }
720                         i++;
721                 }
722         }
723 
724         public void updatePlayerFireSprites()
725         {
726                 for (int i=0; i < playerFireSprites.size(); i++)
727                 {
728                         GameSprite fire = (GameSprite) playerFireSprites.elementAt(i);
729                         fire.y += fire.vy;
730                         
731                         // destroy player fire when out of screen
732                         if (fire.y + fire.h < 0)
733                         {
734                                 playerFireSprites.removeElementAt(i);
735                                 // only increase counter, if not removed from list
736                                 i--;
737                         }
738                 }
739         }
740 
741         public void updateExplosionSprites()
742         {
743                 for (int i=0; i < explosionSprites.size(); i++)
744                 {
745                         GameSprite exp = (GameSprite) explosionSprites.elementAt(i);
746                         
747                         // animate explosion!
748                         exp.frameId++;
749                         
750                         if (exp.frameId > exp.frameIdMax)
751                         {
752                                 explosionSprites.removeElementAt(i);
753                                 // only increase counter, if not removed from list
754                                 i--;
755                         }
756                 }
757                 // create a big bada boom player gameover explosion
758                 //  7 - max explosion frames
759                 //  2 - add an explosion every 2nd frame
760                 if (player_gameover_explosion_counter > 7 &&
761                                 player_gameover_explosion_counter % 2 == 0
762                                 )
763                 {
764                         GameSprite new_exp = addExplosion(player);
765                         new_exp.x += random.nextInt() % player.w;
766                         new_exp.y += random.nextInt() % player.h;
767                 }
768         }
769 
770         public static void loadImages()
771         {
772                 try {
773                         
774                         spriteImages = new Image[SPRITE_IMAGE_MAX]; 
775                         spriteImages[SPRITE_IMAGE_PLAYER] = Image.createImage("/p.png"); 
776                         spriteImages[SPRITE_IMAGE_FIRE] = Image.createImage("/fire.png"); 
777                         spriteImages[SPRITE_IMAGE_BOSS1] = Image.createImage("/boss1.png"); 
778                         spriteImages[SPRITE_IMAGE_ENEMY1] = Image.createImage("/e1.png"); 
779                         spriteImages[SPRITE_IMAGE_ENEMY2] = Image.createImage("/e2.png"); 
780                         spriteImages[SPRITE_IMAGE_ENEMY3] = Image.createImage("/e3.png"); 
781                         spriteImages[SPRITE_IMAGE_EXPLOSION] = Image.createImage("/exp.png"); 
782         
783                         tileImage = Image.createImage("/t04.png");
784                         
785                         imgBackground = Image.createImage("/bg.png");
786                         
787                 } catch (Exception e)   {};
788         }
789 
790         public static GameSprite addExplosion(GameSprite exp_spr)
791         {
792                 // add explosion
793                 GameSprite exp = new GameSprite(SPRITE_IMAGE_EXPLOSION, (byte) 0);
794                 // center the explosion position on the exploded sprite
795                 exp.x = exp_spr.x + exp_spr.w/2 - exp.w/2;
796                 exp.y = exp_spr.y + exp_spr.h/2 - exp.h/2;
797                 exp.vx = exp_spr.vx;
798                 exp.vy = exp_spr.vy;
799                 explosionSprites.addElement(exp);
800                 
801                 return exp;
802         }
803 }
804