| C:\__todo__\tecaj.www\src\Epsilon_05\Level.java |
1 /**
2 * Level contains the Level load and paint 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
14 import java.io.*;
15 import java.util.Vector;
16
17 import javax.microedition.lcdui.Graphics;
18
19 class Level
20 {
21
22 public static final byte MAX_LEVELS = 2;
23
24 public static final byte LEVEL_WIDTH = 16;
25 public static final byte LEVEL_HEIGHT = 64;
26
27 public static final byte LEVEL_WIDTH_SHIFT_FACTOR = 4;
28 public static final byte LEVEL_HEIGHT_SHIFT_FACTOR = 6;
29 public static final byte TILE_SIZE_SHIFT_FACTOR = 4;
30
31 public static final byte TILE_SIZE = 16;
32 public static final byte TILES_PER_IMAGE_LINE = 5;
33
34 // space background position and scroll speed
35 public static int space_scroll_y;
36 public static int space_scroll_vy;
37
38 // tiled background position and scroll speed
39 public static int tiles_scroll_y;
40 public static int tiles_scroll_vy;
41 public static int tiles_scroll_x;
42
43 public static byte levelno;
44
45 public static byte[] tileMap;
46
47 // a translation table for level tile text representation
48 // to tile index in the tile image
49 public static char[] tileTextToImageIndex =
50 {
51 "J", "L","^","<",">",
52 "\\","/","v","O","G",
53 };
54
55 public static final byte SPRITE_ID_PLAYER = 0; // "P"
56 public static final byte SPRITE_ID_ENEMY1_SHOOTING = 1; // "A"
57 public static final byte SPRITE_ID_ENEMY1 = 2; // "a"
58 public static final byte SPRITE_ID_ENEMY2_SHOOTING = 3; // "V"
59 public static final byte SPRITE_ID_ENEMY2 = 4; // "v"
60 public static final byte SPRITE_ID_ENEMY3 = 5; // "O"
61 public static final byte SPRITE_ID_ENEMY3_SINUS = 6; // "s"
62 public static final byte SPRITE_ID_ENEMY3_SINUS_SHOOTING = 7;// "S"
63 public static final byte SPRITE_ID_ENEMY4_SHOOTING = 8; // "T"
64 public static final byte SPRITE_ID_BOSS1 = 9; // "B"
65 public static final byte SPRITE_ID_BOSS2 = 10; // "C"
66 public static final byte SPRITE_ID_EXPLOSION = 11;
67 public static final byte SPRITE_ID_FIRE1 = 12;
68 public static final byte SPRITE_ID_FIRE2 = 13;
69 public static final byte SPRITE_ID_FIRE3 = 14;
70
71
72 // the coordinate above the screen, when enemy sprites reach it, they start moving, shooting and other AIi tricks..
73 public static final byte ENEMY_AI_ACTIVATION_ZONE_Y = - 2*TILE_SIZE;
74
75 public static GameSprite boss;
76 public static Vector enemySprites;
77
78 // a translation table for level sprite text representation
79 // to sprite id
80 public static char[] spriteTextToSpriteId =
81 {
82 "P","A","a","V","v","O","s","S","T","B","C"
83 };
84
85 public static byte getTileIndex(char t)
86 {
87 byte idx = 0;
88 // find tile index
89 while ( idx < tileTextToImageIndex.length && tileTextToImageIndex[idx] != t )
90 idx++;
91
92 // handle unexisting or empty tiles
93 if (idx > tileTextToImageIndex.length)
94 idx = -1;
95
96 return idx;
97 }
98
99 public static byte getSpriteId(char t)
100 {
101 byte idx = 0;
102 // find sprite id
103 while ( idx < spriteTextToSpriteId.length && spriteTextToSpriteId[idx] != t )
104 idx++;
105
106 // handle unexisting sprites
107 if (idx > spriteTextToSpriteId.length)
108 idx = -1;
109
110 return idx;
111 }
112
113 public static void loadLevel(byte level_no)
114 {
115 levelno = level_no;
116
117 // intialize the scrolling background
118 space_scroll_y = 0;
119 space_scroll_vy = (1 << GameSprite.SHIFT_FACTOR) >> 1;
120 tiles_scroll_vy = -(1 << GameSprite.SHIFT_FACTOR);
121
122 // initialize the enemy sprites list
123 enemySprites = new Vector();
124
125 // temp sprite for creating enemy sprites
126 GameSprite new_enemy;
127
128 InputStream inputstream = null;
129 DataInputStream datainputstream = null;
130
131 tileMap = new byte[LEVEL_HEIGHT * LEVEL_WIDTH];
132 int map_row = 0;
133 int tile_map_col = 0;
134 int sprite_map_col = 0;
135 try
136 {
137 inputstream = new Object().getClass().getResourceAsStream( "/stage"+ level_no +".txt" );
138 datainputstream = new DataInputStream(inputstream);
139
140 char ch;
141 boolean eof = false;
142 while(!eof)
143 {
144 // read level text file lines
145 try
146 {
147 // load a row of tiles
148 tile_map_col = 0;
149 ch = " ";
150 while (ch != ";")
151 {
152 ch = (char) datainputstream.readByte();
153 //System.out.print(ch);
154
155 if (ch != ";")
156 {
157 tileMap[ map_row * LEVEL_WIDTH + tile_map_col ] = getTileIndex(ch);
158
159 tile_map_col++;
160 }
161 else
162 {
163 break;
164 }
165 }
166 // load a row of sprites
167 sprite_map_col = 0;
168 ch = " ";
169 while (ch != ";")
170 {
171 ch = (char) datainputstream.readByte();
172 //System.out.print(ch);
173
174 int level_x = sprite_map_col * TILE_SIZE;
175 int level_y = map_row * TILE_SIZE;
176 if (ch != ";")
177 {
178 byte sprite_id = getSpriteId(ch);
179 switch (sprite_id)
180 {
181 case SPRITE_ID_PLAYER:
182
183 // initialize player sprite
184 GameCanvas.player = new GameSprite( SPRITE_ID_PLAYER );
185
186 // GameCanvas.player.x = GameCanvas.canvasWidth / 2 - GameCanvas.player.w/2;
187 // GameCanvas.player.y = GameCanvas.canvasHeight - GameCanvas.player.h - GameCanvas.player.h/2;
188
189 GameCanvas.player.x = level_x << GameSprite.SHIFT_FACTOR;
190 GameCanvas.player.y = level_y << GameSprite.SHIFT_FACTOR;
191
192 Level.tiles_scroll_x = GameCanvas.player.x + ((GameCanvas.player.w/2 - GameCanvas.canvasWidth/2) << GameSprite.SHIFT_FACTOR);
193
194 GameCanvas.player.frameId = GameCanvas.SPRITE_FRAME_PLAYER_CENTER;
195 break;
196
197 case SPRITE_ID_ENEMY1:
198 case SPRITE_ID_ENEMY1_SHOOTING:
199 case SPRITE_ID_ENEMY2:
200 case SPRITE_ID_ENEMY2_SHOOTING:
201 case SPRITE_ID_ENEMY3:
202 case SPRITE_ID_ENEMY3_SINUS:
203 case SPRITE_ID_ENEMY3_SINUS_SHOOTING:
204 case SPRITE_ID_ENEMY4_SHOOTING:
205 case SPRITE_ID_BOSS1:
206 case SPRITE_ID_BOSS2:
207 // initialize player sprite
208 new_enemy = new GameSprite( sprite_id );
209
210 new_enemy.x = level_x << GameSprite.SHIFT_FACTOR;
211 new_enemy.y = level_y << GameSprite.SHIFT_FACTOR;
212
213 new_enemy.vx = 0;
214
215 switch (sprite_id) {
216
217 case SPRITE_ID_ENEMY1:
218 case SPRITE_ID_ENEMY1_SHOOTING:
219 new_enemy.vy = 2 << GameSprite.SHIFT_FACTOR;
220 break;
221 case SPRITE_ID_ENEMY2:
222 case SPRITE_ID_ENEMY2_SHOOTING:
223 new_enemy.vy = 1 << GameSprite.SHIFT_FACTOR;
224 break;
225 case SPRITE_ID_ENEMY3:
226 new_enemy.vy = 3 << GameSprite.SHIFT_FACTOR;
227 break;
228 case SPRITE_ID_ENEMY3_SINUS:
229 case SPRITE_ID_ENEMY3_SINUS_SHOOTING:
230 // sinusoidal movement...
231 new_enemy.vy = 2 << GameSprite.SHIFT_FACTOR;
232 break;
233 case SPRITE_ID_ENEMY4_SHOOTING:
234 // lock this sprite to tiles, it is a gun turret!
235 new_enemy.vy = 0;
236 break;
237 case SPRITE_ID_BOSS1:
238 case SPRITE_ID_BOSS2:
239 new_enemy.vy = 0;
240 new_enemy.vx = 1 << GameSprite.SHIFT_FACTOR;
241
242 // save a reference to boss sprite
243 boss = new_enemy;
244
245 break;
246 }
247
248 enemySprites.addElement(new_enemy);
249
250 //System.out.println("new enemy sprite "+ sprite_id +" at "+level_x+", "+level_y+" vy: "+ new_enemy.vy);
251 break;
252
253 }
254
255 sprite_map_col++;
256 }
257 else
258 {
259
260 //System.out.println();
261
262 // read 0x0D and 0x0A (CR, LF)
263 ch = (char) datainputstream.readByte();
264 ch = (char) datainputstream.readByte();
265
266 break;
267 }
268 }
269
270 // go to next line of text
271 map_row++;
272 }
273 catch (EOFException eofex)
274 {
275 eof = true;
276 }
277 }
278 inputstream.close();
279 inputstream = null;
280 }
281 catch (Exception ex)
282 {
283 ex.printStackTrace();
284 }
285 }
286
287 public static void paintTiles(Graphics g)
288 {
289 // clip window coordinates
290 int cx, cy, cw, ch;
291 // image draw coordinates
292 int dx, dy;
293
294 int tsx = (tiles_scroll_x >> GameSprite.SHIFT_FACTOR);
295 int tsy = (tiles_scroll_y >> GameSprite.SHIFT_FACTOR);
296
297 int x;
298 int y = 0;
299
300 while (y <= GameCanvas.canvasHeight)
301 {
302 x = 0;
303 int ty = tsy + y;
304 while (x <= GameCanvas.canvasWidth)
305 {
306 // get the tileMap index of the tile, located at tx, ty
307 int tx = tsx + x;
308 int tile_idx = ((ty >> TILE_SIZE_SHIFT_FACTOR) << LEVEL_WIDTH_SHIFT_FACTOR) + (tx >> TILE_SIZE_SHIFT_FACTOR);
309
310 // get tile index in image from tileMap
311 byte tile_image_idx = tileMap[tile_idx];
312
313 if ( tile_image_idx >= 0)
314 {
315 // get tile level coordinates from tile index
316 int tile_idx_x = (tile_idx % LEVEL_WIDTH) << TILE_SIZE_SHIFT_FACTOR;
317 int tile_idx_y = (tile_idx >> LEVEL_WIDTH_SHIFT_FACTOR) << TILE_SIZE_SHIFT_FACTOR;
318
319 // translate to screen coordinates
320 tile_idx_x -= tsx;
321 tile_idx_y -= tsy;
322
323 int tile_col = tile_image_idx % TILES_PER_IMAGE_LINE;
324 int tile_row = tile_image_idx / TILES_PER_IMAGE_LINE;
325
326 cx = tile_idx_x;
327 cy = tile_idx_y;
328 cw = TILE_SIZE;
329 ch = TILE_SIZE;
330
331 // check clip window coordinates, if out of screen
332 if (cx < 0)
333 {
334 cw += cx;
335 cx = 0;
336 }
337 if (cy < 0)
338 {
339 ch += cy;
340 cy = 0;
341 }
342
343 // check clip window size, if out of screen
344 if (cx + cw > GameCanvas.canvasWidth)
345 cw -= (cx + cw) - GameCanvas.canvasWidth;
346 if (cy + ch > GameCanvas.canvasHeight)
347 ch -= (cy + ch) - GameCanvas.canvasHeight;
348
349 dx = tile_idx_x - (tile_col << TILE_SIZE_SHIFT_FACTOR);
350 dy = tile_idx_y - (tile_row << TILE_SIZE_SHIFT_FACTOR);
351
352 g.setClip(cx, cy, cw, ch);
353 g.drawImage(GameCanvas.tileImage, dx, dy, Graphics.TOP | Graphics.LEFT);
354 }
355
356 x += TILE_SIZE;
357 }
358
359 y += TILE_SIZE;
360 }
361 g.setClip(0, 0, GameCanvas.canvasWidth, GameCanvas.canvasHeight);
362 }
363
364 public static void paintSpaceBackground(Graphics g)
365 {
366 if (GameCanvas.mode == GameCanvas.MODE_GAME && GameCanvas.player_nuke_counter > 0)
367 {
368 // nuke explosion fx
369 int R = (GameCanvas.player_nuke_counter*16-1);
370 int G = (GameCanvas.player_nuke_counter*16-1);
371 int B = (GameCanvas.player_nuke_counter*16-1);
372 if (R < 0) R = 0;
373 if (G < 0) G = 0;
374 if (B < 0) B = 0;
375 g.setColor(R, G, B);
376 g.fillRect(0, 0, GameCanvas.canvasWidth, GameCanvas.canvasHeight);
377 }
378 else
379 {
380 // fill the vast space
381 g.setColor(0x000000);
382 g.fillRect(0, 0, GameCanvas.canvasWidth, GameCanvas.canvasHeight);
383
384 // init scrolling background image tiling
385 int x = 0;
386 int y = (space_scroll_y >> GameSprite.SHIFT_FACTOR) % GameCanvas.imgBackground.getHeight() - GameCanvas.imgBackground.getHeight();
387
388 // image is wide enough, so we only need to tile it in the vertical (y) direction
389 while (y < GameCanvas.canvasHeight)
390 {
391 g.drawImage(GameCanvas.imgBackground, x, y, Graphics.TOP | Graphics.LEFT);
392
393 y += GameCanvas.imgBackground.getHeight();
394 }
395 }
396 }
397
398 }
399