C:\__todo__\tecaj.www\src\Epsilon_05\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 tileImages
  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   *  CHANGES (02 -> 03)
  42   *  + run() if(gameRunning)
  43   *  + run(), + midlet.display.callSerially(this);
  44   *  + midlet.startApp(), gameCanvas.run()
  45   *  
  46   *  + pause game screen
  47   *     + new menu scr paused game, with 2 softkey labels
  48   *             + resume on softkey1
  49   *             + main menu on softkey2
  50   *     + hidenotify()
  51   *  + player.vy += Level.tiles_scroll_vy
  52   *  + removed automatic enemy sprite generation
  53   *  + updated player screen edge collision detection
  54   *  + spriteData array  
  55   *  + damage and score added to GameSprite, see doCollision
  56   *  + EXPLOSION_FRAME_SMOKE_START
  57   *  + move player with level scroll
  58   *  + enemy activation zone 
  59   *  + remove out-of-screen enemies, updated!
  60   *  + doEnemyAI()
  61   *  + fire_cooldown_frames_counter moved to GameSprite
  62   *  + collision updated, vector loop inverted...
  63   *  + enemyFireSprites Vector, updateEnemyFireSprites() paint ...
  64   *  + doEnemyAI(), shooting enemies!
  65   *  + enemy fire sprites <-> player collision
  66   *  + boss big bada boom explosion, like players...
  67   *  + god_mode
  68   *  + boss, moving, shooting
  69   *  + view and enter hiscore screens
  70   *  + flow for score view and edit
  71   *  + import javax.microedition.rms.*;
  72   *  + import java.io.*;
  73   *  + loadHighscoreFromRMS(), add call to intro mode, when loading
  74   *  + isQualified(int score)
  75   *  + addHighscore(int score, String name)
  76   *  + getHighscoreData(), highscore helper function
  77   *  + saveHighscores(), highscore helper function
  78   *
  79   *  
  80   *  CHANGES (03 -> 04)
  81   *  
  82   *  + added visible property to GameSprite, used for enemy paint and update optimization
  83   *  + BUGFIX> menu option after highscore
  84   *  + BUGFIX> player cannot be killed by enemy fire
  85   *  + FPS counter
  86   *  + 1,3,7 and 9 keys for diagonal movement
  87   *  + all level_scroll and x,y and vx,vy of sprites are now representations of floats, with factor SHIFT_FACTOR
  88   *  + level paint, used shifting instead of * and /
  89   *  + paint and run profiling!
  90   *  + LEVEL_DONE and GAME_DONE, new menu screens
  91   *  + new enemy3 types, sinusoidal movement, with shooting in players direction
  92   *  + new boss2 type
  93   *  + new enemy4 type, gun turret, shooting in players direction
  94   *  + new image for boss2 and gun turret enemy4
  95   *  + player_nukes
  96   *  + nuke status bar indicators
  97   *  + nuke background fade fx
  98   *  + playMusic(), loadMusic(), stopMusic()
  99   *  + hideNotify() added a call to stop music
 100   *  + showNotify() added to restart music
 101   *  
 102   *  
 103   *  CHANGES (03 -> 04)
 104   *  
 105   *  + icon i.png, 24x24 for nokia s60, added to res and link to .jad
 106   *  + boss2 movement
 107   *  + boss2 special paint
 108   *  + boss2 shoot toward player every x seconds
 109   *  + boss2 opening every now an then and shooting a lot when open
 110   *  + boss2 invincible when closed
 111   *  
 112 */
 113 
 114 import java.util.*;
 115 
 116 import javax.microedition.lcdui.*;
 117 
 118 import javax.microedition.rms.*;
 119 import java.io.*;
 120 
 121 import com.nokia.mid.ui.FullCanvas;
 122 
 123 import javax.microedition.media.*;
 124 import javax.microedition.media.control.*;
 125 
 126 class GameCanvas extends FullCanvas implements Runnable
 127 //class GameCanvas extends Canvas implements Runnable
 128 {
 129         private final Game midlet;
 130         
 131         public static int canvasWidth;
 132         public static int canvasHeight;
 133 
 134         public static boolean gameRunning;
 135 
 136         public static final int SOFTKEY_1 = -6;
 137         public static final int SOFTKEY_2 = -7;
 138         
 139         public static boolean menu_command_1;
 140         public static boolean menu_command_2;
 141         
 142         public static boolean command_up;
 143         public static boolean command_down;
 144         public static boolean command_left;
 145         public static boolean command_right;
 146         public static boolean command_fire;
 147         
 148         public static byte mode;
 149         public static final byte MODE_INTRO = 0;
 150         public static final byte MODE_GAME = 1;
 151         public static final byte MODE_MENU = 2;
 152         
 153         public static int loadingCounter;
 154 
 155         public static Image imgIntro;
 156         public static Image imgBackground;
 157 
 158         public static Image[] spriteImages;
 159         public static final byte SPRITE_IMAGE_PLAYER = 0;
 160         public static final byte SPRITE_IMAGE_FIRE = 1;
 161         public static final byte SPRITE_IMAGE_BOSS1 = 2;
 162         public static final byte SPRITE_IMAGE_BOSS2 = 3;
 163         public static final byte SPRITE_IMAGE_ENEMY1 = 4;
 164         public static final byte SPRITE_IMAGE_ENEMY2 = 5;
 165         public static final byte SPRITE_IMAGE_ENEMY3 = 6;
 166         public static final byte SPRITE_IMAGE_ENEMY4 = 7;
 167         public static final byte SPRITE_IMAGE_EXPLOSION = 8;
 168         public static final byte SPRITE_IMAGE_MAX = 9;
 169         
 170         public static final byte SPRITE_FRAME_PLAYER_LEFT = 0;
 171         public static final byte SPRITE_FRAME_PLAYER_CENTER = 1;
 172         public static final byte SPRITE_FRAME_PLAYER_RIGHT = 2;
 173         
 174         public static final byte PLAYER_FIRE_COOLDOWN_WAIT_FRAMES = 3;
 175         public static final byte ENEMY_FIRE_COOLDOWN_WAIT_FRAMES = 40;
 176         
 177         public static Image tileImage;
 178 
 179         public static int menuScreen;
 180         public static final byte MENU_SCR_MAIN = 0; 
 181         public static final byte MENU_SCR_TEXT_ABOUT = 1;
 182         public static final byte MENU_SCR_TEXT_HELP = 2;
 183         public static final byte MENU_SCR_TEXT_GAME_OVER = 3;
 184         public static final byte MENU_SCR_PAUSE_GAME = 4; 
 185         public static final byte MENU_SCR_HISCORE_ENTER = 5; 
 186         public static final byte MENU_SCR_HISCORE_VIEW = 6; 
 187         public static final byte MENU_SCR_TEXT_LEVEL_DONE = 7;
 188         public static final byte MENU_SCR_TEXT_GAME_DONE = 8;
 189 
 190         public static int menuSelectedOption;
 191         public static final byte MENU_OPTION_MAIN_NEW_GAME = 0;
 192         public static final byte MENU_OPTION_MAIN_HISCORES = 1;
 193         public static final byte MENU_OPTION_MAIN_MUSIC_ON_OFF = 2;
 194         public static final byte MENU_OPTION_MAIN_ABOUT = 3;
 195         public static final byte MENU_OPTION_MAIN_HELP = 4;
 196         public static final byte MENU_OPTION_MAIN_MAX = 4;
 197 
 198         public static final String TEXT_ON = " on";
 199         public static final String TEXT_OFF = " off";
 200         
 201         public static final String[] menuScreenMainOptions = { "New game", "Highscore", "Music", "About", "Help"};
 202         
 203         public static final String[][] menuScreensTextLines = {
 204                 { "" },
 205                 { "About", "", "Epsilon v0.5", "(c) 2005 zigah.", "gfx by geci." },
 206                 { "Help", "", "Press LEFT, RIGHT, ", "UP or DOWN", "to move and", "FIRE to shoot." },
 207                 { "Game Over", "", "Try harder!"},
 208                 { "","Paused!"},
 209                 { },
 210                 { },
 211                 { "Stage clear!", "", "Well done!"},
 212                 { "Game over!", "", "Superb!"},
 213         };
 214 
 215 
 216         // Highscore
 217         public static final byte MAX_SCORES = 5;
 218         public static final String SCORE_DB_NAME = "EPS";
 219         public static String hiNames[] = { "JOE", "DOE", "LAA", "BIG", "MAC" };
 220         public static int hiScores[] = { 3000, 2000, 1000, 500, 250 };
 221         private static RecordStore db;
 222 
 223         public static final char[] HI_NAME_ENTER_DEFAULT = {"A","A","A"};
 224         public static final byte MAX_HI_NAME_LENGTH = 3;
 225     public static char[] hi_name_enter = new char[MAX_HI_NAME_LENGTH];
 226         public static byte hi_name_enter_char_pos;
 227         
 228 
 229         // for debug purposes
 230         public boolean god_mode; 
 231         
 232         public static GameSprite player;
 233         public static Vector playerFireSprites;
 234         public static int player_score;
 235         public static int player_gameover_explosion_counter;
 236         public static final byte PLAYER_GAMEOVER_EXPLOSION_COUNTER_MAX = 40;
 237         
 238         public static int player_nukes;
 239         public static int player_nuke_counter = 0;
 240         public static final byte PLAYER_NUKES_MAX = 3;
 241         public static final byte PLAYER_NUKE_COUNTER_MAX = 16;
 242 
 243         public static boolean activate_boss_energy_bar;
 244         
 245         public static int boss_dead_explosion_counter;
 246         public static final byte BOSS_DEAD_EXPLOSION_COUNTER_MAX = 80;
 247 
 248         // boss2 vars
 249         public static byte boss2_open_counter;
 250         public static byte boss2_open_dir;
 251         public static final byte BOSS2_OPEN_COUNTER_MAX = 7;
 252         public static final byte BOSS2_WING_WIDTH = 11;
 253 
 254         public static byte boss2_closed_counter;
 255         public static final byte BOSS2_CLOSED_COUNTER_MAX = 90;
 256         public static byte boss2_stay_open_counter;
 257         public static final byte BOSS2_STAY_OPEN_COUNTER_MAX = 40;
 258         
 259 
 260         public static final short FIRE_VELOCITY = (8 << GameSprite.SHIFT_FACTOR);
 261         public static final byte MAX_ENEMY_FIRE = 6;
 262                 
 263         public static Vector enemyFireSprites;
 264 
 265         public static final byte MAX_ENERGY_PLAYER = 100;
 266         public static final byte MAX_ENERGY_PLAYER_FIRE = 10;
 267         public static final byte MAX_ENERGY_ENEMY = 10;
 268         
 269         public static Vector explosionSprites;
 270 
 271         public static byte max_enemy_sprites = 3;
 272         
 273         public static final short FIXED_FRAME_TIME = 10;
 274 
 275         public static int global_frame_counter;
 276         
 277         public static Random random = new Random();
 278         
 279         public static boolean PROFILE_ON_SCREEN = false; // for all the profiling drawString calls
 280 
 281         GameCanvas(Game midlet)
 282         {
 283                 this.midlet = midlet;
 284 
 285                 canvasWidth = this.getWidth();
 286                 canvasHeight = this.getHeight();
 287 
 288                 loadingCounter = 0;
 289                 menuScreen = MENU_SCR_MAIN;
 290                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
 291                 mode = MODE_INTRO;
 292                 gameRunning = true;
 293         }
 294 
 295         public static int FPS_frame_counter;
 296         public static long FPS_time;
 297         public static int FPS;
 298 
 299         public synchronized void run()
 300         {
 301                 if(gameRunning)
 302                 {
 303                         long frameStartTime = System.currentTimeMillis();
 304                         global_frame_counter++;
 305 
 306                         FPS_frame_counter++;
 307                         if (FPS_time + 1000 < frameStartTime)
 308                         {
 309                                 FPS_time = frameStartTime;
 310                                 FPS = FPS_frame_counter;
 311                                 FPS_frame_counter = 0;
 312                                 System.out.println("FPS:"+ FPS);
 313                         }
 314                         
 315                         repaint();
 316                         //serviceRepaints();
 317                         midlet.display.callSerially(this);
 318 
 319                         switch (mode) {
 320                         case MODE_INTRO:
 321 
 322                                 try
 323                                 {
 324                                         if (loadingCounter == 0)
 325                                         {
 326                                                 imgIntro = Image.createImage("/intro.png");
 327                                         }
 328                                         else if (loadingCounter == 1)
 329                                         {
 330                                                 loadImages();
 331                                                 loadMusic();
 332                                                 loadHighscoreFromRMS();
 333                                         }
 334                                         else
 335                                         {
 336                                                 // view the intro splash image for a while
 337                                                 // it would be better to let user skip intro by pressing a key
 338                                                 // but, in a full game project, loading would take forever, anyway, so...
 339                                                 try     {
 340                                                         Thread.sleep(1000);
 341                                                 } catch (Exception e) {};
 342                                                 // switch mode
 343                                                 mode = MODE_MENU;
 344                                                 playMusic();
 345                                         }
 346                                         loadingCounter++;
 347                                 }
 348                                 catch (Exception e)     {
 349                                         // ignore loading exception     
 350                                 };
 351                                 break;
 352                                 
 353                         case MODE_MENU:
 354 
 355                                 if (command_up) {
 356                                         command_up = false;
 357                                         menuSelectedOption--;
 358                                         if (menuSelectedOption < 0)
 359                                                 menuSelectedOption = 0;
 360                                         
 361                                         if (menuScreen == MENU_SCR_HISCORE_ENTER)
 362                                         {
 363                                                 if ( hi_name_enter[hi_name_enter_char_pos] > "A")
 364                                                         hi_name_enter[hi_name_enter_char_pos]--;
 365                                         }
 366                                 }
 367                                 if (command_down) {
 368                                         command_down = false;
 369                                         menuSelectedOption++;
 370                                         if ((menuScreen == MENU_SCR_MAIN) &&
 371                                                         (menuSelectedOption > MENU_OPTION_MAIN_MAX))
 372                                                 menuSelectedOption = MENU_OPTION_MAIN_MAX;
 373                                         
 374                                         if (menuScreen == MENU_SCR_HISCORE_ENTER)
 375                                         {
 376                                                 if ( hi_name_enter[hi_name_enter_char_pos] < "Z")
 377                                                         hi_name_enter[hi_name_enter_char_pos]++;
 378                                         }
 379                                 }
 380                                 if (command_left) {
 381                                         command_left = false;
 382                                         
 383                                         if (menuScreen == MENU_SCR_HISCORE_ENTER)
 384                                         {
 385                                                 if (hi_name_enter_char_pos > 0)
 386                                                         hi_name_enter_char_pos--;
 387                                         }
 388                                 }
 389                                 if (command_right) {
 390                                         command_left = false;
 391                                         
 392                                         if (menuScreen == MENU_SCR_HISCORE_ENTER)
 393                                         {
 394                                                 if (hi_name_enter_char_pos < MAX_HI_NAME_LENGTH-1)
 395                                                         hi_name_enter_char_pos++;
 396                                         }
 397                                 }
 398                                 
 399                                 if (menu_command_1)
 400                                 {
 401                                         menu_command_1 = false;
 402                                         if (menuScreen == MENU_SCR_MAIN)
 403                                         {
 404                                                 switch(menuSelectedOption)
 405                                                 {
 406                                                 case MENU_OPTION_MAIN_NEW_GAME:
 407                                                         
 408                                                         // init number of nukes available to player
 409                                                         player_nukes = PLAYER_NUKES_MAX;
 410                                                         
 411                                                         // init score
 412                                                         player_score = 0;
 413                                                         
 414                                                         startGame((byte) 1);
 415                                                         break;
 416                                                         
 417                                                 case MENU_OPTION_MAIN_HISCORES:
 418                                                         menuScreen = MENU_SCR_HISCORE_VIEW;
 419                                                         break;
 420                                                 
 421                                                 case MENU_OPTION_MAIN_ABOUT:
 422                                                         menuScreen = MENU_SCR_TEXT_ABOUT;
 423                                                         break;
 424                                                         
 425                                                 case MENU_OPTION_MAIN_MUSIC_ON_OFF:
 426                                                         musicOn = !musicOn;
 427                                                         if (musicOn)
 428                                                                 playMusic();
 429                                                         else
 430                                                                 stopMusic();
 431                                                         break;
 432 
 433                                                 case MENU_OPTION_MAIN_HELP:
 434                                                         menuScreen = MENU_SCR_TEXT_HELP;
 435                                                         break;
 436                                                 }
 437                                         } else if ( menuScreen == MENU_SCR_PAUSE_GAME) {
 438                                                 // resume pressed
 439                                                 mode = MODE_GAME;
 440                                         } else if ( menuScreen == MENU_SCR_TEXT_LEVEL_DONE) {
 441                                                 // load next level
 442                                                 startGame( (byte) (Level.levelno+1) );
 443                                                 
 444                                         } else if ( menuScreen == MENU_SCR_TEXT_GAME_OVER || menuScreen == MENU_SCR_TEXT_GAME_DONE) {
 445                                                 // ok pressed
 446                                                 if ( isQualified( player_score ) != -1 )
 447                                                 {
 448                                                         menuScreen = MENU_SCR_HISCORE_ENTER;
 449                                                         // init enter name character position
 450                                                         hi_name_enter_char_pos = 0;
 451                                                         hi_name_enter = HI_NAME_ENTER_DEFAULT;
 452                                                 } else {
 453                                                         menuScreen = MENU_SCR_HISCORE_VIEW;
 454                                                 }
 455                                         } else if ( menuScreen == MENU_SCR_HISCORE_ENTER) {
 456                                                 // save highscore
 457 
 458                                                 String name = new String(hi_name_enter);
 459                                                 addHighscore(player_score, name);
 460                                                 
 461                                                 menuScreen = MENU_SCR_HISCORE_VIEW;
 462                                         } else {
 463                                                 // all other menu screens go to main menu when OK is selected
 464                                                 menuScreen = MENU_SCR_MAIN;
 465                                                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
 466                                         }
 467                                 }
 468                                 if (menu_command_2)
 469                                 {
 470                                         menu_command_2 = false;
 471                                         
 472                                         // back to main menu, when end game selected
 473                                     if ( menuScreen == MENU_SCR_PAUSE_GAME) {
 474                                                 menuScreen = MENU_SCR_MAIN;
 475                                     } else if (menuScreen == MENU_SCR_MAIN)
 476                                     {
 477                                         gameRunning = false;
 478                                                 midlet.exitRequested();
 479                                     }
 480                                 }
 481 
 482                                 // delay, so the keypress events get their turn...
 483                                 try     {
 484                                         Thread.sleep(40);
 485                                 } catch (Exception e) {};
 486                                 break;
 487                                 
 488                         case MODE_GAME:
 489 
 490                                 // scroll space and tile background
 491                                 Level.space_scroll_y += Level.space_scroll_vy;
 492                                 Level.tiles_scroll_y += Level.tiles_scroll_vy;
 493 
 494                                 // top of the level (boss) reached, stop scrolling
 495                                 if (Level.tiles_scroll_y < 0) {
 496                                         Level.tiles_scroll_y = 0;
 497                                         Level.tiles_scroll_vy = 0;
 498                                 }
 499                                 
 500 //                              int tiles_scroll_x_range = (Level.LEVEL_WIDTH * Level.TILE_SIZE - canvasWidth);
 501 //                              int player_x_range = canvasWidth - player.w;
 502 //                              Level.tiles_scroll_x = player.x * tiles_scroll_x_range / player_x_range;
 503 
 504 
 505                                 // update scroll_x
 506                                 Level.tiles_scroll_x = player.x + (player.w/2 << GameSprite.SHIFT_FACTOR) - (canvasWidth/2 << GameSprite.SHIFT_FACTOR);
 507                                 if ((Level.tiles_scroll_x >> GameSprite.SHIFT_FACTOR) > (Level.LEVEL_WIDTH * Level.TILE_SIZE - canvasWidth)) {
 508                                         Level.tiles_scroll_x = (Level.LEVEL_WIDTH * Level.TILE_SIZE - canvasWidth) << GameSprite.SHIFT_FACTOR;
 509                                 }
 510                                 
 511                                 if (Level.tiles_scroll_x < 0) {
 512                                         Level.tiles_scroll_x = 0;
 513                                 }
 514                                 
 515                                 updatePlayerSprite();
 516                                 updatePlayerFireSprites();
 517 
 518                                 updateEnemySprites();
 519                                 updateEnemyFireSprites();
 520                                 
 521                                 updateExplosionSprites();
 522                                 
 523                                 // check player <-> enemy <-> player fire collision
 524                                 doCollision();
 525                                 
 526                                 // check for game end
 527                                 checkEndGame();
 528                                 
 529                                 if (menu_command_2)
 530                                 {
 531                                         menu_command_2 = false;
 532                                         // on softkey_2 activate pause game menu
 533                                         mode = MODE_MENU;
 534                                         menuScreen = MENU_SCR_PAUSE_GAME;
 535                                 }
 536 
 537                                 // calc. delay
 538                                 long frameTime = System.currentTimeMillis() - frameStartTime;
 539                                 if (frameTime < FIXED_FRAME_TIME)
 540                                 {
 541                                         try     {
 542                                                 Thread.sleep( FIXED_FRAME_TIME - frameTime );
 543                                         } catch (Exception e) {};
 544                                 }
 545                                 break;
 546                         }
 547                 }
 548         }
 549         
 550         
 551         public byte PAINT_PROFILE_TIMES_MAX = 4;
 552         public long[] paint_profile_times = new long[PAINT_PROFILE_TIMES_MAX*2];
 553         public String[] paint_profile_labels = { " ", " ", " ", " ", " " };
 554         public int paint_profile_times_index_counter;
 555 
 556         public void paint_profileStart(int idx, String label) {
 557                 paint_profile_times_index_counter = idx*2;
 558                 paint_profile_times_index_counter = idx*2;
 559                 paint_profile_labels[paint_profile_times_index_counter / 2] = label;
 560                 paint_profile_times[paint_profile_times_index_counter] = System
 561                                 .currentTimeMillis();
 562                 paint_profile_times_index_counter++;
 563         }
 564 
 565         public void paint_profileEnd() {
 566                 paint_profile_times[paint_profile_times_index_counter] = paint_profile_times[paint_profile_times_index_counter]
 567                                 + (System.currentTimeMillis() - paint_profile_times[paint_profile_times_index_counter - 1]);
 568         }
 569 
 570         public synchronized void paint(Graphics g)
 571         {
 572         paint_profile_times_index_counter = 0;
 573                 switch(mode)
 574                 {
 575                 case MODE_INTRO:
 576 
 577                         g.setColor(0x000000);
 578                         g.fillRect(0, 0, canvasWidth, canvasHeight);
 579                         if (imgIntro != null) {
 580                                 g.drawImage(imgIntro, canvasWidth/2, canvasHeight/2, Graphics.VCENTER | Graphics.HCENTER);
 581                         }
 582 
 583 //                      g.setColor(0xFFFFFF);
 584 //                      g.drawString(""+loadingCounter,0,0,Graphics.LEFT | Graphics.TOP);
 585 
 586                         break;
 587                         
 588                 case MODE_MENU:
 589 
 590                         Level.paintSpaceBackground(g);
 591 
 592                         switch(menuScreen)
 593                         {
 594                         case MENU_SCR_MAIN:
 595                                 paintMainMenu(g);
 596                                 break;
 597                                 
 598                         case MENU_SCR_TEXT_ABOUT:
 599                         case MENU_SCR_TEXT_HELP:
 600                         case MENU_SCR_TEXT_GAME_OVER:
 601                         case MENU_SCR_TEXT_GAME_DONE:
 602                         case MENU_SCR_TEXT_LEVEL_DONE:
 603                         case MENU_SCR_PAUSE_GAME:
 604                                 paintTextMenu(g, menuScreen);
 605                                 break;
 606                         case MENU_SCR_HISCORE_VIEW:
 607                                 paintHiscoreView(g);
 608                                 break;
 609                         case MENU_SCR_HISCORE_ENTER:
 610                                 paintHiscoreEnter(g);
 611                                 break;
 612                         }
 613                         break;
 614                         
 615                 case MODE_GAME:
 616 
 617                 paint_profileStart(0,"BG");
 618             Level.paintSpaceBackground(g);
 619                 paint_profileEnd();
 620                 paint_profileStart(1,"TL");
 621                         Level.paintTiles(g);
 622                                 paint_profileEnd();
 623                         
 624                 paint_profileStart(2,"SP");
 625                         paintSprite( g, player );
 626                         
 627                         for (int i=0; i < Level.enemySprites.size(); i++)
 628                         {
 629                                 GameSprite enemy = (GameSprite) Level.enemySprites.elementAt(i);
 630                                 if (enemy.visible)
 631                                         paintSprite( g, enemy );
 632                         }
 633                         
 634                         for (int i=0; i < explosionSprites.size(); i++)
 635                                 paintSprite( g, (GameSprite) explosionSprites.elementAt(i) );
 636 
 637                         for (int i=0; i < playerFireSprites.size(); i++)
 638                                 paintSprite( g, (GameSprite) playerFireSprites.elementAt(i));
 639                         
 640                         for (int i=0; i < enemyFireSprites.size(); i++)
 641                                 paintSprite( g, (GameSprite) enemyFireSprites.elementAt(i));
 642 
 643                                 paint_profileEnd();
 644 
 645                 paint_profileStart(3,"ST");
 646                         paintStatusBars(g);
 647                                 paint_profileEnd();
 648                         
 649             if (GameCanvas.PROFILE_ON_SCREEN) {
 650                                 for (int p = 0; p < PAINT_PROFILE_TIMES_MAX; p++) {
 651                                         g.setColor(0x000000);
 652                                         g.drawString(paint_profile_labels[p] + " "
 653                                                         + paint_profile_times[p * 2 + 1], 2, 20 + 20 * p,
 654                                                         Graphics.LEFT | Graphics.TOP);
 655                                         g.setColor(0xFFFFFF);
 656                                         g.drawString(paint_profile_labels[p] + " "
 657                                                         + paint_profile_times[p * 2 + 1], 2 - 1,
 658                                                         20 + 20 * p - 1, Graphics.LEFT | Graphics.TOP);
 659                                 }
 660                         }
 661 
 662                                 
 663                         break;          
 664                 }
 665         }
 666         
 667         public void keyPressed(int key)
 668         {
 669                 switch(key) {
 670                 case SOFTKEY_1:
 671                         menu_command_1 = true;
 672                         break;
 673                         
 674                 case SOFTKEY_2:
 675                         menu_command_2 = true;
 676                         break;
 677 
 678                 // TODO: debug, temp, remove
 679                 case KEY_POUND:
 680                         god_mode = !god_mode;
 681                         
 682                         // TODO: debug, temp, remove
 683                         Level.tiles_scroll_vy *= 2;
 684                         
 685                         break;
 686                 case KEY_STAR:
 687                         PROFILE_ON_SCREEN = !PROFILE_ON_SCREEN;
 688                         break;
 689                 case KEY_NUM1:
 690                         command_up = true;
 691                         command_left = true;
 692                         break;
 693                 case KEY_NUM3:
 694                         command_up = true;
 695                         command_right = true;
 696                         break;
 697                 case KEY_NUM7:
 698                         command_down = true;
 699                         command_left = true;
 700                         break;
 701                 case KEY_NUM9:
 702                         command_down = true;
 703                         command_right = true;
 704                         break;
 705                 case KEY_NUM0:
 706                         if (player_nuke_counter == 0 && player_nukes > 0)
 707                         {
 708                                 player_nukes--;
 709                                 player_nuke_counter = PLAYER_NUKE_COUNTER_MAX;
 710                         }
 711                         break;
 712                 }
 713                 
 714                 int game_action = getGameAction(key);
 715                 
 716                 switch(game_action)
 717                 {
 718                 case UP:
 719                         command_up = true;
 720                         break;
 721 
 722                 case DOWN:
 723                         command_down = true;
 724                         break;
 725 
 726                 case LEFT:
 727                         command_left = true;
 728                         break;
 729 
 730                 case RIGHT:
 731                         command_right = true;
 732                         break;
 733 
 734                 case FIRE:
 735                         command_fire = true;
 736                         menu_command_1 = true;
 737                         break;
 738                 }
 739         }
 740         
 741         public void keyReleased(int key)
 742         {
 743                 int game_action = getGameAction(key);
 744 
 745                 switch(key)
 746                 {
 747                 case KEY_NUM1:
 748                         command_up = false;
 749                         command_left = false;
 750                         break;
 751                 case KEY_NUM3:
 752                         command_up = false;
 753                         command_right = false;
 754                         break;
 755                 case KEY_NUM7:
 756                         command_down = false;
 757                         command_left = false;
 758                         break;
 759                 case KEY_NUM9:
 760                         command_down = false;
 761                         command_right = false;
 762                         break;
 763                 }
 764 
 765                 switch(game_action)
 766                 {
 767                 case UP:
 768                         command_up = false;
 769                         break;
 770 
 771                 case DOWN:
 772                         command_down = false;
 773                         break;
 774 
 775                 case LEFT:
 776                         command_left = false;
 777                         break;
 778 
 779                 case RIGHT:
 780                         command_right = false;
 781                         break;
 782 
 783                 case FIRE:
 784                         command_fire = false;
 785                         menu_command_1 = false;
 786                         break;
 787                 }
 788         }
 789 
 790         public void paintMainMenu(Graphics g)
 791         {
 792                 // init font
 793                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE));
 794                 int menu_y = canvasHeight/2 - 45;
 795                 for(int i=0; i <= MENU_OPTION_MAIN_MAX; i++)
 796                 {
 797                         // paint the main menu options
 798                         if (i == menuSelectedOption) {
 799                                 g.setColor(0xFFCC00);
 800                         } else {
 801                                 g.setColor(0xFFFFFF);
 802                         }
 803                         
 804                         String option_text = menuScreenMainOptions[i];
 805                         
 806                         if (i == MENU_OPTION_MAIN_MUSIC_ON_OFF)
 807                         {
 808                                 option_text = option_text + (musicOn ? TEXT_ON : TEXT_OFF);
 809                         }
 810                         g.drawString(option_text, canvasWidth/2, menu_y, Graphics.HCENTER | Graphics.TOP);
 811 
 812                         menu_y += 20;
 813                 }
 814                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
 815                 g.setColor(0xFFFFFF);
 816                 // paint softkey_1 label
 817                 g.drawString("Select", 2, canvasHeight-2, Graphics.LEFT | Graphics.BOTTOM);
 818                 // paint softkey_2 label
 819                 g.drawString("Exit", canvasWidth-2, canvasHeight-2, Graphics.RIGHT | Graphics.BOTTOM);
 820         }
 821 
 822         public void paintTextMenu(Graphics g, int screen)
 823         {
 824                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
 825                 g.setColor(0xFFFFFF);
 826                 int text_line_y = 10;
 827                 for(int line=0; line < menuScreensTextLines[screen].length; line++)
 828                 {
 829                         // paint all the lines of text in this menu screen
 830                         g.drawString(menuScreensTextLines[screen][line], canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
 831                         
 832                         text_line_y += 15;
 833                 }
 834                 if (screen == MENU_SCR_TEXT_GAME_OVER || screen == MENU_SCR_TEXT_LEVEL_DONE || screen == MENU_SCR_TEXT_GAME_DONE)
 835                 {
 836                         // print score in the game over screen
 837                         text_line_y += 15;
 838                         g.drawString("Score: "+ player_score, canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
 839                 }
 840 
 841                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
 842                 
 843                 if (menuScreen == MENU_SCR_PAUSE_GAME )
 844                 {
 845                         // paint softkey_1 label
 846                         g.drawString("Resume", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
 847                         // paint softkey_2 label
 848                         g.drawString("End game", canvasWidth-1, canvasHeight-1, Graphics.RIGHT | Graphics.BOTTOM);
 849                 }
 850                 else
 851                 {
 852                         // paint softkey_1 label
 853                         g.drawString("Ok", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
 854                 }
 855         }
 856 
 857         public static void paintHiscoreView(Graphics g)
 858         {
 859                 g.setColor(0xFFFFFF);
 860 
 861                 g.drawString("Highscore!", canvasWidth/2, 2, Graphics.HCENTER | Graphics.TOP);
 862 
 863                 for (int i=0; i < MAX_SCORES; i++)
 864                 {
 865                         g.drawString(hiNames[i], canvasWidth*1/4, 20 + 20*i, Graphics.LEFT | Graphics.TOP);
 866                         g.drawString(""+hiScores[i], canvasWidth*3/4, 20 + 20*i, Graphics.RIGHT | Graphics.TOP);
 867                 }
 868                 
 869                 // paint softkey_1 label
 870                 g.drawString("Ok", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
 871         }
 872         public static void paintHiscoreEnter(Graphics g)
 873         {
 874                 g.setColor(0xFFFFFF);
 875 
 876                 g.drawString("Enter name:", canvasWidth/2, canvasHeight*1/4, Graphics.HCENTER | Graphics.BOTTOM);
 877 
 878                 for (int i=0; i < MAX_HI_NAME_LENGTH; i++)
 879                 {
 880                         if (i == hi_name_enter_char_pos)
 881                                 g.setColor(0xFFFF00);
 882                         else
 883                                 g.setColor(0xFFFFFF);
 884                         g.drawChar(hi_name_enter[i], canvasWidth/2 - 12 + 12*i, canvasHeight*2/4, Graphics.HCENTER | Graphics.BOTTOM);
 885                 }
 886 
 887                 g.setColor(0xFFFFFF);
 888                 g.drawString("Score: "+ player_score, canvasWidth/2, canvasHeight*3/4, Graphics.HCENTER | Graphics.BOTTOM);
 889 
 890                 // paint softkey_1 label
 891                 g.drawString("Save", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
 892         }
 893 
 894         public static void paintSprite(Graphics g, GameSprite spr)
 895         {
 896                 // set the clip window
 897                 int dx = (spr.x - Level.tiles_scroll_x) >> GameSprite.SHIFT_FACTOR;
 898                 int dy = (spr.y - Level.tiles_scroll_y) >> GameSprite.SHIFT_FACTOR;
 899                 int cx = dx;
 900                 int cy = dy;
 901                 int cw = GameSprite.spriteImageFrameWidths[spr.imageId];
 902                 int ch = spr.h;
 903                 
 904                 //  check clip window coordinates, if out of screen
 905                 if (cx < 0)
 906                 {
 907                         cw += cx;
 908                         cx = 0;
 909                 }
 910                 if (cy < 0)
 911                 {
 912                         ch += cy;
 913                         cy = 0;
 914                 }
 915 
 916                 if (spr.spriteId == Level.SPRITE_ID_BOSS2)
 917                 {
 918                         // paint boss2 left wing
 919                         int dxw = dx + (BOSS2_OPEN_COUNTER_MAX - boss2_open_counter);
 920                         int cxw = dxw;
 921                         int cww = BOSS2_WING_WIDTH;
 922                         
 923                         g.setClip(cxw, cy, cww, ch);
 924                         g.drawImage(spriteImages[spr.imageId], dxw, dy, Graphics.TOP | Graphics.LEFT);
 925 
 926                         // paint boss2 rightt wing
 927                         dxw = dx - (BOSS2_OPEN_COUNTER_MAX - boss2_open_counter);
 928                         cxw = dx + GameSprite.spriteImageFrameWidths[spr.imageId] - BOSS2_WING_WIDTH - (BOSS2_OPEN_COUNTER_MAX - boss2_open_counter);
 929                         
 930                         g.setClip(cxw, cy, cww, ch);
 931                         g.drawImage(spriteImages[spr.imageId], dxw, dy, Graphics.TOP | Graphics.LEFT);
 932                         
 933                         // paint boss2 body
 934                         int cwb = cw - BOSS2_WING_WIDTH*2;
 935                         int cxb = cx + BOSS2_WING_WIDTH;
 936 
 937                         g.setClip(cxb, cy, cwb, ch);
 938                         g.drawImage(spriteImages[spr.imageId], dx, dy, Graphics.TOP | Graphics.LEFT);
 939 
 940                 } else {
 941 
 942                         g.setClip(cx, cy, cw, ch);
 943                         
 944                         // calculate the x coordinate of where to start the image paint, so our frame will be seen through the clip window
 945                         dx = dx - spr.frameId * GameSprite.spriteImageFrameWidths[spr.imageId];
 946                         
 947                         // paint the sprites image at the calculated coordinates
 948                         g.drawImage(spriteImages[spr.imageId], dx, dy, Graphics.TOP | Graphics.LEFT);
 949         
 950                 }
 951                 // restore the clip window
 952                 g.setClip(0, 0, canvasWidth, canvasHeight);
 953         }
 954 
 955         public static void paintStatusBars(Graphics g)
 956         {
 957                 int max_energy_bar_width = canvasWidth/2;
 958 
 959                 // paint the energy bar
 960                 g.setColor(0xFFFFFF);
 961                 g.drawRect(5, 5, max_energy_bar_width + 1, 4);
 962                 g.setColor(0xFFCC00);
 963                 g.fillRect(6, 6, player.energy * max_energy_bar_width / player.energyMax, 3);
 964                 
 965                 if ( activate_boss_energy_bar)
 966                 {
 967                         // paint the energy bar
 968                         g.setColor(0xFFFFFF);
 969                         g.drawRect(5, 12, max_energy_bar_width + 1, 4);
 970                         g.setColor(0xFF9900);
 971                         g.fillRect(6, 13, Level.boss.energy * max_energy_bar_width / Level.boss.energyMax, 3);
 972                 }
 973 
 974                 // paint the score count
 975                 g.setColor(0xFFFFFF);
 976                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
 977                 g.drawString(""+player_score, canvasWidth-4, 8, Graphics.TOP | Graphics.RIGHT);
 978                 
 979                 // paint number of nukes
 980                 for (int i=0; i < PLAYER_NUKES_MAX; i++)
 981                 {
 982                         g.setColor(0xFFFF00);
 983                         int x = canvasWidth - (3-i) * (5+3);
 984                         int y = canvasHeight - 8;
 985                         if ((3-i) <= player_nukes)
 986                         {
 987                                 g.fillRect(x,y,5,5);
 988                         }
 989                         g.setColor(0xFFFFFF);
 990                         g.drawRect(x,y,5,5);
 991                 }
 992 
 993                 if (PROFILE_ON_SCREEN)
 994                 {
 995                         // paint the FPS
 996                         g.setColor(0xFFFFFF);
 997                         g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
 998                         g.drawString("FPS: "+FPS, 1, canvasHeight-2, Graphics.BOTTOM | Graphics.LEFT);
 999                 }
1000         }
1001 
1002         public void startGame(byte load_level_no)
1003         {
1004                 player_gameover_explosion_counter = -1;
1005                 player_nuke_counter = 0;
1006                 
1007                 activate_boss_energy_bar = false;
1008                 boss_dead_explosion_counter = -1;
1009 
1010                 // initialize the explosion sprite list
1011                 explosionSprites = new Vector();
1012                 
1013                 // initialize the player fire list
1014                 playerFireSprites = new Vector();
1015 
1016                 // initialize the enemy fire list
1017                 enemyFireSprites = new Vector();
1018 
1019                 // init level tiles position to horizontal center and vertical bottom
1020                 Level.tiles_scroll_x = (Level.LEVEL_WIDTH * Level.TILE_SIZE / 2 - canvasWidth /2) << GameSprite.SHIFT_FACTOR;
1021                 Level.tiles_scroll_y = (Level.LEVEL_HEIGHT * Level.TILE_SIZE - canvasHeight - 1) << GameSprite.SHIFT_FACTOR;
1022         
1023                 Level.loadLevel( load_level_no );
1024 
1025                 // switch to game mode
1026                 mode = MODE_GAME;
1027                 
1028                 boss2_open_counter = 0;
1029                 boss2_open_dir = 1;
1030                 boss2_closed_counter = BOSS2_CLOSED_COUNTER_MAX;
1031                 boss2_stay_open_counter = -1;
1032 
1033         }
1034         
1035         public static final byte GAME_END_NONE = 0; 
1036         public static final byte GAME_END_LOSE = 1; 
1037         public static final byte GAME_END_WIN = 2; 
1038         
1039         public void checkEndGame()
1040         {
1041                 byte game_end = GAME_END_NONE;
1042                 // check for game end
1043                 if ( (player.energy <= 0) && (player_gameover_explosion_counter == 0) )
1044                 {
1045                         game_end = GAME_END_LOSE;
1046                 } else if ( (Level.boss.energy <= 0) && (boss_dead_explosion_counter == 0) )
1047                 {
1048                         game_end = GAME_END_WIN;
1049                 }
1050                 if (game_end > GAME_END_NONE)
1051                 {
1052                         // back to menu mode, set the game or lever over text screen
1053                         mode = MODE_MENU;
1054                         if (game_end == GAME_END_LOSE)
1055                         {
1056                                 menuScreen = MENU_SCR_TEXT_GAME_OVER;
1057                         } else {
1058                                 if (Level.levelno == Level.MAX_LEVELS)
1059                                         menuScreen = MENU_SCR_TEXT_GAME_DONE;
1060                                 else
1061                                         menuScreen = MENU_SCR_TEXT_LEVEL_DONE;
1062                         }
1063         
1064                         // clean up
1065                         player = null;
1066                         Level.enemySprites = null;
1067                 }
1068         }
1069 
1070         public void updateEnemySprites()
1071         {
1072                 // move enemy sprites
1073                 int i = Level.enemySprites.size()-1;
1074                 while (i >= 0)
1075                 {
1076                         GameSprite enemy = (GameSprite) Level.enemySprites.elementAt(i);
1077                         
1078                         if ( (enemy.y - Level.tiles_scroll_y > (canvasHeight << GameSprite.SHIFT_FACTOR)) )
1079                         {
1080                                 // remove out-of-screen enemies
1081                                 Level.enemySprites.removeElementAt(i);
1082                                 i--;
1083                         }
1084                         else
1085                         {
1086                                 //System.out.println(enemy.y +"-"+ Level.tiles_scroll_y +">"+ Level.ENEMY_AI_ACTIVATION_ZONE_Y);
1087                                 // do the AI move, shoot and other tricks
1088                                 if ( enemy.y - Level.tiles_scroll_y > (Level.ENEMY_AI_ACTIVATION_ZONE_Y << GameSprite.SHIFT_FACTOR) )
1089                                 {
1090                                         enemy.visible = true;
1091                                         doEnemyAI( enemy );
1092                                         i--;
1093                                 } else {
1094                                         enemy.visible = false;
1095                                         // optimization
1096                                         // but enemySprites must be ordered by the sprites" y coordinate !
1097                                         // they are in this case, because of loadLevel
1098                                         break;
1099                                 }
1100                         }
1101                 }
1102                 if (boss_dead_explosion_counter > 0)
1103                 {
1104                         boss_dead_explosion_counter--;
1105                 }
1106         }
1107         
1108         public void doEnemyAI( GameSprite sprite )
1109         {
1110                 
1111 //              System.out.println("doing enemy ai for "+sprite.spriteId);
1112                 
1113                 switch (sprite.spriteId)
1114                 {
1115                 case Level.SPRITE_ID_ENEMY1:
1116                         break;
1117                 case Level.SPRITE_ID_ENEMY1_SHOOTING:
1118 
1119                         shootEnemyFire(sprite, Level.SPRITE_ID_FIRE2, (byte) 1);
1120                         
1121                         break;
1122                 case Level.SPRITE_ID_ENEMY2:
1123                         break;
1124                 case Level.SPRITE_ID_ENEMY2_SHOOTING:
1125                         
1126                         shootEnemyFire(sprite, Level.SPRITE_ID_FIRE2, (byte) 1);
1127 
1128                         break;
1129                 case Level.SPRITE_ID_ENEMY4_SHOOTING:
1130                         
1131                         shootEnemyFireTowardPlayer(sprite, Level.SPRITE_ID_FIRE3, (byte) 2);
1132 
1133                         break;
1134                 case Level.SPRITE_ID_ENEMY3:
1135                 case Level.SPRITE_ID_ENEMY3_SINUS:
1136                 case Level.SPRITE_ID_ENEMY3_SINUS_SHOOTING:
1137 
1138                         // animate sprite to next sprite frame every 3 frames
1139                         if (global_frame_counter % 3 == 0)
1140                                 sprite.frameId = (byte) ( (sprite.frameId + 1) % (sprite.frameIdMax+1));
1141                         
1142                         // sinusoidal movement
1143                         if (sprite.spriteId == Level.SPRITE_ID_ENEMY3_SINUS || sprite.spriteId == Level.SPRITE_ID_ENEMY3_SINUS_SHOOTING)
1144                         {
1145                                 int tx = Math.abs( (sprite.y >> 1) % 360);
1146                                 sprite.vx = sin[tx] >> 4;
1147 
1148 //                              int ty = Math.abs(global_frame_counter % 360);
1149 //                              sprite.vy = - sin[ty] >> 5;
1150                         }
1151                         if (sprite.spriteId == Level.SPRITE_ID_ENEMY3_SINUS)
1152                         {
1153                                 shootEnemyFireTowardPlayer(sprite, Level.SPRITE_ID_FIRE3, (byte) 2);
1154                         }
1155                         
1156                         break;
1157                 case Level.SPRITE_ID_BOSS1:
1158 
1159                         activate_boss_energy_bar = true;
1160 
1161                         // boss fire
1162                         if (sprite.fire_cooldown_frames_counter <= 0)
1163                         {
1164                                 GameSprite new_fire;
1165 
1166                                 new_fire = new GameSprite(Level.SPRITE_ID_FIRE2);
1167                                 new_fire.frameId = 1;
1168                                 new_fire.x = sprite.x + ((sprite.w - 5 - new_fire.w) << GameSprite.SHIFT_FACTOR);
1169                                 new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1170                                 new_fire.vx = 0;
1171                                 new_fire.vy = sprite.vy + FIRE_VELOCITY/2;
1172                                 enemyFireSprites.addElement(new_fire);
1173 
1174                                 new_fire = new GameSprite(Level.SPRITE_ID_FIRE2);
1175                                 new_fire.frameId = 1;
1176                                 new_fire.x = sprite.x + (5 << GameSprite.SHIFT_FACTOR);
1177                                 new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1178                                 new_fire.vx = 0;
1179                                 new_fire.vy = sprite.vy + FIRE_VELOCITY/2;
1180                                 enemyFireSprites.addElement(new_fire);
1181 
1182                                 new_fire = new GameSprite(Level.SPRITE_ID_FIRE3);
1183                                 new_fire.frameId = 2;
1184                                 new_fire.x = sprite.x + ((sprite.w / 2 - new_fire.w / 2) << GameSprite.SHIFT_FACTOR);
1185                                 new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1186                                 new_fire.vx = 0;
1187                                 new_fire.vy = sprite.vy + FIRE_VELOCITY;
1188                                 enemyFireSprites.addElement(new_fire);
1189 
1190                                 sprite.fire_cooldown_frames_counter = ENEMY_FIRE_COOLDOWN_WAIT_FRAMES;
1191                         } else {
1192                                 // extra cooldown, boss only
1193                                 sprite.fire_cooldown_frames_counter--;
1194                         }
1195                         
1196                         // boss move
1197                         if (sprite.x + (sprite.w << GameSprite.SHIFT_FACTOR) > (((Level.LEVEL_WIDTH * Level.TILE_SIZE) - (Level.TILE_SIZE/2)) << GameSprite.SHIFT_FACTOR) )
1198                                 sprite.vx = -(1 << GameSprite.SHIFT_FACTOR);
1199                         if (sprite.x < (Level.TILE_SIZE/2 << GameSprite.SHIFT_FACTOR) )
1200                                 sprite.vx = 1 << GameSprite.SHIFT_FACTOR;
1201                         
1202                         break;
1203 
1204                 case Level.SPRITE_ID_BOSS2:
1205 
1206                         activate_boss_energy_bar = true;
1207 
1208                         // boss move
1209                         if (sprite.x + (sprite.w << GameSprite.SHIFT_FACTOR) > (((Level.LEVEL_WIDTH * Level.TILE_SIZE) - (Level.TILE_SIZE/2)) << GameSprite.SHIFT_FACTOR) )
1210                         {
1211                                 sprite.x = (((Level.LEVEL_WIDTH * Level.TILE_SIZE) - (Level.TILE_SIZE/2)) << GameSprite.SHIFT_FACTOR) - (sprite.w << GameSprite.SHIFT_FACTOR);
1212                                 sprite.vx = -(1 << GameSprite.SHIFT_FACTOR);
1213                         }
1214                         if (sprite.x < (Level.TILE_SIZE/2 << GameSprite.SHIFT_FACTOR) )
1215                         {
1216                                 sprite.x = (Level.TILE_SIZE/2 << GameSprite.SHIFT_FACTOR);
1217                                 sprite.vx = 1 << GameSprite.SHIFT_FACTOR;
1218                         }
1219 
1220                         int ty = Math.abs(sprite.x % 360);
1221                         sprite.vy = (- sin[ty]) >> 5;
1222                         
1223                         if ( (sprite.y < ((canvasHeight-Level.TILE_SIZE*5) << GameSprite.SHIFT_FACTOR)) && ((sprite.vx < 0 && sprite.x > player.x) || (sprite.vx > 0 && sprite.x < player.x)) && (sprite.y < player.y) )
1224                                 sprite.y += 2 << GameSprite.SHIFT_FACTOR;
1225                         if ( (sprite.y > (Level.TILE_SIZE << GameSprite.SHIFT_FACTOR)) && ((sprite.vx < 0 && sprite.x < player.x) || (sprite.vx > 0 && sprite.x > player.x) || sprite.y > player.y))
1226                                 sprite.y -= 1 << GameSprite.SHIFT_FACTOR;
1227                         
1228                         if (global_frame_counter % 50 == 0)
1229                         {
1230                                 shootEnemyFireTowardPlayer(sprite, Level.SPRITE_ID_FIRE3, (byte) 2);
1231                                 sprite.fire_cooldown_frames_counter = 0;
1232                         }
1233 
1234                         // waiting closed
1235                         if (boss2_closed_counter > 0)
1236                                 boss2_closed_counter--;
1237 
1238                         // start opening
1239                         if (boss2_closed_counter == 0)
1240                         {
1241                                 boss2_closed_counter--;
1242                                 boss2_open_counter = 0;
1243                                 boss2_open_dir = 1;
1244                         }
1245 
1246                         // opening
1247                         if ( (boss2_closed_counter == -1) && (boss2_open_dir > 0) && (boss2_open_counter < BOSS2_OPEN_COUNTER_MAX) &&
1248                                         boss2_stay_open_counter == -1)
1249                         {
1250                                 boss2_open_counter = (byte) (boss2_open_counter + boss2_open_dir);
1251                         }
1252                         
1253                         // closing
1254                         if ( (boss2_closed_counter == -1) && (boss2_open_dir < 0) && (boss2_open_counter > 0) &&
1255                                         boss2_stay_open_counter == -1)
1256                         {
1257                                 boss2_open_counter = (byte) (boss2_open_counter + boss2_open_dir);
1258                         }
1259 
1260                         // stay open for a while
1261                         if (boss2_open_counter == BOSS2_OPEN_COUNTER_MAX && boss2_stay_open_counter == -1)
1262                         {
1263                                 boss2_stay_open_counter = BOSS2_STAY_OPEN_COUNTER_MAX;
1264                         }
1265                         if ( boss2_stay_open_counter > 0)
1266                         {
1267                                 boss2_stay_open_counter--;
1268                         }
1269                         // start closing
1270                         if ( boss2_stay_open_counter == 0)
1271                         {
1272                                 boss2_open_dir = -1;
1273                                 boss2_stay_open_counter--;
1274                         }
1275                         
1276                         if (boss2_open_dir == -1 && boss2_stay_open_counter == -1 && boss2_open_counter == 0)
1277                         {
1278                                 boss2_open_counter = 0;
1279 
1280                                 boss2_closed_counter = BOSS2_CLOSED_COUNTER_MAX;
1281                                 boss2_open_dir = 0;
1282                         }
1283                         
1284                         if (boss2_open_counter == BOSS2_OPEN_COUNTER_MAX 
1285                                         && boss2_stay_open_counter < BOSS2_STAY_OPEN_COUNTER_MAX/2
1286                                         && sprite.fire_cooldown_frames_counter == 0)
1287                         {
1288                                 GameSprite new_fire;
1289                                 new_fire = new GameSprite(Level.SPRITE_ID_FIRE2);
1290                                 new_fire.frameId = 1;
1291                                 new_fire.x = sprite.x + ((sprite.w - 5 - new_fire.w) << GameSprite.SHIFT_FACTOR);
1292                                 new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1293                                 new_fire.vx = 0;
1294                                 new_fire.vy = sprite.vy + FIRE_VELOCITY/2;
1295                                 enemyFireSprites.addElement(new_fire);
1296 
1297                                 new_fire = new GameSprite(Level.SPRITE_ID_FIRE2);
1298                                 new_fire.frameId = 1;
1299                                 new_fire.x = sprite.x + (5 << GameSprite.SHIFT_FACTOR);
1300                                 new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1301                                 new_fire.vx = 0;
1302                                 new_fire.vy = sprite.vy + FIRE_VELOCITY/2;
1303                                 enemyFireSprites.addElement(new_fire);
1304                                 
1305                                 sprite.fire_cooldown_frames_counter = 4;
1306                         }
1307                         
1308                         break;
1309                 }
1310                 
1311                 // move the sprite
1312                 sprite.x += sprite.vx;
1313                 sprite.y += sprite.vy;
1314 
1315                 if (sprite.fire_cooldown_frames_counter > 0)
1316                         sprite.fire_cooldown_frames_counter--;
1317         }
1318 
1319         public GameSprite shootEnemyFire(GameSprite sprite, byte fire_sprite_id, byte fire_sprite_frame_id)
1320         {
1321                 GameSprite new_fire = null;
1322                 if (enemyFireSprites.size() < MAX_ENEMY_FIRE && sprite.fire_cooldown_frames_counter <= 0)
1323                 {
1324 //                      System.out.println("adding fire sprite ... ");
1325                         new_fire = new GameSprite(fire_sprite_id);
1326                         new_fire.frameId = fire_sprite_frame_id;
1327                         new_fire.x = sprite.x + (sprite.w / 2 << GameSprite.SHIFT_FACTOR);
1328                         new_fire.y = sprite.y + (sprite.h << GameSprite.SHIFT_FACTOR);
1329                         new_fire.vx = 0;
1330                         new_fire.vy = sprite.vy + FIRE_VELOCITY/2;
1331                         enemyFireSprites.addElement(new_fire);
1332 
1333                         sprite.fire_cooldown_frames_counter = ENEMY_FIRE_COOLDOWN_WAIT_FRAMES;
1334                         
1335                 }
1336                 return new_fire;
1337         }
1338         public GameSprite shootEnemyFireTowardPlayer(GameSprite sprite, byte fire_sprite_id, byte fire_sprite_frame_id)
1339         {
1340                 GameSprite new_fire = shootEnemyFire(sprite, fire_sprite_id, fire_sprite_frame_id);
1341                 if (new_fire != null)
1342                 {
1343                         int pdx = player.x - new_fire.x;
1344                         int pdy = player.y - new_fire.y;
1345                         
1346                         // we dont have a tangens function (yet!), so for now this will do...
1347                         int approx_dist = Math.abs(pdx) + Math.abs(pdy);
1348                         int approx_velocity_step = approx_dist / 40;
1349                         new_fire.vx = pdx / approx_velocity_step;
1350                         new_fire.vy = pdy / approx_velocity_step;
1351                 }
1352                 
1353                 return new_fire;
1354         }
1355         
1356         public void updatePlayerSprite()
1357         {
1358                 //  nuke
1359                 if (player_nuke_counter == PLAYER_NUKE_COUNTER_MAX)
1360                 {
1361                         // activate nuke, destroy all visible enemy sprites
1362                         int i = Level.enemySprites.size() - 1;
1363                         while (i >= 0 )
1364                         {
1365                                 GameSprite enemy = (GameSprite) Level.enemySprites.elementAt(i);
1366                                 
1367                                 if ( enemy.visible )
1368                                 {
1369                                         System.out.println("destroying opponent: "+i+" / "+Level.enemySprites.size());
1370                                         enemy.energy = 0;
1371                                         addExplosion(enemy);
1372                                 }
1373                                 i--;
1374                         }
1375                 }
1376                 if (player_nuke_counter > 0)
1377                 {
1378                         player_nuke_counter--;
1379                 }
1380                 
1381                 // move player with level scroll
1382                 player.y += Level.tiles_scroll_vy;
1383 
1384                 if (player_gameover_explosion_counter > 0)
1385                 {
1386                         player_gameover_explosion_counter--;
1387                 }
1388                 else
1389                 {
1390                         if (player.energy <= 0)
1391                         {
1392                                 player_gameover_explosion_counter = PLAYER_GAMEOVER_EXPLOSION_COUNTER_MAX;
1393                         }
1394 
1395                         // move player sprite on command, and check player <-> screen edge collision
1396                         if (command_up)
1397                         {
1398                                 player.y -= player.vy;
1399                                 if (player.y < Level.tiles_scroll_y)
1400                                         player.y = Level.tiles_scroll_y;
1401                         }
1402                         if (command_down)
1403                         {       
1404                                 player.y += player.vy;
1405                                 // level edge collision
1406                                 if (player.y - Level.tiles_scroll_y > ((canvasHeight - player.h) << GameSprite.SHIFT_FACTOR))
1407                                         player.y = Level.tiles_scroll_y + ((canvasHeight - player.h) << GameSprite.SHIFT_FACTOR);
1408                         }
1409                         player.frameId = SPRITE_FRAME_PLAYER_CENTER;
1410                         if (command_left)
1411                         {       
1412                                 player.x -= player.vx;
1413                                 if (player.x < Level.tiles_scroll_x)
1414                                         player.x = Level.tiles_scroll_x;
1415                                 player.frameId = SPRITE_FRAME_PLAYER_LEFT;
1416                         }
1417                         if (command_right)
1418                         {       
1419                                 player.x += player.vx;
1420                                 if (player.x - Level.tiles_scroll_x > ((canvasWidth - player.w) << GameSprite.SHIFT_FACTOR))
1421                                         player.x = Level.tiles_scroll_x + ((canvasWidth - player.w) << GameSprite.SHIFT_FACTOR);
1422                                 player.frameId = SPRITE_FRAME_PLAYER_RIGHT;
1423                         }
1424                         if (command_fire)
1425                         {
1426                                 if (player.fire_cooldown_frames_counter <= 0)
1427                                 {
1428                                         GameSprite fire = new GameSprite(Level.SPRITE_ID_FIRE1);
1429                                         fire.x = player.x + ((player.w/2 - fire.w/2) << GameSprite.SHIFT_FACTOR);
1430                                         fire.y = player.y;
1431                                         fire.vy = -FIRE_VELOCITY + Level.tiles_scroll_vy;
1432                                         playerFireSprites.addElement(fire);
1433         
1434                                         player.fire_cooldown_frames_counter = PLAYER_FIRE_COOLDOWN_WAIT_FRAMES;
1435                                 }
1436                         }
1437                         if (player.fire_cooldown_frames_counter > 0)
1438                                 player.fire_cooldown_frames_counter--;
1439                         if ( god_mode )
1440                                 player.fire_cooldown_frames_counter -= 2;
1441                 }
1442         }
1443 
1444         public void doCollision()
1445         {
1446                 int i = Level.enemySprites.size() - 1;
1447                 while (i >= 0 )
1448                 {
1449                         GameSprite enemy = (GameSprite) Level.enemySprites.elementAt(i);
1450                         
1451                         if ( enemy.visible )
1452                         {
1453                                 // check player <-> enemy collision
1454                                 if (player.collidesWith(enemy))
1455                                 {
1456                                         // add explosion
1457                                         addExplosion(enemy);
1458                                         addExplosion(player);
1459         
1460                                         // player loses energy
1461                                         if ( !god_mode )
1462                                                 player.energy -= enemy.damage;
1463                                         
1464                                         // level boss does not take damage from colliding with player
1465                                         if (enemy != Level.boss)
1466                                                 enemy.energy -= player.damage;
1467         
1468                                 }
1469                                 
1470                                 // check the player fire sprites <-> enemy collision
1471                                 int j = playerFireSprites.size() - 1;
1472                                 while (j >= 0)
1473                                 {
1474                                         GameSprite fire = (GameSprite) playerFireSprites.elementAt(j);
1475                                         if (fire.collidesWith(enemy))
1476                                         {
1477                                                 if (enemy.spriteId != Level.SPRITE_ID_BOSS2 || (boss2_open_counter > 0))
1478                                                 {
1479                                                         enemy.energy -= fire.damage;
1480                                                 
1481                                                         // add explosions
1482                                                         addExplosion(enemy);
1483                                                 }
1484                                                 // destroy player fire
1485                                                 playerFireSprites.removeElementAt(j);
1486                                                 j--;
1487                                         }
1488                                         j--;
1489                                 }
1490                                 // remove dead enemies
1491                                 if (enemy.energy <= 0)
1492                                 {
1493                                         Level.enemySprites.removeElementAt(i);
1494                                         i--;
1495                                         // increase player score
1496                                         player_score += enemy.score;
1497         
1498                                         // if boss sprite
1499                                         if (enemy.spriteId == Level.SPRITE_ID_BOSS1 || enemy.spriteId == Level.SPRITE_ID_BOSS2)
1500                                         {
1501                                                 boss_dead_explosion_counter = BOSS_DEAD_EXPLOSION_COUNTER_MAX;
1502                                         }
1503                                 }
1504                         }
1505                         i--;
1506                 }
1507                 // check the enemy fire sprites <-> player collision
1508                 int j = enemyFireSprites.size() - 1;
1509                 while (j >= 0)
1510                 {
1511                         GameSprite fire = (GameSprite) enemyFireSprites.elementAt(j);
1512                         if (fire.collidesWith(player))
1513                         {
1514                                 if ( !god_mode ) {
1515                                         player.energy -= fire.damage;
1516                                         System.out.println("player.energy "+ player.energy);
1517                                 }
1518                                 
1519                                 // add explosions
1520                                 addExplosion(player);
1521 
1522                                 // destroy enemy fire
1523                                 enemyFireSprites.removeElementAt(j);
1524                                 j--;
1525                         }
1526                         j--;
1527                 }
1528         }
1529 
1530         public void updatePlayerFireSprites()
1531         {
1532                 for (int i=0; i < playerFireSprites.size(); i++)
1533                 {
1534                         GameSprite fire = (GameSprite) playerFireSprites.elementAt(i);
1535                         fire.y += fire.vy;
1536                         
1537                         // destroy player fire when out of screen
1538                         if ( (fire.y + (fire.h << GameSprite.SHIFT_FACTOR)) < Level.tiles_scroll_y)
1539                         {
1540                                 playerFireSprites.removeElementAt(i);
1541                                 // only increase counter, if not removed from list
1542                                 i--;
1543                         }
1544                 }
1545         }
1546 
1547         public void updateEnemyFireSprites()
1548         {
1549                 for (int i=0; i < enemyFireSprites.size(); i++)
1550                 {
1551 //                      System.out.println("updating enemy fire sprite...");
1552                         
1553                         GameSprite fire = (GameSprite) enemyFireSprites.elementAt(i);
1554                         fire.x += fire.vx;
1555                         fire.y += fire.vy;
1556                         
1557                         // destroy enemy fire when out of screen
1558                         if ( fire.y > Level.tiles_scroll_y + (canvasHeight << GameSprite.SHIFT_FACTOR))
1559                         {
1560                                 enemyFireSprites.removeElementAt(i);
1561                                 // only increase counter, if not removed from list
1562                                 i--;
1563                         }
1564                 }
1565         }
1566 
1567         public void updateExplosionSprites()
1568         {
1569                 for (int i=0; i < explosionSprites.size(); i++)
1570                 {
1571                         GameSprite exp = (GameSprite) explosionSprites.elementAt(i);
1572                         
1573                         // animate explosion!
1574                         exp.frameId++;
1575                         
1576                         if (exp.frameId > exp.frameIdMax)
1577                         {
1578                                 explosionSprites.removeElementAt(i);
1579                                 // only increase counter, if not removed from list
1580                                 i--;
1581                         }
1582                 }
1583                 // create a big bada boom player gameover explosion
1584                 //  7 - max explosion frames
1585                 //  2 - add an explosion every 2nd frame
1586                 if (player_gameover_explosion_counter > 7 &&
1587                                 player_gameover_explosion_counter % 2 == 0
1588                                 )
1589                 {
1590                         GameSprite new_exp = addExplosion(player);
1591                         new_exp.x += random.nextInt() % (player.w << GameSprite.SHIFT_FACTOR);
1592                         new_exp.y += random.nextInt() % (player.h << GameSprite.SHIFT_FACTOR);
1593                 }
1594                 // create a big bada boom boss gameover explosion
1595                 //  7 - max explosion frames
1596                 //  2 - add an explosion every 2nd frame
1597                 if (boss_dead_explosion_counter > 7 &&
1598                                 boss_dead_explosion_counter % 2 == 0
1599                                 )
1600                 {
1601                         GameSprite new_exp = addExplosion(Level.boss);
1602                         new_exp.x += random.nextInt() % (Level.boss.w << GameSprite.SHIFT_FACTOR);
1603                         new_exp.y += random.nextInt() % (Level.boss.h << GameSprite.SHIFT_FACTOR);
1604                 }
1605         }
1606 
1607         public static void loadImages()
1608         {
1609                 try {
1610                         
1611                         spriteImages = new Image[SPRITE_IMAGE_MAX]; 
1612                         spriteImages[SPRITE_IMAGE_PLAYER] = Image.createImage("/p.png"); 
1613                         spriteImages[SPRITE_IMAGE_FIRE] = Image.createImage("/fire.png"); 
1614                         spriteImages[SPRITE_IMAGE_BOSS1] = Image.createImage("/boss1.png"); 
1615                         spriteImages[SPRITE_IMAGE_BOSS2] = Image.createImage("/boss2.png"); 
1616                         spriteImages[SPRITE_IMAGE_ENEMY1] = Image.createImage("/e1.png"); 
1617                         spriteImages[SPRITE_IMAGE_ENEMY2] = Image.createImage("/e2.png"); 
1618                         spriteImages[SPRITE_IMAGE_ENEMY3] = Image.createImage("/e3.png"); 
1619                         spriteImages[SPRITE_IMAGE_ENEMY4] = Image.createImage("/e4.png"); 
1620                         spriteImages[SPRITE_IMAGE_EXPLOSION] = Image.createImage("/exp.png"); 
1621         
1622                         tileImage = Image.createImage("/t04.png");
1623                         
1624                         imgBackground = Image.createImage("/bg.png");
1625                         
1626                 } catch (Exception e)   {};
1627         }
1628 
1629         public static GameSprite addExplosion(GameSprite exp_spr)
1630         {
1631                 // add explosion
1632                 GameSprite exp = new GameSprite(Level.SPRITE_ID_EXPLOSION);
1633                 // center the explosion position on the exploded sprite
1634                 exp.x = exp_spr.x + ((exp_spr.w/2 - exp.w/2) << GameSprite.SHIFT_FACTOR);
1635                 exp.y = exp_spr.y + ((exp_spr.h/2 - exp.h/2) << GameSprite.SHIFT_FACTOR);
1636                 exp.vx = exp_spr.vx;
1637                 exp.vy = exp_spr.vy;
1638                 explosionSprites.addElement(exp);
1639                 
1640                 if (exp_spr.energy > 0)
1641                         exp.frameId = GameSprite.EXPLOSION_FRAME_SMOKE_START;
1642                 
1643                 return exp;
1644         }
1645         
1646         public void hideNotify()
1647         {
1648                 // hideNotify method of Canvas is called on external events, which hide the Canvas
1649                 // this method can be used to handle such events (battery warnings, incoming phone calls...)
1650                 if (mode == MODE_GAME)
1651                 {
1652                         mode = MODE_MENU;
1653                         menuScreen = MENU_SCR_PAUSE_GAME;
1654                         stopMusic();
1655                 }
1656         }
1657 
1658         public void showNotify()
1659         {
1660                 if (musicOn)
1661                         playMusic();
1662         }
1663 
1664 
1665     // loads the highscores from RMS - the internal phone database
1666         // also saves default scores, if no scores exist.
1667         public static void loadHighscoreFromRMS()
1668         {
1669                 try
1670                 {
1671                         db = RecordStore.openRecordStore(SCORE_DB_NAME, true);
1672 
1673                         byte[] score_data = null;
1674                         // initialize scores
1675                         if (db.getNumRecords() == 0)
1676                         {
1677                                 // add record with initial default scores
1678                                 score_data = getHighscoreData();
1679                                 db.addRecord(score_data, 0, score_data.length);
1680                         }
1681                         // load highscore
1682                         score_data = db.getRecord(1);
1683                         ByteArrayInputStream in = new ByteArrayInputStream(score_data);
1684                         DataInputStream dis = new DataInputStream(in);
1685                         for (byte i = 0; i < MAX_SCORES; i++)
1686                         {
1687                                 hiScores[i] = dis.readInt();
1688                                 hiNames[i] = dis.readUTF();
1689                         }
1690                         dis.close();
1691                         in.close();
1692                         db.closeRecordStore();
1693                         dis = null;
1694                         in = null;
1695                         db = null;
1696 //                      System.gc();
1697                 } catch (Exception ex) {
1698                         ex.printStackTrace();
1699                 }
1700         }
1701 
1702         // prepares data in a byte array, ready for saving to a RMS record
1703         public static byte[] getHighscoreData() throws IOException
1704         {
1705                 ByteArrayOutputStream out = new ByteArrayOutputStream();
1706                 DataOutputStream dos = new DataOutputStream(out);
1707                 for (byte i = 0; i < MAX_SCORES; i++)
1708                 {
1709                         dos.writeInt(hiScores[i]);
1710                         dos.writeUTF(hiNames[i]);
1711                 }
1712                 dos.close();
1713                 out.close();
1714 
1715                 return out.toByteArray();
1716         }
1717 
1718         // saves highscores to RMS
1719         public static void saveHighscores()
1720         {
1721                 try
1722                 {
1723                         db = RecordStore.openRecordStore(SCORE_DB_NAME, true);
1724 
1725                         byte[] data = getHighscoreData();
1726 
1727                         db.setRecord(1, data, 0, data.length);
1728                         db.closeRecordStore();
1729                 } catch (Exception ex) {
1730                         ex.printStackTrace();
1731                 }
1732         }
1733 
1734         // returns -1 if not qualified, highscore position otherwise
1735         public static int isQualified(int score)
1736         {
1737                 for (byte i = 0; i < MAX_SCORES; i++)
1738                         if (hiScores[i] < score)
1739                                 return i;
1740                 return -1;
1741         }
1742 
1743         // add a score to the scores array and to the rms
1744         public static void addHighscore(int score, String name)
1745         {
1746                 int i = isQualified(score);
1747                 
1748                 // move others down 1 place
1749                 for (byte k = (byte) (MAX_SCORES - 1); k > i; k--) {
1750                         hiScores[k] = hiScores[k - 1];
1751                         hiNames[k] = hiNames[k - 1];
1752                 }
1753                 // insert score
1754                 hiScores[i] = score;
1755                 hiNames[i] = name;
1756 
1757                 saveHighscores();
1758                 return;
1759         }
1760 
1761         public static final short SIN_FACTOR = 1024;
1762         public static final short[] sin = {
1763         0, 18, 36, 54, 71, 89, 107, 125, 143, 160, 
1764         178, 195, 213, 230, 248, 265, 282, 299, 316, 333, 
1765         350, 367, 384, 400, 416, 433, 449, 465, 481, 496, 
1766         512, 527, 543, 558, 573, 587, 602, 616, 630, 644, 
1767         658, 672, 685, 698, 711, 724, 737, 749, 761, 773, 
1768         784, 796, 807, 818, 828, 839, 849, 859, 868, 878, 
1769         887, 896, 904, 912, 920, 928, 935, 943, 949, 956, 
1770         962, 968, 974, 979, 984, 989, 994, 998, 1002, 1005, 
1771         1008, 1011, 1014, 1016, 1018, 1020, 1022, 1023, 1023, 1024, 
1772         1024, 1024, 1023, 1023, 1022, 1020, 1018, 1016, 1014, 1011, 
1773         1008, 1005, 1002, 998, 994, 989, 984, 979, 974, 968, 
1774         962, 956, 949, 943, 935, 928, 920, 912, 904, 896, 
1775         887, 878, 868, 859, 849, 839, 828, 818, 807, 796, 
1776         784, 773, 761, 749, 737, 724, 711, 698, 685, 672, 
1777         658, 644, 630, 616, 602, 587, 573, 558, 543, 527, 
1778         512, 496, 481, 465, 449, 433, 416, 400, 384, 367, 
1779         350, 333, 316, 299, 282, 265, 248, 230, 213, 195, 
1780         178, 160, 143, 125, 107, 89, 71, 54, 36, 18, 
1781         0, -18, -36, -54, -71, -89, -107, -125, -143, -160, 
1782         -178, -195, -213, -230, -248, -265, -282, -299, -316, -333, 
1783         -350, -367, -384, -400, -416, -433, -449, -465, -481, -496, 
1784         -512, -527, -543, -558, -573, -587, -602, -616, -630, -644, 
1785         -658, -672, -685, -698, -711, -724, -737, -749, -761, -773, 
1786         -784, -796, -807, -818, -828, -839, -849, -859, -868, -878, 
1787         -887, -896, -904, -912, -920, -928, -935, -943, -949, -956, 
1788         -962, -968, -974, -979, -984, -989, -994, -998, -1002, -1005, 
1789         -1008, -1011, -1014, -1016, -1018, -1020, -1022, -1023, -1023, -1024, 
1790         -1024, -1024, -1023, -1023, -1022, -1020, -1018, -1016, -1014, -1011, 
1791         -1008, -1005, -1002, -998, -994, -989, -984, -979, -974, -968, 
1792         -962, -956, -949, -943, -935, -928, -920, -912, -904, -896, 
1793         -887, -878, -868, -859, -849, -839, -828, -818, -807, -796, 
1794         -784, -773, -761, -749, -737, -724, -711, -698, -685, -672, 
1795         -658, -644, -630, -616, -602, -587, -573, -558, -543, -527, 
1796         -512, -496, -481, -465, -449, -433, -416, -400, -384, -367, 
1797         -350, -333, -316, -299, -282, -265, -248, -230, -213, -195,
1798         -178, -160, -143, -125, -107, -89, -54, -36, -18, 0
1799         };
1800 
1801 
1802         public static boolean musicOn = true;
1803 //      public static javax.microedition.media.Player musicPlayer;
1804 
1805         public static void loadMusic()
1806         {
1807 //              InputStream inputstream;
1808 //
1809 //              try 
1810 //              {
1811 //                      inputstream = new Object().getClass().getResourceAsStream("/music.mid");
1812 //                      musicPlayer = Manager.createPlayer(inputstream, "audio/midi");
1813 //                      musicPlayer.realize();
1814 //                      musicPlayer.setLoopCount(-1);
1815 //              } 
1816 //              catch (Exception e) {
1817 //              }
1818         }
1819 
1820         public static void playMusic()
1821         {
1822 //              try 
1823 //              {
1824 //                      VolumeControl volume = (VolumeControl) musicPlayer
1825 //                                      .getControl("javax.microedition.media.control.VolumeControl");
1826 //                      volume.setLevel(20);
1827 //
1828 //                      musicPlayer.realize();
1829 //                      musicPlayer.start();
1830 //              } 
1831 //              catch (Exception e) {
1832 //              }
1833         }
1834 
1835         public static void stopMusic() {
1836 //              try 
1837 //              {
1838 //                      if (musicPlayer != null) {
1839 //                              musicPlayer.stop();
1840 //                              musicPlayer.setMediaTime(-1);
1841 //                      }
1842 //              } 
1843 //              catch (Exception e) {
1844 //              }
1845 //
1846         }
1847 
1848 }
1849