Advertisement
Guest User

Untitled

a guest
May 5th, 2011
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.59 KB | None | 0 0
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.net.*;
  4. import java.applet.Applet;
  5. import java.applet.AudioClip;
  6. import java.io.*;
  7. import java.util.*;
  8. import java.net.*;
  9. import java.applet.*;
  10. import java.awt.*;
  11.  
  12. public class SnakePit extends Applet implements Runnable, KeyListener {
  13.  
  14.  
  15. // Copyright information.
  16.  
  17. String copyName = "Snake Pit";
  18. String copyVers = "Version 1.1";
  19. String copyInfo = "Copyright 2011 by OA";
  20. String copyLink = "http://www.servicedesk.net78.net";
  21. String copyText = copyName + '\n' + copyVers + '\n'
  22. + copyInfo + '\n' + copyLink;
  23.  
  24. // Thread control variables.
  25.  
  26. Thread loopThread;
  27. Thread loadThread;
  28.  
  29. // Constants
  30.  
  31. static final int MAX_DELAY = 75; // Milliseconds between screen updates.
  32. static final int MIN_DELAY = 50;
  33. static final int DELAY_INCR = 5;
  34.  
  35. static final int GRID_WIDTH = 39; // Size of playing field.
  36. static final int GRID_HEIGHT = 25;
  37. static final int GRID_SIZE = 16; // Grid size in pixels.
  38.  
  39. static final int NUM_LEVELS = 5; // Number of levels.
  40. static final int NUM_MICE = 6; // Number of active mice.
  41. static final int NUM_LIVES = 3; // Starting number of lives.
  42.  
  43. static final int INIT = 1; // Game states.
  44. static final int PLAY = 2;
  45. static final int LEVEL = 3;
  46. static final int END = 4;
  47. static final int OVER = 5;
  48.  
  49. static final int END_COUNT = 30; // Counter values.
  50. static final int LEVEL_COUNT = 40;
  51.  
  52. static final int TYPE_MASK = 0x00FF0000; // Grid cell types.
  53. static final int EMPTY = 0x00000000;
  54. static final int BLOCK = 0x00010000;
  55. static final int SNAKE = 0x00020000;
  56. static final int MOUSE = 0x00030000;
  57. static final int KEY = 0x00040000;
  58.  
  59. static final int DIR_MASK = 0x0000FF00; // Grid cell directions.
  60. static final int NONE = 0x00000000;
  61. static final int LEFT = 0x00000100;
  62. static final int RIGHT = 0x00000200;
  63. static final int UP = 0x00000300;
  64. static final int DOWN = 0x00000400;
  65.  
  66. static final int SHAPE_MASK = 0x000000FF; // Grid cell shapes.
  67. static final int SQUARE = 0x00000000;
  68. static final int SNAKEHEAD = 0x00000001;
  69. static final int SNAKEBODY = 0x00000002;
  70. static final int SNAKEELB1 = 0x00000003;
  71. static final int SNAKEELB2 = 0x00000004;
  72. static final int SNAKETAIL = 0x00000005;
  73. static final int MOUSEBODY = 0x00000006;
  74. static final int KEYSHAPE = 0x00000007;
  75.  
  76. static final int MOUSE_POINTS = 10; // Scoring values.
  77. static final int LEVEL_POINTS = 200;
  78. static final int EXTRA_LIFE = 500;
  79.  
  80. // Sizing data.
  81.  
  82. int width;
  83. int height;
  84.  
  85. // Game data.
  86.  
  87. int score; // Scoring data.
  88. int highScore;
  89. int lives;
  90. int extraLife;
  91.  
  92. int level; // Level data.
  93. int levelTotal;
  94. int miceNeeded;
  95. int miceEaten;
  96. int delay;
  97.  
  98. int[][] grid; // Playing field.
  99.  
  100. Point[] snake; // Snake data.
  101. int headPtr;
  102. int tailPtr;
  103. int direction;
  104. int lastDirection;
  105. boolean lockKeys;
  106.  
  107. Point[] mouse; // Mouse data.
  108.  
  109. Point key; // Key data.
  110. boolean keyActive;
  111.  
  112. int gameState; // Game state data.
  113. int levelCounter;
  114. int endCounter;
  115. boolean paused;
  116.  
  117. // Screen colors.
  118.  
  119. Color bgColor = Color.black;
  120. Color fgColor = Color.white;
  121. Color blockColor = new Color(0, 0, 153);
  122. Color fieldColor = new Color(204, 153, 102);
  123. Color snakeColor = new Color(0, 153, 0);
  124. Color mouseColor = Color.gray;
  125. Color keyColor = new Color(204, 102, 102);
  126.  
  127. // Basic shapes.
  128.  
  129. Polygon snakeHead;
  130. Polygon snakeBody;
  131. Polygon snakeTail;
  132. Polygon snakeElb1;
  133. Polygon snakeElb2;
  134. Polygon mouseBody;
  135. Polygon keyShape;
  136.  
  137. // Sound data.
  138.  
  139. boolean loaded = false;
  140. boolean sound;
  141. AudioClip bonkSound;
  142. AudioClip munchSound;
  143. AudioClip squeakSound;
  144. AudioClip chimeSound;
  145. AudioClip advanceSound;
  146.  
  147. // For tracking the loading of sound clips.
  148.  
  149. int clipTotal = 0;
  150. int clipsLoaded = 0;
  151.  
  152. // )ff screen image.
  153.  
  154. Dimension offDimension;
  155. Image offImage;
  156. Graphics offGraphics;
  157.  
  158. // Font data.
  159.  
  160. Font font = new Font("Helvetica", Font.BOLD, 12);
  161. FontMetrics fm = getFontMetrics(font);
  162. int fontWidth = fm.getMaxAdvance();
  163. int fontHeight = fm.getHeight();
  164.  
  165. // Applet information.
  166.  
  167. public String getAppletInfo() {
  168.  
  169. // Return copyright information.
  170.  
  171. return(copyText);
  172. }
  173.  
  174. public void init() {
  175.  
  176. int i;
  177.  
  178. // Display copyright information.
  179.  
  180. System.out.println(copyText);
  181.  
  182. // Set up key event handling and set focus to applet window.
  183.  
  184. addKeyListener(this);
  185. requestFocus();
  186.  
  187. // Define the playing grid.
  188.  
  189. grid = new int[GRID_WIDTH][GRID_HEIGHT];
  190.  
  191. // Initialize basic shapes.
  192.  
  193. snakeHead = new Polygon();
  194. snakeHead.addPoint(4, 15);
  195. snakeHead.addPoint(3, 14);
  196. snakeHead.addPoint(1, 12);
  197. snakeHead.addPoint(1, 8);
  198. snakeHead.addPoint(3, 6);
  199. snakeHead.addPoint(3, 4);
  200. snakeHead.addPoint(6, 1);
  201. snakeHead.addPoint(9, 1);
  202. snakeHead.addPoint(12, 4);
  203. snakeHead.addPoint(12, 6);
  204. snakeHead.addPoint(14, 8);
  205. snakeHead.addPoint(14, 12);
  206. snakeHead.addPoint(12, 14);
  207. snakeHead.addPoint(11, 15);
  208.  
  209. snakeBody = new Polygon();
  210. snakeBody.addPoint(11, 0);
  211. snakeBody.addPoint(11, 15);
  212. snakeBody.addPoint(4, 15);
  213. snakeBody.addPoint(4, 0);
  214.  
  215. snakeElb1 = new Polygon();
  216. snakeElb1.addPoint(11, 0);
  217. snakeElb1.addPoint(11, 4);
  218. snakeElb1.addPoint(15, 4);
  219. snakeElb1.addPoint(15, 11);
  220. snakeElb1.addPoint(7, 11);
  221. snakeElb1.addPoint(4, 8);
  222. snakeElb1.addPoint(4, 0);
  223.  
  224. snakeElb2 = mirror(snakeElb1);
  225.  
  226. snakeTail = new Polygon();
  227. snakeTail.addPoint(11, 0);
  228. snakeTail.addPoint(8, 15);
  229. snakeTail.addPoint(7, 15);
  230. snakeTail.addPoint(4, 0);
  231.  
  232. mouseBody = new Polygon();
  233. mouseBody.addPoint(8, 1);
  234. mouseBody.addPoint(12, 5);
  235. mouseBody.addPoint(12, 6);
  236. mouseBody.addPoint(10, 7);
  237. mouseBody.addPoint(12, 9);
  238. mouseBody.addPoint(12, 12);
  239. mouseBody.addPoint(10, 14);
  240. mouseBody.addPoint(5, 14);
  241. mouseBody.addPoint(3, 12);
  242. mouseBody.addPoint(3, 9);
  243. mouseBody.addPoint(5, 7);
  244. mouseBody.addPoint(3, 6);
  245. mouseBody.addPoint(3, 5);
  246. mouseBody.addPoint(7, 1);
  247.  
  248. keyShape = new Polygon();
  249. keyShape.addPoint(1, 6);
  250. keyShape.addPoint(7, 6);
  251. keyShape.addPoint(9, 4);
  252. keyShape.addPoint(13, 4);
  253. keyShape.addPoint(15, 6);
  254. keyShape.addPoint(15, 10);
  255. keyShape.addPoint(13, 12);
  256. keyShape.addPoint(9, 12);
  257. keyShape.addPoint(7, 10);
  258. keyShape.addPoint(3, 10);
  259. keyShape.addPoint(3, 11);
  260. keyShape.addPoint(0, 11);
  261. keyShape.addPoint(0, 7);
  262.  
  263. // Initialize data.
  264.  
  265. highScore = 0;
  266. sound = true;
  267. snake = new Point[GRID_WIDTH * GRID_HEIGHT];
  268. for (i = 0; i < snake.length; i++)
  269. snake[i] = new Point(-1, -1);
  270. mouse = new Point[NUM_MICE];
  271. for (i = 0; i < NUM_MICE; i++)
  272. mouse[i] = new Point(-1, -1);
  273. key = new Point(-1, -1);
  274. lockKeys = false;
  275. initGame();
  276. endGame();
  277. for (i = 0; i < NUM_MICE; i++)
  278. killMouse(i);
  279. gameState = INIT;
  280. }
  281.  
  282. public void initGame() {
  283.  
  284. // Initialize game data.
  285.  
  286. score = 0;
  287. lives = NUM_LIVES;
  288. level = 0;
  289. levelTotal = 0;
  290. extraLife = EXTRA_LIFE;
  291. delay = MAX_DELAY;
  292. paused = false;
  293. initLevel();
  294. }
  295.  
  296. public void endGame() {
  297.  
  298. gameState = OVER;
  299. }
  300.  
  301. public void initLevel() {
  302.  
  303. int i;
  304.  
  305. // Advance level. Once we have gone thru each, start at the beginning and
  306. // increase speed.
  307.  
  308. level++;
  309. if (level > NUM_LEVELS) {
  310. level = 1;
  311. if (delay > MIN_DELAY)
  312. delay -= DELAY_INCR;
  313. }
  314.  
  315. // Level total for display.
  316.  
  317. levelTotal++;
  318.  
  319. // Initialize game data.
  320.  
  321. initBlocks();
  322. initSnake();
  323. for (i = 0; i < NUM_MICE; i++)
  324. initMouse(i);
  325. miceEaten = 0;
  326. miceNeeded = 3 * (NUM_MICE + NUM_LEVELS - level);
  327. keyActive = false;
  328. gameState = PLAY;
  329. }
  330.  
  331. public void endLevel() {
  332.  
  333. // Start counter to pause before changing level.
  334.  
  335. gameState = LEVEL;
  336. levelCounter = LEVEL_COUNT;
  337. }
  338.  
  339.  
  340. public void initLife() {
  341.  
  342. // Create a new snake.
  343.  
  344. killSnake();
  345. initSnake();
  346. gameState = PLAY;
  347. }
  348.  
  349. public void endLife() {
  350.  
  351. // Start counter to pause before starting a new snake.
  352.  
  353. gameState = END;
  354. endCounter = END_COUNT;
  355. }
  356.  
  357. public void start() {
  358.  
  359. if (loopThread == null) {
  360. loopThread = new Thread(this);
  361. loopThread.start();
  362. }
  363. if (!loaded && loadThread == null) {
  364. loadThread = new Thread(this);
  365. loadThread.start();
  366. }
  367. }
  368.  
  369. public void stop() {
  370.  
  371. if (loopThread != null) {
  372. loopThread.stop();
  373. loopThread = null;
  374. }
  375. if (loadThread != null) {
  376. loadThread.stop();
  377. loadThread = null;
  378. }
  379. }
  380.  
  381. public void run() {
  382.  
  383. int i;
  384. long startTime;
  385.  
  386. // Lower this thread's priority and get the current time.
  387.  
  388. Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  389. startTime = System.currentTimeMillis();
  390.  
  391. // Run thread for loading sounds.
  392.  
  393. if (!loaded && Thread.currentThread() == loadThread) {
  394. loadSounds();
  395. loaded = true;
  396. loadThread.stop();
  397. }
  398.  
  399. // This is the main loop.
  400.  
  401. while (Thread.currentThread() == loopThread) {
  402.  
  403. if (!paused) {
  404.  
  405. // Move snake and mice.
  406.  
  407. if (gameState == PLAY) {
  408. moveSnake();
  409. for (i = 0; i < NUM_MICE; i++)
  410. moveMouse(i);
  411. }
  412.  
  413. // Check the score and advance high score if necessary.
  414.  
  415. if (score > highScore)
  416. highScore = score;
  417.  
  418. // Add an extra life if score is high enough.
  419.  
  420. if (score >= extraLife) {
  421. lives++;
  422. extraLife += EXTRA_LIFE;
  423. }
  424.  
  425. // See if the snake was killed. If any lives are left, continue with
  426. // a new one.
  427.  
  428. if (gameState == END && --endCounter < 0)
  429. if (--lives == 0)
  430. endGame();
  431. else
  432. initLife();
  433.  
  434. // If enough mice have been eaten, show the key.
  435.  
  436. if (gameState == PLAY && miceEaten == miceNeeded && !keyActive) {
  437. if (loaded && sound)
  438. chimeSound.play();
  439. initKey();
  440. }
  441.  
  442. // If level was completed, go to the next one when the counter finishes.
  443.  
  444. if (gameState == LEVEL && --levelCounter < 0)
  445. initLevel();
  446. }
  447.  
  448. // Update the screen and set the timer for the next loop.
  449.  
  450. repaint();
  451. try {
  452. if (gameState == PLAY)
  453. startTime += delay;
  454. else
  455. startTime += MIN_DELAY;
  456. Thread.sleep(Math.max(0, startTime - System.currentTimeMillis()));
  457. }
  458. catch (InterruptedException e) {
  459. break;
  460. }
  461. }
  462. }
  463.  
  464. public void loadSounds() {
  465.  
  466. // Load all sound clips by playing and immediately stopping them.
  467.  
  468. try {
  469. bonkSound = getAudioClip(new URL(getCodeBase(), "bonk.au"));
  470. clipTotal++;
  471. munchSound = getAudioClip(new URL(getCodeBase(), "munch.au"));
  472. clipTotal++;
  473. squeakSound = getAudioClip(new URL(getCodeBase(), "squeak.au"));
  474. clipTotal++;
  475. chimeSound = getAudioClip(new URL(getCodeBase(), "chime.au"));
  476. clipTotal++;
  477. advanceSound = getAudioClip(new URL(getCodeBase(), "advance.au"));
  478. clipTotal++;
  479. }
  480. catch (MalformedURLException e) {}
  481.  
  482. try {
  483. bonkSound.play(); bonkSound.stop(); clipsLoaded++;
  484. repaint(); Thread.currentThread().sleep(MIN_DELAY);
  485. munchSound.play(); munchSound.stop(); clipsLoaded++;
  486. repaint(); Thread.currentThread().sleep(MIN_DELAY);
  487. squeakSound.play(); squeakSound.stop(); clipsLoaded++;
  488. repaint(); Thread.currentThread().sleep(MIN_DELAY);
  489. chimeSound.play(); chimeSound.stop(); clipsLoaded++;
  490. repaint(); Thread.currentThread().sleep(MIN_DELAY);
  491. advanceSound.play(); advanceSound.stop(); clipsLoaded++;
  492. repaint(); Thread.currentThread().sleep(MIN_DELAY);
  493. }
  494. catch (InterruptedException e) {}
  495. }
  496.  
  497. public void keyPressed(KeyEvent e) {
  498.  
  499. char c;
  500.  
  501. // Check if any cursor keys have been pressed and set flags.
  502. // Check if any cursor keys have been pressed and set direction but don't
  503. // allow a reversal of direction.
  504.  
  505. if (!paused && !lockKeys) {
  506. if (e.getKeyCode() == KeyEvent.VK_LEFT && lastDirection != RIGHT)
  507. direction = LEFT;
  508. else if (e.getKeyCode() == KeyEvent.VK_RIGHT && lastDirection != LEFT && lastDirection != NONE)
  509. direction = RIGHT;
  510. else if (e.getKeyCode() == KeyEvent.VK_UP && lastDirection != DOWN)
  511. direction = UP;
  512. else if (e.getKeyCode() == KeyEvent.VK_DOWN && lastDirection != UP)
  513. direction = DOWN;
  514. }
  515.  
  516. // Allow upper or lower case characters for remaining keys.
  517.  
  518. c = Character.toLowerCase(e.getKeyChar());
  519.  
  520. // 'M' key: toggle sound.
  521.  
  522. if (c == 'm') {
  523. if (sound) {
  524. bonkSound.stop();
  525. munchSound.stop();
  526. squeakSound.stop();
  527. chimeSound.stop();
  528. advanceSound.stop();
  529. }
  530. sound = !sound;
  531. }
  532.  
  533. // 'P' key: toggle pause mode.
  534.  
  535. if (c == 'p')
  536. paused = !paused;
  537.  
  538. // 'S' key: start the game, if not already in progress.
  539.  
  540. if (loaded && c == 's' && (gameState == INIT || gameState == OVER))
  541. initGame();
  542.  
  543. // 'HOME' key: jump to web site (undocumented).
  544.  
  545. if (e.getKeyCode() == KeyEvent.VK_HOME)
  546. try {
  547. getAppletContext().showDocument(new URL(copyLink));
  548. }
  549. catch (Exception excp) {}
  550. }
  551.  
  552. public void keyReleased(KeyEvent e) {}
  553.  
  554. public void keyTyped(KeyEvent e) {}
  555.  
  556. public void initBlocks() {
  557.  
  558. int i, j;
  559.  
  560. // Clear the grid.
  561.  
  562. for (i = 0; i < GRID_WIDTH; i++)
  563. for (j = 0; j < GRID_HEIGHT; j++)
  564. grid[i][j] = EMPTY | NONE | SQUARE;
  565.  
  566. // Add outer walls.
  567.  
  568. for (i = 0; i < GRID_WIDTH; i++) {
  569. grid[i][0] = BLOCK | NONE | SQUARE;
  570. grid[i][GRID_HEIGHT - 1] = BLOCK | NONE | SQUARE;
  571. }
  572. for (j = 1; j < GRID_HEIGHT - 1; j++) {
  573. grid[0][j] = BLOCK | NONE | SQUARE;
  574. grid[GRID_WIDTH - 1][j] = BLOCK | NONE | SQUARE;
  575. }
  576.  
  577. // Add inner walls depending on current level.
  578.  
  579. if (level == 2 || level == 4) {
  580. i = GRID_WIDTH / 4;
  581. for (j = GRID_HEIGHT / 4; j <= GRID_HEIGHT / 2 - 3; j++) {
  582. grid[i][j] = BLOCK | NONE | SQUARE;
  583. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  584. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  585. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  586. }
  587. j = GRID_HEIGHT / 4;
  588. for (i = GRID_WIDTH / 4; i <= GRID_WIDTH / 2 - 3; i++) {
  589. grid[i][j] = BLOCK | NONE | SQUARE;
  590. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  591. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  592. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  593. }
  594. }
  595.  
  596. if (level == 3) {
  597. i = GRID_WIDTH / 2;
  598. for (j = 0; j <= 3; j++) {
  599. grid[i][j] = BLOCK | NONE | SQUARE;
  600. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  601. }
  602. }
  603.  
  604. if (level == 3 || level == 5) {
  605. j = GRID_HEIGHT / 4;
  606. for (i = 5; i <= GRID_WIDTH / 4; i++) {
  607. grid[i][j] = BLOCK | NONE | SQUARE;
  608. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  609. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  610. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  611. }
  612. i = GRID_WIDTH / 4;
  613. for (j = GRID_HEIGHT / 4; j <= GRID_HEIGHT / 2; j++) {
  614. grid[i][j] = BLOCK | NONE | SQUARE;
  615. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  616. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  617. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  618. }
  619. j = GRID_HEIGHT / 2;
  620. for (i = 0; i <= GRID_WIDTH / 4 - 5; i++) {
  621. grid[i][j] = BLOCK | NONE | SQUARE;
  622. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  623. }
  624. }
  625.  
  626. if (level == 4) {
  627. i = 4;
  628. for (j = GRID_HEIGHT / 2 - 2; j <= GRID_HEIGHT / 2; j++) {
  629. grid[i][j] = BLOCK | NONE | SQUARE;
  630. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  631. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  632. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  633. }
  634. i = GRID_WIDTH / 2;
  635. for (j = 0; j <= 2; j++) {
  636. grid[i][j] = BLOCK | NONE | SQUARE;
  637. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  638. }
  639. }
  640.  
  641. if (level == 5) {
  642. i = 3 * GRID_WIDTH / 8;
  643. for (j = 4; j <= GRID_HEIGHT / 3 - 1; j++) {
  644. grid[i][j] = BLOCK | NONE | SQUARE;
  645. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  646. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  647. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  648. }
  649. j = GRID_HEIGHT / 3 - 1;
  650. for (i = 3 * GRID_WIDTH / 8; i <= GRID_WIDTH / 2; i++) {
  651. grid[i][j] = BLOCK | NONE | SQUARE;
  652. grid[GRID_WIDTH - 1 - i][j] = BLOCK | NONE | SQUARE;
  653. grid[i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  654. grid[GRID_WIDTH - 1 - i][GRID_HEIGHT - 1 - j] = BLOCK | NONE | SQUARE;
  655. }
  656. }
  657. }
  658.  
  659. public void initSnake() {
  660.  
  661. int i, j;
  662. int m, n;
  663.  
  664. // Create a new snake in the center of the grid and reset cell list.
  665.  
  666. i = GRID_WIDTH / 2;
  667. j = GRID_HEIGHT / 2;
  668.  
  669. snake[4].x = i - 2; snake[4].y = j;
  670. snake[3].x = i - 1; snake[3].y = j;
  671. snake[2].x = i - 0; snake[2].y = j;
  672. snake[1].x = i + 1; snake[1].y = j;
  673. snake[0].x = i + 2; snake[0].y = j;
  674.  
  675. headPtr = 4;
  676. tailPtr = 0;
  677.  
  678. grid[i - 2][j] = SNAKE | LEFT | SNAKEHEAD;
  679. grid[i - 1][j] = SNAKE | LEFT | SNAKEBODY;
  680. grid[i][j] = SNAKE | LEFT | SNAKEBODY;
  681. grid[i + 1][j] = SNAKE | LEFT | SNAKEBODY;
  682. grid[i + 2][j] = SNAKE | LEFT | SNAKETAIL;
  683.  
  684. // Clear snake direction.
  685.  
  686. direction = NONE;
  687. lastDirection = NONE;
  688.  
  689. // Relocate any mice that were overwritten.
  690.  
  691. for (m = 0; m < NUM_MICE; m++)
  692. for (n = -2; n <= 2 ; n++)
  693. if (mouse[m].x == i + n && mouse[m].y == j)
  694. initMouse(m);
  695.  
  696. // Relocate key if overwritten.
  697.  
  698. if (keyActive)
  699. for (n = -2; n <= 2 ; n++)
  700. if (key.x == i + n && key.y == j)
  701. initKey();
  702. }
  703.  
  704. public void moveSnake() {
  705.  
  706. Point pt;
  707. int i, j;
  708. int k;
  709. int c;
  710. int d;
  711.  
  712. // Lock cursor keys to prevent the current direction from being changed
  713. // until we are done processing it.
  714.  
  715. lockKeys = true;
  716.  
  717. // Move snake's head into the next cell based on current direction.
  718.  
  719. pt = snake[headPtr];
  720. i = pt.x;
  721. j = pt.y;
  722. switch (direction) {
  723. case LEFT:
  724. i--;
  725. break;
  726. case RIGHT:
  727. i++;
  728. break;
  729. case UP:
  730. j--;
  731. break;
  732. case DOWN:
  733. j++;
  734. break;
  735. default:
  736. lockKeys = false;
  737. return;
  738. }
  739.  
  740. // Unlock cursor keys and save direction.
  741.  
  742. lockKeys = false;
  743. lastDirection = direction;
  744.  
  745. // Skip if no direction given.
  746.  
  747. if (direction == NONE)
  748. return;
  749.  
  750. // Get the type of the new cell.
  751.  
  752. c = grid[i][j] & TYPE_MASK;
  753.  
  754. // Check if we hit a wall or ourselves.
  755.  
  756. if (c == BLOCK || c == SNAKE) {
  757. if (loaded && sound)
  758. bonkSound.play();
  759. endLife();
  760. return;
  761. }
  762.  
  763. // Replace current head with the appropriate body part.
  764.  
  765. d = grid[pt.x][pt.y] & DIR_MASK;
  766. if (d == direction)
  767. grid[pt.x][pt.y] = SNAKE | d | SNAKEBODY;
  768. else if (d == LEFT && direction == UP)
  769. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB1;
  770. else if (d == UP && direction == RIGHT)
  771. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB1;
  772. else if (d == RIGHT && direction == DOWN)
  773. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB1;
  774. else if (d == DOWN && direction == LEFT)
  775. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB1;
  776. else if (d == UP && direction == LEFT)
  777. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB2;
  778. else if (d == LEFT && direction == DOWN)
  779. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB2;
  780. else if (d == DOWN && direction == RIGHT)
  781. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB2;
  782. else if (d == RIGHT && direction == UP)
  783. grid[pt.x][pt.y] = SNAKE | direction | SNAKEELB2;
  784.  
  785. // Change the new cell to a snake's head and set it in the cell list.
  786.  
  787. grid[i][j] = SNAKE | direction | SNAKEHEAD;
  788. if (++headPtr >= snake.length)
  789. headPtr = 0;
  790. snake[headPtr].x = i;
  791. snake[headPtr].y = j;
  792.  
  793. // If we got a mouse, bump the score and create a new one. Otherwise,
  794. // move the tail.
  795.  
  796. if (c == MOUSE) {
  797. score += MOUSE_POINTS;
  798. if (loaded && sound)
  799. munchSound.play();
  800. for (k = 0; k < NUM_MICE; k++)
  801. if (mouse[k].x == i && mouse[k].y == j)
  802. initMouse(k);
  803. miceEaten++;
  804. }
  805. else {
  806. pt = snake[tailPtr];
  807. grid[pt.x][pt.y] = EMPTY & NONE & SQUARE;
  808. if (++tailPtr >= snake.length)
  809. tailPtr = 0;
  810. pt = snake[tailPtr];
  811. d = grid[pt.x][pt.y] & DIR_MASK;
  812. grid[pt.x][pt.y] = SNAKE | d | SNAKETAIL;
  813. }
  814.  
  815. // Check if we got the key. If so, end the current level.
  816.  
  817. if (c == KEY) {
  818. score += LEVEL_POINTS;
  819. if (loaded && sound)
  820. advanceSound.play();
  821. endLevel();
  822. }
  823. }
  824.  
  825. public void killSnake() {
  826.  
  827. Point pt;
  828. int n;
  829.  
  830. // Remove snake from the grid.
  831.  
  832. n = headPtr + 1;
  833. if (n >= snake.length)
  834. n = 0;
  835. while(tailPtr != n) {
  836. pt = snake[tailPtr];
  837. grid[pt.x][pt.y] = EMPTY | NONE | SQUARE;
  838. if (++tailPtr >= snake.length)
  839. tailPtr = 0;
  840. }
  841. }
  842.  
  843. public void initMouse(int n) {
  844.  
  845. int i, j;
  846. int d;
  847.  
  848. // Find an empty cell.
  849.  
  850. do {
  851. i = (int) (Math.random() * GRID_WIDTH);
  852. j = (int) (Math.random() * GRID_HEIGHT);
  853. } while ((grid[i][j] & TYPE_MASK) != EMPTY);
  854.  
  855. // Get a random direction.
  856.  
  857. d = (int) (Math.random() * 4) + 1;
  858. d <<= 8;
  859.  
  860. // Save mouse position.
  861.  
  862. mouse[n].x = i;
  863. mouse[n].y = j;
  864.  
  865. // Set the cell with mouse data.
  866.  
  867. grid[i][j] = MOUSE | d | MOUSEBODY;
  868. }
  869.  
  870. public void moveMouse(int n) {
  871.  
  872. int i, j;
  873. int d;
  874. int m;
  875.  
  876. // Skip move at random.
  877.  
  878. if (Math.random() > 0.25)
  879. return;
  880.  
  881. // Skip move if mouse is dead.
  882.  
  883. if (mouse[n].x == -1 || mouse[n].y == -1)
  884. return;
  885.  
  886. // Toss in a random squeak.
  887.  
  888. if (loaded && sound && Math.random() > 0.975)
  889. squeakSound.play();
  890.  
  891. // Get a random direction.
  892.  
  893. d = (int) (Math.random() * 5);
  894. d <<= 8;
  895.  
  896. // Don't allow a reversal of direction.
  897.  
  898. m = grid[mouse[n].x][mouse[n].y] & DIR_MASK;
  899. if ((m == LEFT && d == RIGHT) ||
  900. (m == RIGHT && d == LEFT) ||
  901. (m == UP && d == DOWN) ||
  902. (m == DOWN && d == UP))
  903. return;
  904.  
  905. i = mouse[n].x;
  906. j = mouse[n].y;
  907. switch (d) {
  908. case LEFT:
  909. i--;
  910. break;
  911. case RIGHT:
  912. i++;
  913. break;
  914. case UP:
  915. j--;
  916. break;
  917. case DOWN:
  918. j++;
  919. break;
  920. default:
  921. return;
  922. }
  923.  
  924. // See if the new cell is empty. If not, skip move.
  925.  
  926. if ((grid[i][j] & TYPE_MASK) != EMPTY)
  927. return;
  928.  
  929. // Clear mouse from old cell and move to the new one.
  930.  
  931. grid[mouse[n].x][mouse[n].y] = EMPTY | NONE | SQUARE;
  932. mouse[n].x = i;
  933. mouse[n].y = j;
  934. grid[i][j] = MOUSE | d | MOUSEBODY;
  935. }
  936.  
  937. public void killMouse(int n) {
  938.  
  939. // Clear mouse from grid and set coordinates to (-1, -1) so we know it is
  940. // dead.
  941.  
  942. grid[mouse[n].x][mouse[n].y] = EMPTY | NONE | SQUARE;
  943. mouse[n].x = -1;
  944. mouse[n].y = -1;
  945. }
  946.  
  947. public void initKey() {
  948.  
  949. int i, j;
  950.  
  951. // Find an empty cell.
  952.  
  953. do {
  954. i = (int) (Math.random() * GRID_WIDTH);
  955. j = (int) (Math.random() * GRID_HEIGHT);
  956. } while ((grid[i][j] & TYPE_MASK) != EMPTY);
  957.  
  958. // Save key position.
  959.  
  960. key.x = i;
  961. key.y = j;
  962.  
  963. // Set the cell with key data and set the flag to show it's been added.
  964.  
  965. grid[i][j] = KEY | NONE | KEYSHAPE;
  966. keyActive = true;
  967. }
  968.  
  969. public Polygon translate(Polygon p, int dx, int dy) {
  970.  
  971. Polygon polygon;
  972. int i;
  973.  
  974. // Returns the polygon created by translating the given shape.
  975.  
  976. polygon = new Polygon();
  977. for (i = 0; i < p.npoints; i++)
  978. polygon.addPoint(p.xpoints[i] + dx, p.ypoints[i] + dy);
  979.  
  980. return polygon;
  981. }
  982.  
  983. public Polygon rotate(Polygon p, int d) {
  984.  
  985. Polygon polygon;
  986. int i;
  987.  
  988. // Returns the polygon created by rotating the given shape in 90 deg. increments.
  989.  
  990. polygon = new Polygon();
  991. for (i = 0; i < p.npoints; i++)
  992. switch (d) {
  993. case LEFT:
  994. polygon.addPoint(p.ypoints[i], (GRID_SIZE - 1) - p.xpoints[i]);
  995. break;
  996. case RIGHT:
  997. polygon.addPoint((GRID_SIZE - 1) - p.ypoints[i], p.xpoints[i]);
  998. break;
  999. case DOWN:
  1000. polygon.addPoint((GRID_SIZE - 1) - p.xpoints[i], (GRID_SIZE - 1) - p.ypoints[i]);
  1001. break;
  1002. default:
  1003. polygon.addPoint(p.xpoints[i], p.ypoints[i]);
  1004. break;
  1005. }
  1006.  
  1007. return polygon;
  1008. }
  1009.  
  1010. public Polygon mirror(Polygon p) {
  1011.  
  1012. Polygon polygon;
  1013. int i;
  1014.  
  1015. // Returns the polygon created by mirroring the given shape.
  1016.  
  1017. polygon = new Polygon();
  1018. for (i = 0; i < p.npoints; i++)
  1019. polygon.addPoint((GRID_SIZE - 1) - p.xpoints[i], p.ypoints[i]);
  1020.  
  1021. return polygon;
  1022. }
  1023.  
  1024. public Color fade(Color s, Color e, double pct) {
  1025.  
  1026. int r, g, b;
  1027.  
  1028. // Fade the starting color to the ending color by the given percentage.
  1029.  
  1030. if (pct < 0.0)
  1031. return e;
  1032. if (pct > 1.0)
  1033. return s;
  1034.  
  1035. r = e.getRed() + (int) Math.round(pct * (s.getRed() - e.getRed()));
  1036. g = e.getGreen() + (int) Math.round(pct * (s.getGreen() - e.getGreen()));
  1037. b = e.getBlue() + (int) Math.round(pct * (s.getBlue() - e.getBlue()));
  1038.  
  1039. return(new Color(r, g, b));
  1040. }
  1041.  
  1042. public void update(Graphics g) {
  1043.  
  1044. paint(g);
  1045. }
  1046.  
  1047. public void paint(Graphics g) {
  1048.  
  1049. Dimension d = getSize();
  1050. int width, height;
  1051. int xOff, yOff;
  1052. int i, j;
  1053. int m;
  1054. int n;
  1055. Polygon p;
  1056. String s;
  1057. int x, y;
  1058. int w, h;
  1059.  
  1060. // Create the off screen graphics context, if no good one exists.
  1061.  
  1062. if (offGraphics == null || d.width != offDimension.width || d.height != offDimension.height) {
  1063. offDimension = d;
  1064. offImage = createImage(d.width, d.height);
  1065. offGraphics = offImage.getGraphics();
  1066. }
  1067.  
  1068. // Fill in applet background.
  1069.  
  1070. offGraphics.setColor(bgColor);
  1071. offGraphics.fillRect(0, 0, d.width, d.height);
  1072.  
  1073. // Center game area.
  1074.  
  1075. width = GRID_WIDTH * GRID_SIZE;
  1076. height = GRID_HEIGHT * GRID_SIZE;
  1077. xOff = (d.width - width) / 2;
  1078. yOff = (d.height - (height + 2 * fontHeight)) / 2;
  1079. offGraphics.translate(xOff, yOff);
  1080.  
  1081. // Fill in playing field.
  1082.  
  1083. if (gameState == LEVEL)
  1084. offGraphics.setColor(fade(fieldColor, bgColor, (double) levelCounter / (double) LEVEL_COUNT));
  1085. else
  1086. offGraphics.setColor(fieldColor);
  1087. offGraphics.fillRect(0, 0, GRID_WIDTH * GRID_SIZE, GRID_HEIGHT * GRID_SIZE);
  1088.  
  1089. // Fill in each grid cell with the appropriate shape.
  1090.  
  1091. for (i = 0; i < GRID_WIDTH; i++)
  1092. for (j = 0; j < GRID_HEIGHT; j++)
  1093. switch (grid[i][j] & TYPE_MASK) {
  1094.  
  1095. case EMPTY:
  1096. break;
  1097.  
  1098. case BLOCK:
  1099. if (gameState == LEVEL)
  1100. offGraphics.setColor(fade(blockColor, bgColor, (double) levelCounter / (double) LEVEL_COUNT));
  1101. else
  1102. offGraphics.setColor(blockColor);
  1103. offGraphics.fillRect(i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
  1104. offGraphics.setColor(bgColor);
  1105. offGraphics.drawRect(i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
  1106. break;
  1107.  
  1108. case SNAKE:
  1109. n = grid[i][j] & SHAPE_MASK;
  1110. switch (n) {
  1111. case SNAKEHEAD:
  1112. p = snakeHead;
  1113. break;
  1114. case SNAKEBODY:
  1115. p = snakeBody;
  1116. break;
  1117. case SNAKEELB1:
  1118. p = snakeElb1;
  1119. break;
  1120. case SNAKEELB2:
  1121. p = snakeElb2;
  1122. break;
  1123. case SNAKETAIL:
  1124. p = snakeTail;
  1125. break;
  1126. default:
  1127. p = snakeHead;
  1128. break;
  1129. }
  1130. p = translate(rotate(p, grid[i][j] & DIR_MASK), i * GRID_SIZE, j * GRID_SIZE);
  1131. if (gameState == LEVEL)
  1132. offGraphics.setColor(fade(snakeColor, bgColor, (double) levelCounter / (double) LEVEL_COUNT));
  1133. else if (gameState == END || gameState == OVER)
  1134. offGraphics.setColor(fade(snakeColor, fieldColor, (double) endCounter / (double) END_COUNT));
  1135. else
  1136. offGraphics.setColor(snakeColor);
  1137. offGraphics.fillPolygon(p);
  1138. offGraphics.drawPolygon(p);
  1139. offGraphics.drawLine(p.xpoints[p.npoints - 1], p.ypoints[p.npoints - 1], p.xpoints[0], p.ypoints[0]);
  1140. if (gameState == END || gameState == OVER)
  1141. offGraphics.setColor(fade(bgColor, fieldColor, (double) endCounter / (double) END_COUNT));
  1142. else
  1143. offGraphics.setColor(bgColor);
  1144. if (n == SNAKEHEAD || n == SNAKETAIL)
  1145. for (m = 0; m < p.npoints - 1; m++)
  1146. offGraphics.drawLine(p.xpoints[m], p.ypoints[m], p.xpoints[m + 1], p.ypoints[m + 1]);
  1147. if (n == SNAKEBODY) {
  1148. offGraphics.drawLine(p.xpoints[0], p.ypoints[0], p.xpoints[1], p.ypoints[1]);
  1149. offGraphics.drawLine(p.xpoints[2], p.ypoints[2], p.xpoints[3], p.ypoints[3]);
  1150. }
  1151. if (n == SNAKEELB1 || n == SNAKEELB2) {
  1152. offGraphics.drawLine(p.xpoints[0], p.ypoints[0], p.xpoints[1], p.ypoints[1]);
  1153. offGraphics.drawLine(p.xpoints[1], p.ypoints[1], p.xpoints[2], p.ypoints[2]);
  1154. offGraphics.drawLine(p.xpoints[3], p.ypoints[3], p.xpoints[4], p.ypoints[4]);
  1155. offGraphics.drawLine(p.xpoints[4], p.ypoints[4], p.xpoints[5], p.ypoints[5]);
  1156. offGraphics.drawLine(p.xpoints[5], p.ypoints[5], p.xpoints[6], p.ypoints[6]);
  1157. }
  1158. break;
  1159.  
  1160. case MOUSE:
  1161. if (gameState == LEVEL)
  1162. offGraphics.setColor(fade(mouseColor, bgColor, (double) levelCounter / (double) LEVEL_COUNT));
  1163. else
  1164. offGraphics.setColor(mouseColor);
  1165. p = translate(rotate(mouseBody, grid[i][j] & DIR_MASK), i * GRID_SIZE, j * GRID_SIZE);
  1166. offGraphics.fillPolygon(p);
  1167. offGraphics.setColor(bgColor);
  1168. offGraphics.drawPolygon(p);
  1169. offGraphics.drawLine(p.xpoints[p.npoints - 1], p.ypoints[p.npoints - 1], p.xpoints[0], p.ypoints[0]);
  1170. break;
  1171.  
  1172. case KEY:
  1173. p = translate(rotate(keyShape, grid[i][j] & DIR_MASK), i * GRID_SIZE, j * GRID_SIZE);
  1174. offGraphics.setColor(keyColor);
  1175. offGraphics.fillPolygon(p);
  1176. offGraphics.setColor(bgColor);
  1177. offGraphics.drawPolygon(p);
  1178. offGraphics.drawLine(p.xpoints[p.npoints - 1], p.ypoints[p.npoints - 1], p.xpoints[0], p.ypoints[0]);
  1179. break;
  1180.  
  1181. default:
  1182. break;
  1183. }
  1184.  
  1185. // Outline playing field.
  1186.  
  1187. offGraphics.setColor(fieldColor);
  1188. offGraphics.drawRect(0, 0, GRID_WIDTH * GRID_SIZE, GRID_HEIGHT * GRID_SIZE - 1);
  1189.  
  1190. // Display status and messages.
  1191.  
  1192. offGraphics.setFont(font);
  1193.  
  1194. offGraphics.setColor(fieldColor);
  1195. i = height - 1;
  1196. j = height + 3 * fontHeight / 2;
  1197. offGraphics.drawRect(0, i, width, 2 * fontHeight);
  1198.  
  1199. offGraphics.setColor(fgColor);
  1200. s = "Score: " + score;
  1201. offGraphics.drawString(s, fontWidth, j);
  1202. s = "Level: " + levelTotal;
  1203. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 4, j);
  1204. s = "Lives: " + lives;
  1205. offGraphics.drawString(s, 3 * (width - fm.stringWidth(s)) / 4, j);
  1206. s = "High: " + highScore;
  1207. offGraphics.drawString(s, width - (fontWidth + fm.stringWidth(s)), j);
  1208. if (paused) {
  1209. s = "Paused";
  1210. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, j);
  1211. }
  1212. else if (!sound) {
  1213. s = "Muted";
  1214. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, j);
  1215. }
  1216.  
  1217. if (gameState == INIT || gameState == OVER) {
  1218. s = copyName;
  1219. offGraphics.setColor(bgColor);
  1220. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, height / 3 - 3 * fontHeight + 1);
  1221. offGraphics.setColor(fgColor);
  1222. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, height / 3 - 3 * fontHeight);
  1223. s = copyVers;
  1224. offGraphics.setColor(bgColor);
  1225. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, height / 3 - 2 * fontHeight + 1);
  1226. offGraphics.setColor(fgColor);
  1227. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, height / 3 - 2 * fontHeight);
  1228. s = copyInfo;
  1229. offGraphics.setColor(bgColor);
  1230. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, height / 3 + 1);
  1231. offGraphics.setColor(fgColor);
  1232. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, height / 3);
  1233. s = copyLink;
  1234. offGraphics.setColor(bgColor);
  1235. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, height / 3 + fontHeight + 1);
  1236. offGraphics.setColor(fgColor);
  1237. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, height / 3 + fontHeight);
  1238. if (!loaded) {
  1239. s = "Loading sounds...";
  1240. w = 4 * fontWidth + fm.stringWidth(s);
  1241. h = fontHeight;
  1242. x = (width - w) / 2;
  1243. y = 2 * height / 3 - fm.getMaxAscent();
  1244. offGraphics.setColor(fieldColor);
  1245. offGraphics.fillRect(x, y, w, h);
  1246. offGraphics.setColor(fade(fieldColor, bgColor, 0.5));
  1247. if (clipTotal > 0)
  1248. offGraphics.fillRect(x, y, (int) (w * clipsLoaded / clipTotal), h);
  1249. offGraphics.setColor(bgColor);
  1250. offGraphics.drawRect(x + 1, y + 1, w, h);
  1251. offGraphics.drawString(s, x + 2 * fontWidth + 1, y + fm.getMaxAscent() + 1);
  1252. offGraphics.setColor(fgColor);
  1253. offGraphics.drawRect(x, y, w, h);
  1254. offGraphics.drawString(s, x + 2 * fontWidth, y + fm.getMaxAscent());
  1255. }
  1256. else {
  1257. s = "Game Over - 'S' to Start";
  1258. offGraphics.setColor(bgColor);
  1259. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, 2 * height / 3 + 1);
  1260. offGraphics.setColor(fgColor);
  1261. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, 2 * height / 3);
  1262. }
  1263. }
  1264. if (gameState == LEVEL) {
  1265. s = "Advancing to Level " + (levelTotal + 1);
  1266. offGraphics.setColor(bgColor);
  1267. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2 + 1, height / 2 + 1);
  1268. offGraphics.setColor(fgColor);
  1269. offGraphics.drawString(s, (width - fm.stringWidth(s)) / 2, height / 2);
  1270. }
  1271.  
  1272. // Copy the off screen buffer to the screen.
  1273.  
  1274. offGraphics.translate(-xOff, -yOff);
  1275. g.drawImage(offImage, 0, 0, this);
  1276. }
  1277. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement