Reaper.java (33068B)
1 import java.awt.Color; 2 import java.awt.Image; 3 import java.awt.Point; 4 import java.awt.event.KeyEvent; 5 import java.awt.event.KeyListener; 6 7 import javax.swing.JFrame; 8 9 //* Copyright (c) Mary Percival 2003 */ 10 /* Reaper game Created May 2003 */ 11 12 public class Reaper extends JFrame implements KeyListener, Runnable { 13 private static final long serialVersionUID = -3998951090286400255L; 14 boolean easymode = true; 15 static int MAXLEVEL = 1; 16 static int level = 1; 17 18 // the levels so far are: 19 // 1 beginner level: 4 fire hydrants & 1 runner 20 21 static int LEFT = 1; 22 static int RIGHT = 0; 23 // the next 2 constants are overridden in init once we know the screen size 24 static int RIGHTEDGE = 789; 25 static int BOTTOMEDGE = 900; 26 static int PAGEWIDTH = 741; 27 28 static Point IMAGESIZE = new Point(152, 107); 29 static final int LEFTEDGE = 0; 30 static final int TOPEDGE = -10; 31 static int GROUNDLEVEL = 503; 32 static int startPosY; 33 static int JUMPAMOUNT = 70; 34 static int BOUNCEAMOUNT = 48; 35 static final int FALLAMOUNT = 16; // amount he falls each time interval 36 static final int RISEAMOUNT = 16; // amount he rises each time interval 37 static final int XAMOUNT = 12; 38 39 static final int X = 1; 40 static final int Y = 2; 41 static final int NOT = 3; 42 static final int DELAY = 50; 43 44 static final int OBSTACLEIMAGES = 1; // static obstacles - unlike reaper obstacles 45 static final int HEROIMAGES = 4; 46 static final int PREYIMAGES = 3; 47 48 // ---------------------------------------------------------------------------------------------- 49 // PREY TYPES 50 // ---------------------------------------------------------------------------------------------- 51 static final int PREYTYPES = 1; // runner 52 static final int RUNNER = 0; 53 54 // prey positions (height) 55 static final int RUNNERHEIGHT = GROUNDLEVEL - 20; 56 static int preyHeight[] = new int[PREYTYPES]; 57 58 static final int preySize[] = { 27 }; 59 static final int preyTopSpace[] = { 4 }; 60 61 static final int SPACE_FROM_X_TO_REAPER = 55; 62 static final int REAPERHEIGHT = 86; 63 static final int REAPEROFFSET = 21; 64 static final int REAPERCROUCHOFFSET = 39; 65 static final int REAPERSTANDINGSIZE = 65; 66 static final int REAPERCROUCHINGSIZE = 45; 67 68 static final int JUMPDURATION = 5; 69 static final int SUPERJUMPDURATION = 8; 70 static final int REAPERLEFTOFOBSTACLE = 45; // fudge factor because Reaper image is diff size to obstacle image 71 static final int REAPERRIGHTOFOBSTACLE = 10; // fudge factor because Reaper image is diff size to obstacle image 72 static final int PREYLEFTOFOBSTACLE = 33; // fudge factor for prey images 73 static final int PREYRIGHTOFOBSTACLE = 7; // >49 causes panic! 74 static final int REAPERLEFTOFPREY = 73; 75 static final int REAPERRIGHTOFPREY = -23; 76 77 static final int LEFTDOWN = 0; 78 static final int RIGHTDOWN = 1; 79 static final int DOWNDOWN = 2; 80 static final int SPACEDOWN = 3; 81 82 static final int OBSTACLEHEIGHT = 42; 83 static final int TALLOBSTACLEDIFF = 28; 84 static final int OBSTACLEWIDTH = 40; 85 int GROUNDDIFF = 605 - GROUNDLEVEL; 86 87 // all member variables 'static' because shared with the prey action thread 88 static ReaperArea area; 89 static Thread timer; 90 static boolean finished = false; 91 static boolean ingame = false; 92 static boolean juststarted = true; 93 static Point warpzone; 94 static int[] keysdown = new int[4]; 95 static Point[] preyPositions; 96 static Point playerPosition; 97 static Point[] obstaclePositions; 98 static boolean[] piranhaPopping; // one for each obstacle 99 static boolean[] hasPiranha; // one for each obstacle 100 static boolean[] isTall; // one for each obstacle 101 static int preyDirection[]; 102 static int preyNumber = 1, preyRemaining = 1, obstacleNumber = 1; 103 static boolean reapercrouching = false; 104 static boolean onTheWayUp = false; 105 static boolean bouncing = false; 106 static boolean wasbouncing = false; 107 static boolean dead = false; 108 static int page = 0; 109 static int reaperImageNo = 0; 110 static int preyImageNo[]; 111 static int levellength = 1482; 112 static Image[] reaperImages = new Image[HEROIMAGES]; 113 static Image[] obstacleImages = new Image[OBSTACLEIMAGES]; // obstacle, piranhapeep, piranha peepy etc 114 static Image[] squished = new Image[PREYTYPES]; // squished images for each prey type 115 static Image[][][] preyImages = new Image[PREYTYPES][2][PREYIMAGES]; // left right left right or whatever 116 static int obstacleImageNo[]; // what is the current image for obstacle n 117 static Image[][] preyImage = new Image[PREYTYPES][PREYIMAGES];// what is the current image for prey n? 118 static Image floors[] = new Image[MAXLEVEL]; 119 static int preyType[]; // what is the type of prey n? 120 static boolean preyDead[]; // is prey n dead? 121 static boolean reaperleft = false; 122 static boolean jumping = false; 123 static int preyMove[] = new int[PREYTYPES]; 124 boolean somethingChangedSinceRepaint = false; 125 126 // ************************************************************* 127 public static void main(String[] args) { 128 Reaper reaper = new Reaper(); 129 130 reaper.setLayout(null); 131 reaper.setBackground(Color.white); 132 reaper.setSize(RIGHTEDGE, BOTTOMEDGE); 133 reaper.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 134 reaper.setTitle("Reaper"); 135 136 area = new ReaperArea(reaper); 137 reaper.add(area); 138 //RIGHTEDGE = (Reaper.getBounds().width / XAMOUNT) * XAMOUNT + LEFTEDGE; 139 //BOTTOMEDGE = Reaper.getBounds().height - 1; 140 reaper.setVisible(true); 141 area.setBounds(0, 0, RIGHTEDGE, BOTTOMEDGE); 142 //GROUNDLEVEL = Reaper.getBounds().height - Reaper.GROUNDDIFF; 143 startPosY = GROUNDLEVEL; 144 //ReaperArea.FLOORLEVEL = Reaper.getBounds().height - ReaperArea.FLOORDIFF; 145 area.setVisible(true); 146 147 reaper.addKeyListener(reaper); 148 area.addKeyListener(reaper); 149 area.requestFocus(); 150 151 for (int i = 0; i < OBSTACLEIMAGES; i++) { 152 obstacleImages[i] = area.obstacle; 153 } 154 155 preyImages[RUNNER][RIGHT][0] = area.runner; 156 preyImages[RUNNER][RIGHT][1] = area.runner2; 157 preyImages[RUNNER][LEFT][0] = area.runnerleft; 158 preyImages[RUNNER][LEFT][1] = area.runner2left; 159 160 preyMove[RUNNER] = 5; 161 preyHeight[RUNNER] = 40; 162 squished[RUNNER] = area.squishedrunner; 163 164 // for (int i=0; i < MAXLEVEL; i++) { 165 // floors[i] = area.floor4; 166 // } 167 168 timer = new Thread(reaper); 169 timer.start(); 170 171 } 172 173 synchronized void faceRight() { 174 reaperImages[0] = area.reaperstand; 175 reaperImages[1] = area.reaper1; 176 reaperImages[2] = area.reaperstand; 177 reaperImages[3] = area.reaper2; 178 reaperImageNo = 0; 179 reaperleft = false; 180 } 181 182 synchronized void faceLeft() { 183 reaperImages[0] = area.reaperstandleft; 184 reaperImages[1] = area.reaper1left; 185 reaperImages[2] = area.reaperstandleft; 186 reaperImages[3] = area.reaper2left; 187 reaperImageNo = 0; 188 reaperleft = true; 189 } 190 191 synchronized void preyFaceRight(int preyno) { 192 preyImage[preyno][0] = preyImages[preyType[preyno]][RIGHT][0]; 193 preyImage[preyno][1] = preyImages[preyType[preyno]][RIGHT][1]; 194 preyDirection[preyno] = RIGHT; 195 } 196 197 synchronized void preyFaceLeft(int preyno) { 198 preyImage[preyno][0] = preyImages[preyType[preyno]][LEFT][0]; 199 preyImage[preyno][1] = preyImages[preyType[preyno]][LEFT][1]; 200 preyDirection[preyno] = LEFT; 201 } 202 203 synchronized void preyDie(int preyno) { 204 // displayStatus(); 205 preyImage[preyno][0] = squished[preyType[preyno]]; 206 preyImage[preyno][1] = squished[preyType[preyno]]; 207 } 208 209 synchronized void standStill() { 210 reaperImageNo = 0; 211 } 212 213 public void doLevel(int level) { 214 // this runs one 'level' 215 juststarted = true; 216 dead = false; 217 218 // position reaper at the bottom left 219 playerPosition = new Point(LEFTEDGE, GROUNDLEVEL); 220 faceRight(); 221 222 // *********** THIS STUFF DEPENDS WHAT LEVEL YOU ARE ON ************ 223 switch (level) { 224 case 1: 225 obstacleNumber = 4; // 4 obstacles for level 1 226 preyNumber = 1; 227 levellength = 1482; // 2 pages 228 break; 229 default: 230 System.out.println("Level " + level + " has not yet been implemented"); 231 } 232 preyImage = new Image[preyNumber][PREYIMAGES];// what is the current image for prey n? 233 // initialise piranha states 234 obstacleImageNo = new int[obstacleNumber]; 235 hasPiranha = new boolean[obstacleNumber]; 236 piranhaPopping = new boolean[obstacleNumber]; 237 isTall = new boolean[obstacleNumber]; 238 239 // initialise the arrays of prey, etc 240 preyPositions = new Point[preyNumber]; 241 preyType = new int[preyNumber]; 242 preyDead = new boolean[preyNumber]; 243 obstaclePositions = new Point[obstacleNumber]; 244 preyDirection = new int[preyNumber]; 245 preyImageNo = new int[preyNumber]; 246 247 for (int i = 0; i < preyNumber; i++) { 248 preyImageNo[i] = 0; 249 } 250 251 switch (level) { 252 // ----------------------------------------------- 253 // LEVEL 1 254 // ----------------------------------------------- 255 case 1: 256 for (int i = 0; i < obstacleNumber; i++) { 257 isTall[i] = false; 258 piranhaPopping[i] = false; 259 hasPiranha[i] = false; 260 } 261 obstaclePositions[0] = new Point(400, GROUNDLEVEL); 262 obstaclePositions[1] = new Point(950, GROUNDLEVEL); 263 obstaclePositions[2] = new Point(1245, GROUNDLEVEL); // 1255 for adjacent 264 obstaclePositions[3] = new Point(1320, GROUNDLEVEL); 265 266 preyPositions[0] = new Point(1000, RUNNERHEIGHT); 267 preyType = new int[] { RUNNER }; 268 break; 269 // ----------------------------------------------- 270 // LEVEL 2 271 // ----------------------------------------------- 272 default: 273 274 } 275 276 for (int j = 0; j < preyNumber; j++) { 277 preyFaceRight(j); // in this game all the 'prey' are fleeing to the right 278 preyDead[j] = false; 279 } 280 281 for (int i = 0; i < obstacleNumber; i++) { 282 if (hasPiranha[i]) { // pick a random image number between 0 and 18 (inclusive) 283 obstacleImageNo[i] = (int) (Math.random() * 18) / 1; 284 } else 285 obstacleImageNo[i] = 0; 286 } 287 288 // position the warp zone at the end of the level 289 warpzone = new Point(levellength, GROUNDLEVEL); 290 // *********** END OF STUFF THAT DEPENDS WHAT LEVEL YOU ARE ON ************ 291 292 ingame = true; 293 System.out.println("Started level " + level); 294 } 295 296 boolean isPlayerPosition(Point p) { 297 return (p.x == playerPosition.x && p.y == playerPosition.y); 298 } 299 300 int isEnemyPosition(Point p) { 301 for (int i = 0; i < preyNumber; i++) { 302 if (isEnemyX(p) != -1 && isEnemyY(p) != -1 && !preyDead[i]) 303 return (i); 304 } 305 return (-1); 306 } 307 308 boolean isObstaclePosition(Point p, boolean forReaper) { 309 int obby; 310 for (int i = 0; i < obstacleNumber; i++) { 311 obby = isObstacleX(p, forReaper); 312 if (obby != -1 && isObstacleY(p, obby, forReaper) != -1) { 313 return (true); 314 } 315 } 316 return (false); 317 } 318 319 boolean checkIfBlockingObstacle(Point p) { 320 boolean result = false; 321 int obby; 322 obby = isObstacleX(p, true); 323 if (obby != -1 && isBlockingObstacleY(p, obby)) { 324 piranhaPopping[obby] = false; 325 result = true; 326 } 327 for (int i = 0; i < obstacleNumber; i++) { 328 if (i != obby || !result) { 329 if (hasPiranha[i]) 330 piranhaPopping[i] = true; 331 } 332 } 333 if (!result) 334 startPosY = GROUNDLEVEL; 335 return (result); 336 } 337 338 int isObstacleX(Point p, boolean forReaper) { 339 int obstaclex; 340 for (int i = 0; i < obstacleNumber; i++) { 341 // if x is >= obstacleposition - (REAPERLEFTOFOBSTACLE) and x <= 342 // obstacleposition + (REAPERRIGHTOFOBSTACLE) 343 obstaclex = obstaclePositions[i].x; 344 if (forReaper) { 345 if (p.x >= (obstaclex - REAPERLEFTOFOBSTACLE) && p.x <= (obstaclex + REAPERRIGHTOFOBSTACLE)) 346 return (i); // return the number of the matching obstacle 347 } else { 348 if (p.x >= (obstaclex - PREYLEFTOFOBSTACLE) && p.x <= (obstaclex + PREYRIGHTOFOBSTACLE)) 349 return (i); // return the number of the matching obstacle 350 } 351 } 352 return (-1); 353 } 354 355 boolean isBlockingObstacleY(Point p, int obstaclenumber) { 356 // String s = "Is Reaper blocking obstacle " + obstaclenumber + " which is " + 357 // (isTall[obstaclenumber] ? "" : "not ") + "tall"; 358 if (isTall[obstaclenumber]) { 359 if (p.y <= obstaclePositions[obstaclenumber].y - (OBSTACLEHEIGHT + TALLOBSTACLEDIFF)) { 360 // System.out.println(s+": Yes"); 361 return (true); 362 } 363 } else { 364 if (p.y <= obstaclePositions[obstaclenumber].y - OBSTACLEHEIGHT) { 365 // System.out.println(s+": Yes"); 366 return (true); 367 } 368 } 369 // System.out.println(s+": No"); 370 return (false); 371 } 372 373 int isObstacleY(Point p, int obstaclenumber, boolean forReaper) { 374 if (isTall[obstaclenumber]) { 375 if (p.y > obstaclePositions[obstaclenumber].y - (OBSTACLEHEIGHT + TALLOBSTACLEDIFF)) { 376 return (obstaclenumber); 377 } 378 } else { 379 if (p.y > obstaclePositions[obstaclenumber].y - OBSTACLEHEIGHT) { 380 return (obstaclenumber); 381 } 382 } 383 return (-1); 384 } 385 386 int isEnemyX(Point p) { 387 int preyx; 388 for (int i = 0; i < preyNumber; i++) { 389 // if x is >= preyposition - (LEFTOFPREY) and x <= preyposition + (RIGHTOFPREY) 390 preyx = preyPositions[i].x; 391 // System.out.println("Player got by prey if " + 392 // p.x + " >= " + (preyx - REAPERLEFTOFPREY) + " && " + p.x + " <= " + (preyx + 393 // REAPERRIGHTOFPREY)); 394 if (p.x >= (preyx - REAPERLEFTOFPREY) && p.x <= (preyx + REAPERRIGHTOFPREY) && !preyDead[i]) 395 return (i); // return the number of the matching prey 396 } 397 return (-1); 398 } 399 400 int isEnemyY(Point p) { 401 int offset = reapercrouching ? REAPERCROUCHOFFSET : REAPEROFFSET; 402 for (int i = 0; i < preyNumber; i++) { 403 if (!preyDead[i] && ((p.y + offset <= preyPositions[i].y + preySize[preyType[i]]) 404 && (p.y + REAPERHEIGHT) >= preyPositions[i].y)) 405 return (i); 406 } 407 return (-1); 408 } 409 410 int randomMove() { 411 // return + or - value (randomly) 412 if (Math.random() >= 0.5) 413 return (24); 414 else 415 return (-24); 416 } 417 418 private synchronized void incKeysDown(int whichone) { 419 keysdown[whichone] = 1; 420 } 421 422 private synchronized void decKeysDown(int whichone) { 423 keysdown[whichone] = 0; 424 } 425 426 // this class will use just the key pressed event 427 @Override 428 public void keyPressed(KeyEvent e) { 429 if (e.getKeyCode() == KeyEvent.VK_F1) { 430 displayStatus(); 431 } 432 if (ingame) { 433 if (!(e.getKeyCode() == KeyEvent.VK_LEFT && playerPosition.x <= (LEFTEDGE + XAMOUNT))) { 434 435 // valid move: move the player and then move the prey 436 if (e.getKeyCode() == KeyEvent.VK_DOWN) { 437 reapercrouching = true; 438 incKeysDown(DOWNDOWN); 439 setSomethingChangedSinceRepaint(true); 440 } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { 441 incKeysDown(LEFTDOWN); 442 leftPressed(false); 443 setSomethingChangedSinceRepaint(true); 444 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 445 incKeysDown(RIGHTDOWN); 446 rightPressed(false); 447 setSomethingChangedSinceRepaint(true); 448 } else if (e.getKeyCode() == KeyEvent.VK_SPACE) { 449 if (!jumping) { 450 startPosY = playerPosition.y; 451 jumping = true; 452 onTheWayUp = true; 453 setSomethingChangedSinceRepaint(true); 454 } 455 } 456 if (somethingChangedSinceRepaint) { 457 area.repaint(); 458 } 459 } // if valid key press 460 } else if (e.getKeyCode() == KeyEvent.VK_ENTER) { 461 if (level == MAXLEVEL || dead) 462 doLevel(level); 463 else 464 doLevel(++level); 465 page = 0; 466 area.repaint(); 467 } 468 } 469 470 /* synchronized */ void setSomethingChangedSinceRepaint(boolean val) { 471 somethingChangedSinceRepaint = val; 472 } 473 474 void leftPressed(boolean skid) { 475 if (!reapercrouching) { 476 // if Hero was facing right, turn him left 477 if (!reaperleft) 478 faceLeft(); 479 else { 480 // if the target position is not occupied by a obstacle... 481 for (int i = 0; i < obstacleNumber; i++) { 482 if (isObstaclePosition(new Point(playerPosition.x - XAMOUNT, playerPosition.y), true)) 483 return; // can't move 484 } 485 playerPosition.x -= XAMOUNT; 486 if (!skid) 487 incrementHeroImage(); 488 } 489 } 490 } 491 492 void rightPressed(boolean skid) { 493 if (!reapercrouching) { 494 if ((playerPosition.x + SPACE_FROM_X_TO_REAPER) >= (warpzone.x + 4)) { 495 // level complete! 496 ingame = false; 497 } else { 498 // if Hero was facing left, turn him right 499 if (reaperleft) 500 faceRight(); 501 else { 502 for (int i = 0; i < obstacleNumber; i++) { 503 if (isObstaclePosition(new Point(playerPosition.x + XAMOUNT, playerPosition.y), true)) 504 return; // can't move 505 } 506 playerPosition.x += XAMOUNT; 507 // System.out.println("Reaper's x position is " + playerPosition.x); 508 if (!skid) 509 incrementHeroImage(); 510 } 511 } 512 } 513 } 514 515 boolean anythingVisibleChanged() { 516 return (somethingChangedSinceRepaint); 517 } 518 519 @Override 520 public void run() { 521 boolean odd = true; // only change piranha image every other cycle 522 while (true) { 523 if (juststarted) { 524 try { 525 Thread.sleep(750); 526 } catch (Exception e) { 527 } 528 area.repaint(); 529 juststarted = false; 530 } 531 try { 532 Thread.sleep(DELAY); 533 } catch (InterruptedException e) { 534 } 535 if (ingame) { 536 if (keysdown[LEFTDOWN] == 0 && keysdown[RIGHTDOWN] == 0 && keysdown[DOWNDOWN] == 0) 537 standStill(); 538 539 if (keysdown[LEFTDOWN] > 0) { 540 leftPressed(false); 541 setSomethingChangedSinceRepaint(true); 542 } else if (keysdown[RIGHTDOWN] > 0) { 543 rightPressed(false); 544 setSomethingChangedSinceRepaint(true); 545 } 546 547 if (!odd) { 548 // for each obstacle, cycle through the piranha pictures 549 for (int i = 0; i < obstacleNumber; i++) { 550 if (piranhaPopping[i]) { 551 incrementObstacleImage(i); 552 if (isVisibleObstacle(i)) 553 setSomethingChangedSinceRepaint(true); 554 } 555 } 556 } 557 odd = !odd; 558 559 // for each prey, move the prey in the direction it was going 560 for (int i = 0; i < preyNumber; i++) { 561 // TODO if there is a fatal obstacle at that position, fall into it and 562 // decrement count of prey 563 // and set that prey's position to -1, -1 564 /* 565 * if (isObstaclePosition(preyPositions[i])) { 566 * System.out.println("A prey fell into a obstacle"); 567 * 568 * preyPositions[i] = new Point(-1, -1); preyRemaining--; 569 * System.out.println(preyNumber-preyRemaining + " down, " + preyRemaining + 570 * " to go..."); } 571 */ 572 // if there is a non-fatal obstacle 573 if (isObstaclePosition(preyPositions[i], false)) { 574 // change direction 575 changeDirection(i); 576 if (isVisibleEnemy(i)) 577 setSomethingChangedSinceRepaint(true); 578 } 579 if (!preyDead[i]) { 580 preyPositions[i] = move(i, preyPositions[i], preyDirection[i], odd); 581 if (isVisibleEnemy(i)) 582 setSomethingChangedSinceRepaint(true); 583 } 584 585 // if player is caught by a prey, end the game 586 int preyno = isEnemyPosition(playerPosition); 587 if (preyno > -1) { 588 int NEEDTOBEABOVE = preyPositions[preyno].y + preyTopSpace[preyno] - REAPERHEIGHT; 589 if (easymode) 590 NEEDTOBEABOVE = preyPositions[preyno].y - preyHeight[preyType[preyno]]; 591 if ((!onTheWayUp && (playerPosition.y <= NEEDTOBEABOVE))) { 592 // player may have squished an prey 593 preyDead[preyno] = true; 594 preyDie(preyno); 595 // player bounces 596 bouncing = true; 597 startPosY = playerPosition.y; 598 setSomethingChangedSinceRepaint(true); 599 } else { 600 int offset = reapercrouching ? REAPERCROUCHOFFSET : REAPEROFFSET; 601 if (playerPosition.y > NEEDTOBEABOVE && (playerPosition.y 602 + offset <= preyPositions[preyno].y + preySize[preyType[preyno]])) { 603 die(); 604 setSomethingChangedSinceRepaint(true); 605 } 606 } 607 } 608 } 609 if (!dead) { 610 if (onTheWayUp) { 611 if (playerPosition.y > startPosY - JUMPAMOUNT) { 612 playerPosition = new Point(playerPosition.x, playerPosition.y - RISEAMOUNT); 613 setSomethingChangedSinceRepaint(true); 614 } else { 615 onTheWayUp = false; 616 } 617 } else if (bouncing) { 618 if (playerPosition.y > startPosY - BOUNCEAMOUNT) { 619 playerPosition = new Point(playerPosition.x, playerPosition.y - RISEAMOUNT); 620 setSomethingChangedSinceRepaint(true); 621 } else { 622 bouncing = false; 623 wasbouncing = true; 624 } 625 } else { 626 int obstacleno = isObstacleX(playerPosition, true); 627 if (obstacleno == -1) { // no obstacle at this position 628 if (!onTheWayUp && !bouncing) { 629 if (playerPosition.y < startPosY) { 630 playerPosition = new Point(playerPosition.x, playerPosition.y + FALLAMOUNT); 631 wasbouncing = false; 632 setSomethingChangedSinceRepaint(true); 633 } else 634 jumping = false; 635 } 636 } else { 637 Point obstaclepos = obstaclePositions[obstacleno]; 638 // if reaper's y position <= obstacle's height 639 int thisObstacleHeight = isTall[obstacleno] ? OBSTACLEHEIGHT + TALLOBSTACLEDIFF 640 : OBSTACLEHEIGHT; 641 if (playerPosition.y <= (obstaclepos.y - thisObstacleHeight) && // can't land on the 642 // obstacle if just < (??!) 643 (playerPosition.y + FALLAMOUNT >= (obstaclepos.y - thisObstacleHeight))) { 644 // allow reaper to land on the obstacle 645 jumping = false; 646 if (playerPosition.y != obstaclepos.y - thisObstacleHeight) 647 setSomethingChangedSinceRepaint(true); 648 playerPosition = new Point(playerPosition.x, obstaclepos.y - thisObstacleHeight); 649 // if the piranha was up, Hero dies 650 if (obstacleImages[obstacleImageNo[obstacleno]] != area.obstacle) { 651 die(); 652 } else { 653 // otherwise stop this Piranha 654 piranhaPopping[obstacleno] = false; 655 } 656 } else { 657 if (!onTheWayUp && !bouncing) { 658 if (playerPosition.y < startPosY) { 659 setSomethingChangedSinceRepaint(true); 660 playerPosition = new Point(playerPosition.x, playerPosition.y + FALLAMOUNT); 661 wasbouncing = false; 662 } else 663 jumping = false; 664 } 665 } 666 } 667 } 668 if (!dead) { 669 checkIfBlockingObstacle(playerPosition); 670 if (playerPosition.y > GROUNDLEVEL) 671 playerPosition.y = GROUNDLEVEL; 672 } 673 if (anythingVisibleChanged()) { 674 area.repaint(); 675 } 676 } else { 677 if (!area.showingMessage) 678 area.repaint(); 679 } 680 } 681 } 682 } 683 684 boolean isVisibleObstacle(int i) { 685 // TODO - this probably needs fixing when obstacle is near page boundary 686 return ((obstaclePositions[i].x >= page * PAGEWIDTH) && (obstaclePositions[i].x < (page + 1) * PAGEWIDTH)); 687 } 688 689 boolean isVisibleEnemy(int i) { 690 // TODO - this probably needs fixing when prey is near page boundary 691 return ((preyPositions[i].x >= page * PAGEWIDTH) && (preyPositions[i].x < (page + 1) * PAGEWIDTH) 692 && !preyDead[i]); 693 } 694 695 void changeDirection(int preyno) { 696 if (preyDirection[preyno] == LEFT) { 697 preyFaceRight(preyno); 698 } else { 699 preyFaceLeft(preyno); 700 } 701 } 702 703 synchronized void die() { 704 System.out.println("The Player is dead. Press the Enter key to restart the level"); 705 ingame = false; 706 dead = true; 707 displayStatus(); 708 } 709 710 synchronized void incrementObstacleImage(int i) { 711 obstacleImageNo[i]++; 712 if (obstacleImageNo[i] == OBSTACLEIMAGES) 713 obstacleImageNo[i] = 0; 714 } 715 716 synchronized void incrementHeroImage() { 717 reaperImageNo++; 718 if (reaperImageNo == HEROIMAGES) 719 reaperImageNo = 0; 720 } 721 722 synchronized void incrementEnemyImage(int i) { 723 preyImageNo[i]++; 724 if (preyImageNo[i] > (PREYIMAGES - 2)) 725 preyImageNo[i] = 0; 726 } 727 728 Point move(int preyNo, Point start, int direction, boolean odd) { 729 if (odd) 730 incrementEnemyImage(preyNo); 731 if (direction == LEFT) { 732 return (new Point(start.x - preyMove[preyType[preyNo]], start.y)); 733 } else { 734 return (new Point(start.x + preyMove[preyType[preyNo]], start.y)); 735 } 736 } 737 738 @Override 739 public void keyReleased(KeyEvent e) { 740 if (e.getKeyCode() == KeyEvent.VK_DOWN) { 741 reapercrouching = false; 742 decKeysDown(DOWNDOWN); 743 } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { 744 decKeysDown(LEFTDOWN); 745 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 746 decKeysDown(RIGHTDOWN); 747 } 748 } 749 750 public void keyTyped(KeyEvent e) { 751 } 752 753 synchronized Image getHeroImage() { 754 return (reaperImages[reaperImageNo]); 755 } 756 757 synchronized Image getObstacleImage(int obstaclenum) { 758 return (obstacleImages[obstacleImageNo[obstaclenum]]); 759 } 760 761 synchronized Image getEnemyImage(int preyno) { 762 return (preyImage[preyno][preyImageNo[preyno]]); 763 } 764 765 void displayStatus() { 766 /* 767 * // when a certain F Key is pressed, display positions of Reaper, // all 768 * obstacles and all prey and the end flag (warp zone) 769 * System.out.println("--------"); System.out.println("Reaper is " + (dead? 770 * "dead" : "alive")); if (dead) { int preyno = isEnemyPosition(playerPosition); 771 * System.out.println("Reaper was killed by prey " + preyno); } 772 * System.out.println("In game is " + ingame); System.out.println("Reaper is " + 773 * (onTheWayUp? "on the way up" : "not on the way up")); 774 * System.out.println("Reaper's position is (" + playerPosition.x + ", " + 775 * playerPosition.y + ")"); 776 * System.out.println("Reaper's visible left, bottom co-ordinates are " + 777 * (playerPosition.x + 55) + " and " + (playerPosition.y + REAPERHEIGHT)); 778 * System.out.println("Reaper is on page " + page + 779 * " (which shows x positions from " + (page*PAGEWIDTH) + " to " + 780 * ((page+1)*PAGEWIDTH) + ")"); System.out.println("Screen bounds are (" + 781 * getBounds().width + ", " + getBounds().height + ")"); System.out.println(""); 782 * for (int prey=0; prey < preyNumber; prey++) { System.out.println("Enemy " + 783 * prey + " is " + preyTypeString(preyType[prey]) + " and is " + (preyDead[prey] 784 * ? " " : "not ") + "dead"); System.out.println("Enemy " + prey + 785 * " is at position (" + preyPositions[prey].x + ", " + 786 * preyPositions[prey].y+") and has size " + preySize[preyType[prey]]); } 787 * //System.out.println(""); //for (int obstacle=0; obstacle < obstacleNumber; 788 * obstacle++) { // System.out.println("Obstacle " + obstacle + 789 * " is at position (" + obstaclePositions[obstacle].x + // ", " + 790 * obstaclePositions[obstacle].y+")"); //} System.out.println(""); 791 * System.out.println("The warp zone is positioned at (" + warpzone.x + ", " + 792 * warpzone.y + ")"); System.out.println("========"); 793 */ 794 } 795 796 String preyTypeString(int fortype) { 797 switch (fortype) { 798 case RUNNER: 799 return ("RUNNER"); 800 default: 801 return ("Unknown type (" + fortype + ")"); 802 } 803 } 804 805 void changePageIfNecessary() { 806 if (playerPosition.x == LEFTEDGE) 807 return; 808 if ((playerPosition.x + SPACE_FROM_X_TO_REAPER) > (page * PAGEWIDTH + RIGHTEDGE - XAMOUNT)) { 809 // System.out.println("Change page up: (" + playerPosition.x+ "+" + 810 // SPACE_FROM_X_TO_REAPER+ ") > (" + page+ "*" + PAGEWIDTH + "+" + RIGHTEDGE + 811 // "-" + XAMOUNT + ")"); 812 page++; 813 } else if ((playerPosition.x + SPACE_FROM_X_TO_REAPER) - (page * PAGEWIDTH) < (LEFTEDGE + XAMOUNT)) { 814 // System.out.println("Change page down: (" + playerPosition.x+ "+" + 815 // SPACE_FROM_X_TO_REAPER+ ")-(" + page+ "*" + PAGEWIDTH + ") < (" + LEFTEDGE+ 816 // "+" + XAMOUNT+")"); 817 page--; 818 } 819 } 820 }