Link.java (19759B)
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 /* Link game Created May 2003 */ 11 12 public class Link extends JFrame implements KeyListener, Runnable { 13 private static final long serialVersionUID = 136423218680421502L; 14 // all member variables 'static' because shared with the enemy action thread 15 static LinkArea area; 16 static boolean finished = false; 17 static boolean ingame = false; 18 static boolean juststarted = false; 19 static int level = 0; 20 static Point[] enemyPositions; 21 static Point playerPosition; 22 static Point[][] obstaclePositions; 23 static int direction[]; 24 static Thread timer; 25 static int enemyNumber = 1, enemiesRemaining = 1, obstacleNumber = 1; 26 static boolean herocrouching = false; 27 static final int MAXLEVELS = 1; 28 static final int levellengths[] = new int[MAXLEVELS]; 29 boolean hasWeaponOut = false; 30 31 static int LEFT = -1; 32 static int RIGHT = 1; 33 34 // the next 2 constants are overridden in init once we know the screen size 35 static int RIGHTEDGE = 789; 36 static int BOTTOMEDGE = 800; 37 // 38 static Point IMAGESIZE = new Point(152, 107); 39 static Point HEROPOS = new Point(63, 28); 40 static final int LEFTEDGE = -15; 41 static final int TOPEDGE = -10; 42 static final int FALLAMOUNT = 16; // amount he falls each time interval 43 static final int RISEAMOUNT = 16; // amount he rises each time interval 44 static int GROUNDLEVEL = 500; 45 static int XAMOUNT = 5; 46 static int YAMOUNT = 5; 47 static int JUMPAMOUNT = 70; 48 static final int X = 1; 49 static final int Y = 2; 50 static final int NOT = 3; 51 static final int DELAY = 60; 52 53 static int heroImageNo = 0; 54 static final int OBSTACLEIMAGES = 1; 55 static final int HEROIMAGES = 4; 56 static Image[] heroImages = new Image[HEROIMAGES]; 57 static Image[] obstacleImages = new Image[OBSTACLEIMAGES]; // obstacles don't move 58 static int obstacleImageNo[]; 59 static boolean heroleft = false; 60 static boolean jumping = false; 61 static Point warpzone; 62 // static boolean superjump = false; 63 static final int JUMPDURATION = 5; 64 static final int SUPERJUMPDURATION = 8; 65 static final int LEFTOFOBSTACLE = 27; 66 static final int RIGHTOFOBSTACLE = 33; 67 static int[] keysdown = new int[4]; 68 static final int LEFTDOWN = 0; 69 static final int RIGHTDOWN = 1; 70 static final int DOWNDOWN = 2; 71 static final int SPACEDOWN = 3; 72 73 static final int OBSTACLEHEIGHT = 42; 74 boolean onTheWayUp = false; 75 static int startPosY = GROUNDLEVEL; 76 77 public static void main(String[] args) { 78 Link link = new Link(); 79 80 link.setLayout(null); 81 link.setBackground(Color.white); 82 link.setSize(RIGHTEDGE, BOTTOMEDGE); 83 link.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 84 link.setTitle("Link"); 85 86 area = new LinkArea(link); 87 link.add(area); 88 XAMOUNT = 12; 89 YAMOUNT = 12; 90 //RIGHTEDGE = (Link.getBounds().width / XAMOUNT) * XAMOUNT + LEFTEDGE; 91 //BOTTOMEDGE = Link.getBounds().height - 1; 92 link.setVisible(true); 93 //area.setBounds(0, 0, Link.getBounds().width, BOTTOMEDGE); 94 area.setBounds(0, 0, RIGHTEDGE, BOTTOMEDGE); 95 area.setVisible(true); 96 97 link.addKeyListener(link); 98 area.addKeyListener(link); 99 area.requestFocus(); 100 101 levellengths[0] = RIGHTEDGE; 102 obstacleImages[0] = area.obstacle; 103 104 timer = new Thread(link); 105 timer.start(); 106 } 107 108 synchronized void faceRight() { 109 heroImages[0] = area.herostand; 110 heroImages[1] = area.hero1; 111 heroImages[2] = area.herostand; 112 heroImages[3] = area.hero2; 113 heroImageNo = 0; 114 heroleft = false; 115 } 116 117 synchronized void faceLeft() { 118 heroImages[0] = area.herostandleft; 119 heroImages[1] = area.hero1left; 120 heroImages[2] = area.herostandleft; 121 heroImages[3] = area.hero2left; 122 heroImageNo = 0; 123 heroleft = true; 124 } 125 126 synchronized void getSwordOut() { 127 hasWeaponOut = true; 128 if (heroleft) { 129 heroImages[0] = area.heroswordleft; 130 heroImages[1] = area.heroswordleft; 131 heroImages[2] = area.heroswordleft; 132 heroImages[3] = area.heroswordleft; 133 } else { 134 heroImages[0] = area.heroswordright; 135 heroImages[1] = area.heroswordright; 136 heroImages[2] = area.heroswordright; 137 heroImages[3] = area.heroswordright; 138 } 139 heroImageNo = 0; 140 } 141 142 synchronized void getShieldOut() { 143 hasWeaponOut = true; 144 if (heroleft) { 145 heroImages[0] = area.heroshieldleft; 146 heroImages[1] = area.heroshieldleft; 147 heroImages[2] = area.heroshieldleft; 148 heroImages[3] = area.heroshieldleft; 149 } else { 150 heroImages[0] = area.heroshieldright; 151 heroImages[1] = area.heroshieldright; 152 heroImages[2] = area.heroshieldright; 153 heroImages[3] = area.heroshieldright; 154 } 155 heroImageNo = 0; 156 } 157 158 synchronized void putWeaponAway() { 159 hasWeaponOut = false; 160 if (heroleft) 161 faceLeft(); 162 else 163 faceRight(); 164 } 165 166 synchronized void standStill() { 167 heroImageNo = 0; 168 } 169 170 public void doLevel(int level) { 171 // this runs one 'level' 172 juststarted = true; 173 174 System.out.println("Started level " + level); 175 176 // position Hero at the bottom left 177 playerPosition = new Point(LEFTEDGE, GROUNDLEVEL); 178 faceRight(); 179 180 // initialise obstacle states 181 obstacleImageNo = new int[obstacleNumber]; 182 obstacleImageNo[0] = 0; 183 184 // initialise the arrays of enemies, etc 185 enemyPositions = new Point[enemyNumber]; 186 obstaclePositions = new Point[MAXLEVELS][obstacleNumber]; 187 direction = new int[enemyNumber]; 188 for (int i = 0; i < enemyNumber; i++) { 189 enemyPositions[i] = new Point(RIGHTEDGE, GROUNDLEVEL); 190 direction[i] = LEFT; 191 } 192 for (int i = 0; i < obstacleNumber; i++) { 193 switch (level) { 194 case 1: 195 obstaclePositions[level - 1][i] = new Point((RIGHTEDGE + 15) / 2, GROUNDLEVEL); 196 System.out.println("Obstacle positioned at (" + (RIGHTEDGE - LEFTEDGE) / 2 + ", " + GROUNDLEVEL + ")"); 197 break; 198 default: 199 } 200 } 201 202 // position the warp zone at the end of the level 203 warpzone = new Point(levellengths[level - 1], GROUNDLEVEL); 204 205 // paint the panel here 206 // area.repaint(); 207 ingame = true; 208 } 209 210 Point randomPosition() { 211 return new Point((int) (Math.random() * RIGHTEDGE) / XAMOUNT * XAMOUNT, 212 (int) (Math.random() * BOTTOMEDGE) / YAMOUNT * YAMOUNT); 213 } 214 215 boolean isPlayerPosition(Point p) { 216 return (p.x == playerPosition.x && p.y == playerPosition.y); 217 } 218 219 boolean isEnemyPosition(Point p) { 220 for (int i = 0; i < enemyNumber; i++) { 221 if (p.x == enemyPositions[i].x && p.y == enemyPositions[i].y) 222 return (true); 223 } 224 return (false); 225 } 226 227 boolean isObstaclePosition(Point p) { 228 for (int i = 0; i < obstacleNumber; i++) { 229 if (isObstacleX(p) != -1 && isObstacleY(p) != -1) { 230 return (true); 231 } 232 } 233 return (false); 234 } 235 236 boolean checkIfBlockingObstacle(Point p) { 237 boolean result = false; 238 for (int i = 0; i < obstacleNumber; i++) { 239 if (isObstacleX(p) != -1 && isBlockingObstacleY(p) != -1) { 240 // piranhaPopping[i] = false; 241 result = true; 242 } 243 // else piranhaPopping[i] = true; 244 } 245 if (!result) 246 startPosY = GROUNDLEVEL; 247 return (result); 248 } 249 250 int isObstacleX(Point p) { 251 int obstaclex; 252 for (int i = 0; i < obstacleNumber; i++) { 253 // if x is >= obstacleposition - (LEFTOFOBSTACLE) and x <= obstacleposition + 254 // (RIGHTOFOBSTACLE) 255 obstaclex = obstaclePositions[level - 1][i].x; 256 if (p.x >= (obstaclex - LEFTOFOBSTACLE) && p.x <= (obstaclex + RIGHTOFOBSTACLE)) 257 return (i); // return the number of the matching obstacle 258 } 259 return (-1); 260 } 261 262 int isBlockingObstacleY(Point p) { 263 for (int i = 0; i < obstacleNumber; i++) { 264 if (p.y <= obstaclePositions[level - 1][i].y - OBSTACLEHEIGHT) 265 return (i); 266 } 267 return (-1); 268 } 269 270 int isObstacleY(Point p) { 271 for (int i = 0; i < obstacleNumber; i++) { 272 if (p.y > obstaclePositions[level - 1][i].y - OBSTACLEHEIGHT) 273 return (i); 274 } 275 return (-1); 276 } 277 278 int randomMove() { 279 // return + or - value (randomly) 280 if (Math.random() >= 0.5) 281 return (24); 282 else 283 return (-24); 284 } 285 286 private synchronized void incKeysDown(int whichone) { 287 keysdown[whichone] = 1; 288 } 289 290 private synchronized void decKeysDown(int whichone) { 291 keysdown[whichone] = 0; 292 } 293 294 // this class will use just the key pressed event 295 @Override 296 public void keyPressed(KeyEvent e) { 297 if (ingame) { 298 if (!((e.getKeyCode() == KeyEvent.VK_LEFT && playerPosition.x <= (LEFTEDGE + XAMOUNT)) 299 || (e.getKeyCode() == KeyEvent.VK_RIGHT && playerPosition.x >= (RIGHTEDGE - XAMOUNT)))) { 300 // valid move: move the player and then move the enemies 301 if (e.getKeyCode() == KeyEvent.VK_DOWN) { 302 herocrouching = true; 303 incKeysDown(DOWNDOWN); 304 } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { 305 incKeysDown(LEFTDOWN); 306 leftPressed(); 307 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 308 incKeysDown(RIGHTDOWN); 309 rightPressed(); 310 } else if (e.getKeyCode() == KeyEvent.VK_SPACE) { 311 // System.out.println("Jump when jumping is " + jumping); 312 if (!jumping) { 313 // incKeysDown(SPACEDOWN); 314 startPosY = playerPosition.y; 315 jumping = true; 316 onTheWayUp = true; 317 } 318 } else if (e.getKeyCode() == KeyEvent.VK_Z) { 319 getSwordOut(); 320 } else if (e.getKeyCode() == KeyEvent.VK_X) { 321 getShieldOut(); 322 } 323 if (isEnemyPosition(playerPosition)) { 324 System.out.println("The Player ran into an enemy!! Press the Enter key to restart the level"); 325 ingame = false; 326 } 327 // area.repaint(); 328 // System.out.println("Hero's position = (" + playerPosition.x + ", " + 329 // playerPosition.y + ")"); 330 // System.out.println(" "); 331 } // if valid key press 332 } else if (e.getKeyCode() == KeyEvent.VK_ENTER) { 333 doLevel(++level); 334 } 335 } 336 337 void leftPressed() { 338 if (!herocrouching) { 339 // superjump = true; // if jumping 340 // if Hero was facing right, turn him left 341 if (!heroleft && !hasWeaponOut) 342 faceLeft(); 343 else { 344 // if the target position is not occupied by a obstacle... 345 for (int i = 0; i < obstacleNumber; i++) { 346 if (isObstaclePosition(new Point(playerPosition.x - XAMOUNT, playerPosition.y))) 347 return; // can't move 348 } 349 playerPosition.x -= XAMOUNT; 350 incrementHeroImage(); 351 } 352 } 353 } 354 355 void rightPressed() { 356 if (!herocrouching) { 357 // superjump = true; // if jumping 358 // if Hero was facing left, turn him right 359 if (heroleft && !hasWeaponOut) 360 faceRight(); 361 else { 362 for (int i = 0; i < obstacleNumber; i++) { 363 if (isObstaclePosition(new Point(playerPosition.x + XAMOUNT, playerPosition.y))) 364 return; // can't move 365 } 366 playerPosition.x += XAMOUNT; 367 incrementHeroImage(); 368 } 369 } 370 } 371 372 @Override 373 public void run() { 374 while (true) { 375 if (juststarted) { 376 try { 377 Thread.sleep(750); 378 } catch (Exception e) { 379 } 380 area.repaint(); 381 juststarted = false; 382 } 383 try { 384 Thread.sleep(DELAY); 385 } catch (InterruptedException e) { 386 } 387 if (ingame) { 388 // System.out.println("Run: BEFORE: Hero's position = (" + playerPosition.x + ", 389 // " + playerPosition.y + ")"); 390 if (keysdown[LEFTDOWN] == 0 && keysdown[RIGHTDOWN] == 0 391 && keysdown[DOWNDOWN] == 0 /* 392 * && keysdown[SPACEDOWN] == 0 393 */) 394 standStill(); 395 396 if (keysdown[LEFTDOWN] > 0) 397 leftPressed(); 398 else if (keysdown[RIGHTDOWN] > 0) 399 rightPressed(); 400 401 // for each obstacle, cycle through the piranha pictures 402 for (int i = 0; i < obstacleNumber; i++) { 403 incrementObstacleImage(i); 404 } 405 406 /* 407 * // for each enemy, move the enemy in the direction it was going for (int i=0; 408 * i < enemyPositions.length; i++) { if (!deadHero(enemyPositions[i])) { 409 * enemyPositions[i] = move(enemyPositions[i], direction[i]); } // if there is a 410 * obstacle at that position, fall into it and decrement count of enemies // and 411 * set that enemy's position to -1, -1 if 412 * (isObstaclePosition(enemyPositions[i])) { 413 * System.out.println("A enemy fell into a obstacle"); 414 * 415 * enemyPositions[i] = new Point(-1, -1); enemiesRemaining--; 416 * System.out.println(enemyNumber-enemiesRemaining + " down, " + 417 * enemiesRemaining + " to go..."); } // if player is caught by a enemy or all 418 * enemies are gone, end the game if (isPlayerPosition(enemyPositions[i])) { 419 * System.out. 420 * println(""Mmm! Brains...". The Player is dead. Press the Enter key to restart the level" 421 * ); level--; // because it will be incremented in a minute and we want to stay 422 * on the same 'level' ingame = false; } } if (enemiesRemaining == 0) { 423 * System.out. 424 * println("All the enemies are gone -- you won!! Press the Enter key to start the next level" 425 * ); enemyNumber++; if (obstacleNumber > 2) obstacleNumber--; ingame = false; } 426 */ 427 if (onTheWayUp) { 428 // System.out.println("OnTheWayUp. Start Y Position =" + startPosY); 429 if (playerPosition.y > startPosY - JUMPAMOUNT) 430 playerPosition = new Point(playerPosition.x, playerPosition.y - RISEAMOUNT); 431 else { 432 onTheWayUp = false; 433 } 434 } else { 435 int obstacleno = isObstacleX(playerPosition); 436 if (obstacleno == -1) { // no obstacle at this position 437 if (onTheWayUp == false) { 438 if (playerPosition.y < startPosY) 439 playerPosition = new Point(playerPosition.x, playerPosition.y + FALLAMOUNT); 440 else 441 jumping = false; 442 } 443 } else { 444 Point obstaclepos = obstaclePositions[level - 1][obstacleno]; 445 // if hero's y position <= obstacle's height 446 if (playerPosition.y <= (obstaclepos.y - OBSTACLEHEIGHT)) { // can't land on the obstacle if 447 // just < (??!) 448 // allow hero to land on the obstacle 449 // System.out.println("Allow Hero to land (or stay) on obstacle"); 450 jumping = false; 451 playerPosition = new Point(playerPosition.x, obstaclepos.y - OBSTACLEHEIGHT); 452 // if the piranha was up, Hero dies 453 if (obstacleImages[obstacleImageNo[obstacleno]] != area.obstacle) { 454 System.out.println("Hero dies!!"); 455 ingame = false; 456 457 } 458 /* 459 * else { // otherwise stop this Piranha piranhaPopping[obstacleno] = false; } 460 */ 461 } else { 462 if (onTheWayUp == false) { 463 if (playerPosition.y < startPosY) 464 playerPosition = new Point(playerPosition.x, playerPosition.y + FALLAMOUNT); 465 else 466 jumping = false; 467 } 468 } 469 } 470 } 471 checkIfBlockingObstacle(playerPosition); 472 // System.out.println("Run: AFTER: Hero's position = (" + playerPosition.x + ", 473 // " + playerPosition.y + ")"); 474 area.repaint(); 475 } 476 } 477 } 478 479 synchronized void incrementObstacleImage(int i) { 480 obstacleImageNo[i]++; 481 if (obstacleImageNo[i] == OBSTACLEIMAGES) 482 obstacleImageNo[i] = 0; 483 } 484 485 synchronized void incrementHeroImage() { 486 heroImageNo++; 487 if (heroImageNo == HEROIMAGES) 488 heroImageNo = 0; 489 } 490 491 Point move(Point start, int direction) { 492 return (new Point(start.x + direction, start.y)); 493 } 494 495 boolean deadHero(Point p) { 496 return (p.x == -1 && p.y == -1); 497 } 498 499 @Override 500 public void keyReleased(KeyEvent e) { 501 // boolean needrepaint = false; 502 if (e.getKeyCode() == KeyEvent.VK_DOWN) { 503 herocrouching = false; 504 decKeysDown(DOWNDOWN); 505 // needrepaint = true; 506 } 507 /* 508 * else if (e.getKeyCode() == KeyEvent.VK_SPACE) { decKeysDown(SPACEDOWN); } 509 */ 510 else if (e.getKeyCode() == KeyEvent.VK_LEFT) { 511 decKeysDown(LEFTDOWN); 512 // superjump = false; 513 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 514 decKeysDown(RIGHTDOWN); 515 // superjump = false; 516 } else 517 putWeaponAway(); 518 // if (needrepaint) area.repaint(); 519 } 520 521 @Override 522 public void keyTyped(KeyEvent e) { 523 } 524 525 synchronized Image getHeroImage() { 526 return (heroImages[heroImageNo]); 527 } 528 529 synchronized Image getObstacleImage(int obstaclenum) { 530 return (obstacleImages[obstacleImageNo[obstaclenum]]); 531 } 532 533 }