old-java-games

java games my brother and I developed as kids.
Log | Files | Refs | README

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 }