C:\eclipse\workspace\Epsilon_01\src\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 
 13 import java.util.*;
 14 import javax.microedition.lcdui.*;
 15 
 16 import com.nokia.mid.ui.FullCanvas;
 17 
 18 class GameCanvas extends FullCanvas implements Runnable
 19 //class GameCanvas extends Canvas implements Runnable
 20 {
 21         private final Game midlet;
 22         
 23         public static int canvasWidth;
 24         public static int canvasHeight;
 25 
 26         public static boolean gameRunning;
 27 
 28         public static final int SOFTKEY_1 = -6;
 29         public static final int SOFTKEY_2 = -7;
 30         
 31         public static boolean menu_command_1;
 32         public static boolean menu_command_2;
 33         
 34         public static boolean command_up;
 35         public static boolean command_down;
 36         public static boolean command_left;
 37         public static boolean command_right;
 38         public static boolean command_fire;
 39         
 40         public static byte mode;
 41         public static final byte MODE_INTRO = 0;
 42         public static final byte MODE_GAME = 1;
 43         public static final byte MODE_MENU = 2;
 44         
 45         public static int loadingCounter;
 46         
 47         public static Image imgIntro;
 48         public static Image imgBackground;
 49         public static Image imgPlayer;
 50         public static Image imgPlayerFire;
 51         public static Image imgEnemy;
 52 
 53         public static int menuScreen;
 54         public static final byte MENU_SCR_MAIN = 0; 
 55         public static final byte MENU_SCR_TEXT_ABOUT = 1;
 56         public static final byte MENU_SCR_TEXT_HELP = 2;
 57         public static final byte MENU_SCR_TEXT_GAME_OVER = 3;
 58 
 59         public static int menuSelectedOption;
 60         public static final byte MENU_OPTION_MAIN_NEW_GAME = 0;
 61         public static final byte MENU_OPTION_MAIN_ABOUT = 1;
 62         public static final byte MENU_OPTION_MAIN_HELP = 2;
 63         public static final byte MENU_OPTION_MAIN_MAX = 2;
 64         
 65         public static final String[] menuScreenMainOptions = { "New game", "About", "Help"};
 66         
 67         public static final String[][] menuScreensTextLines = {
 68                 { "" },
 69                 { "About", "", "Epsilon v0.1", "(c) 2005 zigah.", "GFX by Geci." },
 70                 { "Help", "", "Press LEFT, RIGHT, ", "UP or DOWN", "to move and", "FIRE to shoot." },
 71                 { "Game Over", "", "Well done!"},
 72         };
 73         
 74         public static GameSprite player;
 75         public static GameSprite player_fire;
 76         public static int player_score;
 77 
 78         public static final byte MAX_ENERGY_PLAYER = 100;
 79         public static final byte MAX_ENERGY_PLAYER_FIRE = 10;
 80         public static final byte MAX_ENERGY_ENEMY = 10;
 81         
 82         public static Vector enemySprites;
 83         
 84         public static byte max_enemy_sprites = 3;
 85         
 86         public static int space_scroll_y;
 87         public static int space_scroll_vy;
 88         
 89         public static Random random = new Random();
 90         
 91         GameCanvas(Game midlet)
 92         {
 93                 this.midlet = midlet;
 94 
 95                 canvasWidth = this.getWidth();
 96                 canvasHeight = this.getHeight();
 97 
 98                 loadingCounter = 0;
 99                 menuScreen = MENU_SCR_MAIN;
100                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
101                 mode = MODE_INTRO;
102                 gameRunning = true;
103         }
104 
105         public void run()
106         {
107                 while(gameRunning)
108                 {
109                         repaint();
110                         serviceRepaints();
111 
112                         switch (mode) {
113                         case MODE_INTRO:
114 
115                                 try
116                                 {
117                                         if (loadingCounter == 0)
118                                         {
119                                                 imgIntro = Image.createImage("/intro.png");
120                                         }
121                                         else if (loadingCounter == 1)
122                                         {
123                                                 imgPlayer = Image.createImage("/p.png");
124                                         }
125                                         else if (loadingCounter == 2)
126                                         {
127                                                 imgPlayerFire = Image.createImage("/pf.png");
128                                         }
129                                         else if (loadingCounter == 3)
130                                         {
131                                                 imgEnemy = Image.createImage("/e.png");
132                                         }
133                                         else if (loadingCounter == 4)
134                                         {
135                                                 imgBackground = Image.createImage("/bg.png");
136                                         }
137                                         else
138                                         {
139                                                 // view the intro splash image for a while
140                                                 // it would be better to let user skip intro by pressing a key
141                                                 // but, in a full game project, loading would take forever, anyway, so...
142                                                 try     {
143                                                         Thread.sleep(1000);
144                                                 } catch (Exception e) {
145                                                         e.printStackTrace();
146                                                 }
147                                                 // switch mode
148                                                 mode = MODE_MENU;
149                                         }
150                                         loadingCounter++;
151                                 }
152                                 catch (Exception e)     {
153                                         // ignore loading exception     
154                                 };
155                                 break;
156                                 
157                         case MODE_MENU:
158 
159                                 if (command_up) {
160                                         command_up = false;
161                                         menuSelectedOption--;
162                                         if (menuSelectedOption < 0)
163                                                 menuSelectedOption = 0;
164                                 }
165                                 if (command_down) {
166                                         command_down = false;
167                                         menuSelectedOption++;
168                                         if ((menuScreen == MENU_SCR_MAIN) &&
169                                                         (menuSelectedOption > MENU_OPTION_MAIN_MAX))
170                                                 menuSelectedOption = MENU_OPTION_MAIN_MAX;
171                                 }
172                                 
173                                 if (menu_command_1)
174                                 {
175                                         menu_command_1 = false;
176                                         if (menuScreen == MENU_SCR_MAIN)
177                                         {
178                                                 switch(menuSelectedOption)
179                                                 {
180                                                 case MENU_OPTION_MAIN_NEW_GAME:
181                                                         startGame();
182                                                         break;
183                                                         
184                                                 case MENU_OPTION_MAIN_ABOUT:
185                                                         menuScreen = MENU_SCR_TEXT_ABOUT;
186                                                         break;
187                                                         
188                                                 case MENU_OPTION_MAIN_HELP:
189                                                         menuScreen = MENU_SCR_TEXT_HELP;
190                                                         break;
191                                                 }
192                                         } else {
193                                                 // all other menu screens go to main menu when OK is selected
194                                                 menuScreen = MENU_SCR_MAIN;
195                                                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
196                                         }
197                                 }
198                                 if (menu_command_2)
199                                 {
200                                         menu_command_2 = false;
201                                         
202                                         // exit when in main menu
203                                         if (menuScreen == MENU_SCR_MAIN)
204                                                 midlet.exitRequested();
205                                 }
206                                 
207                                 // delay, so the keypress events get their turn...
208                                 try     {
209                                         Thread.sleep(40);
210                                 } catch (Exception e) {
211                                         e.printStackTrace();
212                                 }
213                                 break;
214                                 
215                         case MODE_GAME:
216 
217                                 // update space background
218                                 space_scroll_y += space_scroll_vy;
219                                 
220                                 updateEnemySprites();
221 
222                                 updatePlayerSprite();
223                                 
224                                 updatePlayerFireSprite();
225                                 
226                                 // check player <-> enemy <-> player fire collision
227                                 doCollision();
228                                 
229                                 // check for game end
230                                 if (menu_command_2 || player.energy == 0)
231                                 {
232                                         menu_command_2 = false;
233                                         // on softkey_2 end game and return to main menu..
234                                         endGame();
235                                 }
236 
237                                 // delay
238                                 try     {
239                                         Thread.sleep(40);
240                                 } catch (Exception e) {
241                                         e.printStackTrace();
242                                 }
243                                 break;
244                         }
245                 }
246         }
247         
248         public void paint(Graphics g)
249         {
250                 switch(mode)
251                 {
252                 case MODE_INTRO:
253 
254                         g.setColor(0x000000);
255                         g.fillRect(0, 0, canvasWidth, canvasHeight);
256                         if (imgIntro != null) {
257                                 g.drawImage(imgIntro, canvasWidth/2, canvasHeight/2, Graphics.VCENTER | Graphics.HCENTER);
258                         }
259 
260 //                      g.setColor(0xFFFFFF);
261 //                      g.drawString(""+loadingCounter,0,0,Graphics.LEFT | Graphics.TOP);
262 
263                         break;
264                         
265                 case MODE_MENU:
266 
267                         paintSpaceBackground(g);
268 
269                         switch(menuScreen)
270                         {
271                         case MENU_SCR_MAIN:
272                                 paintMainMenu(g);
273                                 break;
274                                 
275                         case MENU_SCR_TEXT_ABOUT:
276                         case MENU_SCR_TEXT_HELP:
277                         case MENU_SCR_TEXT_GAME_OVER:
278                                 paintTextMenu(g, menuScreen);
279                                 break;
280                         }
281                         break;
282                         
283                 case MODE_GAME:
284                         
285                         paintSpaceBackground(g);
286                         
287                         paintSprite( g, player );
288                         
289                         if (player_fire != null)
290                                 paintSprite( g, player_fire );
291                         
292                         for (int i=0; i < enemySprites.size(); i++)
293                         {
294                                 paintSprite( g, (GameSprite) enemySprites.elementAt(i) );
295                         }
296                         
297                         paintStatusBars(g);
298                         
299                         break;          
300                 }
301         }
302         
303         public void keyPressed(int key)
304         {
305                 switch(key) {
306                 case SOFTKEY_1:
307                         menu_command_1 = true;
308                         break;
309                         
310                 case SOFTKEY_2:
311                         menu_command_2 = true;
312                         break;
313                 }
314                 
315                 int game_action = getGameAction(key);
316                 
317                 switch(game_action)
318                 {
319                 case UP:
320                         command_up = true;
321                         break;
322 
323                 case DOWN:
324                         command_down = true;
325                         break;
326 
327                 case LEFT:
328                         command_left = true;
329                         break;
330 
331                 case RIGHT:
332                         command_right = true;
333                         break;
334 
335                 case FIRE:
336                         command_fire = true;
337                         menu_command_1 = true;
338                         break;
339                 }
340         }
341         
342         public void keyReleased(int key)
343         {
344                 int game_action = getGameAction(key);
345 
346                 switch(game_action)
347                 {
348                 case UP:
349                         command_up = false;
350                         break;
351 
352                 case DOWN:
353                         command_down = false;
354                         break;
355 
356                 case LEFT:
357                         command_left = false;
358                         break;
359 
360                 case RIGHT:
361                         command_right = false;
362                         break;
363 
364                 case FIRE:
365                         command_fire = false;
366                         break;
367                 }
368         }
369 
370         public void paintSpaceBackground(Graphics g)
371         {
372                 // fill the vast space
373                 g.setColor(0x000000);
374                 g.fillRect(0, 0, canvasWidth, canvasHeight);
375                 
376                 // init scrolling background image tiling
377                 int x = 0;
378                 int y = space_scroll_y % imgBackground.getHeight() - imgBackground.getHeight();
379 
380                 // image is wide enough, so we only need to tile it in the vertical (y) direction
381                 while (y < canvasHeight)
382                 {
383                         g.drawImage(imgBackground, x, y, Graphics.TOP | Graphics.LEFT);
384                         g.setClip(0, 0, canvasWidth, canvasHeight);
385                 
386                         y += imgBackground.getHeight();
387                 }
388         }
389 
390         public void paintMainMenu(Graphics g)
391         {
392                 // init font
393                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE));
394                 int menu_y = canvasHeight/2 - 45;
395                 for(int i=0; i <= MENU_OPTION_MAIN_MAX; i++)
396                 {
397                         // paint the main menu options
398                         if (i == menuSelectedOption) {
399                                 g.setColor(0xFFCC00);
400                         } else {
401                                 g.setColor(0xFFFFFF);
402                         }
403                         
404                         g.drawString(menuScreenMainOptions[i], canvasWidth/2, menu_y, Graphics.HCENTER | Graphics.TOP);
405                         
406                         menu_y += 30;
407                 }
408                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
409                 g.setColor(0xFFFFFF);
410                 // paint softkey_1 label
411                 g.drawString("Select", 2, canvasHeight-2, Graphics.LEFT | Graphics.BOTTOM);
412                 // paint softkey_2 label
413                 g.drawString("Exit", canvasWidth-2, canvasHeight-2, Graphics.RIGHT | Graphics.BOTTOM);
414         }
415 
416         public void paintTextMenu(Graphics g, int screen)
417         {
418                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
419                 g.setColor(0xFFFFFF);
420                 int text_line_y = 10;
421                 for(int line=0; line < menuScreensTextLines[screen].length; line++)
422                 {
423                         // paint all the lines of text in this menu screen
424                         g.drawString(menuScreensTextLines[screen][line], canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
425                         
426                         text_line_y += 15;
427                 }
428                 if (screen == MENU_SCR_TEXT_GAME_OVER)
429                 {
430                         // print score in the game over screen
431                         text_line_y += 15;
432                         g.drawString("Score: "+ player_score, canvasWidth/2, text_line_y, Graphics.HCENTER | Graphics.TOP);
433                 }
434 
435                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
436                 // paint softkey_1 label
437                 g.drawString("Ok", 1, canvasHeight-1, Graphics.LEFT | Graphics.BOTTOM);
438         }
439 
440         public static void paintSprite(Graphics g, GameSprite spr)
441         {
442                 // paint the sprites image at its coordinates
443                 g.drawImage(spr.img, spr.x, spr.y, Graphics.TOP | Graphics.LEFT);
444         }
445 
446         public static void paintStatusBars(Graphics g)
447         {
448                 int max_energy_bar_width = canvasWidth/2;
449 
450                 // paint the energy bar
451                 g.setColor(0xFFFFFF);
452                 g.drawRect(5, 10, max_energy_bar_width + 1, 4);
453                 g.setColor(0xFFCC00);
454                 g.fillRect(6, 11, player.energy * max_energy_bar_width / player.energyMax, 3);
455                 
456                 // paint the score count
457                 g.setColor(0xFFFFFF);
458                 g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
459                 g.drawString(""+player_score, canvasWidth-4, 8, Graphics.TOP | Graphics.RIGHT);
460         }
461 
462         public void startGame()
463         {
464                 // switch to game mode
465                 mode = MODE_GAME;
466 
467                 // initialize player sprite
468                 player = new GameSprite(imgPlayer, MAX_ENERGY_PLAYER);
469                 player.x = canvasWidth / 2;
470                 player.y = canvasHeight - player.h - player.h/2;
471                 player_score = 0;
472                 
473                 // intialize the scrolling background
474                 space_scroll_y = 0;
475                 space_scroll_vy = 1;
476                 
477                 // initialize the enemy sprites list
478                 enemySprites = new Vector();
479         }
480         
481         public void endGame()
482         {
483                 // back to menu mode, set the game over text screen
484                 mode = MODE_MENU;
485                 menuScreen = MENU_SCR_TEXT_GAME_OVER;
486                 menuSelectedOption = MENU_OPTION_MAIN_NEW_GAME;
487 
488                 // clean up
489                 player = null;
490                 enemySprites = null;
491         }
492 
493         public void updateEnemySprites()
494         {
495                 // check if a new enemy has to be generated
496                 if( enemySprites.size() < max_enemy_sprites )
497                 {
498                         GameSprite new_enemy;
499                         
500                         // create a new enemy
501                         new_enemy = new GameSprite(imgEnemy, MAX_ENERGY_ENEMY);
502 
503                         new_enemy.x = Math.abs(random.nextInt()) % canvasWidth;
504                         new_enemy.y = -new_enemy.h;
505                         
506                         new_enemy.vx = random.nextInt() % 2;
507                         new_enemy.vy = 3 + random.nextInt() % 2;
508 
509                         // add the new enemy to the enemy sprites list
510                         enemySprites.addElement(new_enemy);
511                 }
512 
513                 // move enemy sprites
514                 for (int i=0; i < enemySprites.size(); i++)
515                 {
516                         GameSprite enemy = (GameSprite) enemySprites.elementAt(i);
517 
518                         enemy.x += enemy.vx;
519                         enemy.y += enemy.vy;
520                         
521                         // if enemy is out of screen
522                         if ( (enemy.x > canvasWidth) || (enemy.x+enemy.w < 0) ||
523                                  (enemy.y > canvasHeight) || (enemy.y+enemy.h < 0) )
524                         {
525                                 enemySprites.removeElementAt(i);
526                         }
527                 }
528         }
529 
530         public void updatePlayerSprite()
531         {
532                 // move player sprite on command, and check player <-> screen edge collision
533                 if (command_up)
534                 {
535                         player.y -= player.vy;
536                         if (player.y < 0)
537                                 player.y = 0;
538                 }
539                 if (command_down)
540                 {       
541                         player.y += player.vy;
542                         if (player.y > canvasHeight - player.h)
543                                 player.y = canvasHeight - player.h;
544                 }
545                 if (command_left)
546                 {       
547                         player.x -= player.vx;
548                         if (player.x < 0)
549                                 player.x = 0;
550                 }
551                 if (command_right)
552                 {       
553                         player.x += player.vx;
554                         if (player.x > canvasWidth - player.w)
555                                 player.x = canvasWidth - player.w;
556                 }
557                 if (command_fire)
558                 {
559                         if (player_fire == null)
560                         {
561                                 player_fire = new GameSprite(imgPlayerFire, MAX_ENERGY_PLAYER_FIRE);
562                                 player_fire.x = player.x + player.w/2 - player_fire.w/2;
563                                 player_fire.y = player.y;
564                                 player_fire.vy = -4;
565                         }
566                 }
567         }
568 
569         public void doCollision()
570         {
571                 for (int i=0; i < enemySprites.size(); i++)
572                 {
573                         GameSprite enemy = (GameSprite) enemySprites.elementAt(i);
574                         
575                         // check player <-> enemy collision
576                         if (player.collidesWith(enemy))
577                         {
578                                 // player loses energy
579                                 player.energy -= player.energyMax/4;
580 
581                                 // enemy sprite is destroyed
582                                 enemySprites.removeElementAt(i);
583                         }
584 
585                         if (player_fire != null && player_fire.collidesWith(enemy))
586                         {
587                                 // destroy player fire
588                                 player_fire = null;
589 
590                                 // enemy sprite is destroyed
591                                 enemySprites.removeElementAt(i);
592                                 
593                                 // increase player score
594                                 player_score += 10;
595                         }
596                 }
597         }
598 
599         public void updatePlayerFireSprite()
600         {
601                 if (player_fire != null)
602                 {
603                         player_fire.y += player_fire.vy;
604                         
605                         // destroy player fire when out of screen
606                         if (player_fire.y + player_fire.h < 0)
607                                 player_fire = null;
608                 }
609         }
610 
611 }
612