/* This program and its graphics are copyright (c) 1996 by Ethan Koehler. -- See the 'readme.txt' file for info on the appropriate parameters in HTML -- Please DO NOT modify and redistribute this program under the name "Daleks!" without consent of the author. If you make modifications to my design, please give it another name so as not to confuse the two programs. The code and the techniques used in Daleks! may otherwise be used freely. And the lovely graphics are also fair game. Share and enjoy. Questions or comments? Send e-mail: 5q89koehlere@vms.csd.mu.edu */ import java.awt.*; import java.applet.*; public class daleks14 extends java.applet.Applet implements Runnable { // program control flags & other stuff boolean screwdriverUsed = false; // did the player use screwdriver? boolean lastStand = false; // player making a "last stand"? boolean allDead = false; // are all the daleks dead? boolean animLevel = false; // animate a level change? boolean animRegen = false; // animate a regeneration? boolean animIntro = false; // is the intro screen running? boolean animTele = false; // animate teleportation to new location? boolean newRubble = false; // is there new rubble on the board? boolean doneLoading = false; // are pictures done loading? boolean levelComplete = false; // has current level been cleared? boolean playerDead = false; // is the player dead? Thread kicker = null; // used to kick off animation thread MediaTracker tracker; // used to wait until pics are loaded int currentPic = 0; // current picture being loaded by tracker animatedIntroClass animateIntro = new animatedIntroClass(); // intro screen object int numDaleks = 0; // number of daleks on current level int levelMultiple = 4; // number of daleks added each level int baseNumDaleks = 2; // minimum number of daleks every level int highScore = 150; // player's high score this session int level = 1; // current level number int maxX = 30; // number of "squares" horizontally on board int maxY = 20; // number of "squares" vertically int screwdrivers = 2; // number of sonic screwdrivers remaining int score = 0; // score of current game // vars to hold and adjust GIF images int imgH = 20; // height in pixels of dalek pictures (from HTML) int imgW = 20; // width of dalek pictures (from HTML) Image dalekPic[] = new Image[2]; // left- and right-facing dalek pics Image doctorPic[] = new Image[10]; // left- and right-facing player pics (5 pairs) int whichDoc = 0; // which doctor pic should be displayed? (depends on level) Image rubblePic[] = new Image[2]; // left- and right-facing dalek rubble piles Image deadPic; // graphic for "dead" player Image digit[] = new Image[10]; // graphics for digits 0 .. 9 Image nextScreen; // behind-the-scenes bitmap Graphics offScreenGC; // "graphics context" of the off-screen bitmap int faceLeft = 0; // pseudo-constants int faceRight = 1; // " // variables holding player position and status String title, flyingWidget; // strings to hold values from param tags int numWidgets = 50; // number of flying "widgets" on title screen int drStartX = 15; // horizontal starting position for player int drStartY = 10; // vertical starting position for player int drX; // current player horizontal position int drY; // current player vertical position int oldX, oldY; // last coordinates occupied by player int drF = faceLeft; // starting orientation (left or right) of player boolean drA = true; // is the player still alive? // arrays for dalek positions and status int dalX[]; // dalek X position on board int dalY[]; // dalek Y position on board int dalF[]; // facing direction (0=left, 1=right) int maxEnemies = 100; // maximum number of enemies allowed boolean dalR[] = new boolean[100]; // is this dalek rubbled? boolean dalA[] = new boolean[100]; // is this dalek alive? //--------------------------------------------------------------- // "daleks" Class Methods //--------------------------------------------------------------- public boolean mouseDown(Event evt, int x, int y) { repaint(); return false; } public synchronized boolean keyDown(Event evt, int x) { if (doneLoading) handleKeyPress(x); return false; } public void handleKeyPress(int whichKey) { if (animIntro) { // if the intro screen is running.. animIntro = false; kicker.stop(); // stop the intro animation thread resetGame(); // reset the game data setupBoard(); // initialize next level repaint(); } else if (levelComplete) { // if this level was cleared.. oldX = drX; oldY = drY; animLevel = true; repaint(); setupBoard(); repaint(); } else if (playerDead) { // player died.. playerDead = false; prepareScreen(); animateIntro.updateBar(nextScreen); animateIntro.startFadeIn(); animateIntro.start(); animIntro = true; repaint(); } else { // player is still alive and daleks remain.. char ASCIImove = (char)whichKey; boolean validMove = movePlayer(ASCIImove); if (validMove) { if (lastStand) repaint(); else { if (screwdriverUsed) { calcSonic(); play(getCodeBase(), "sonic.au"); } moveDaleks(); if (newRubble) play(getCodeBase(), "crash.au"); } } repaint(); checkDaleks(); if ((drA) && (allDead)) levelComplete = true; else if (!drA) { // prepareScreen(); // daleks may die during player's final move, so.... // repaint(); // this ensures the *latest* high score is displayed playerDead = true; } } } public void getHTMLParameters() { // read the parameters within the HTML applet tags if (getParameter("maxX") != null) maxX = Integer.parseInt(getParameter("maxX")); if (getParameter("maxY") != null) maxY = Integer.parseInt(getParameter("maxY")); if (getParameter("imgH") != null) imgH = Integer.parseInt(getParameter("imgH")); if (getParameter("imgW") != null) imgW = Integer.parseInt(getParameter("imgW")); if (getParameter("levelMultiple") != null) levelMultiple = Integer.parseInt(getParameter("levelMultiple")); if (getParameter("baseNum") != null) baseNumDaleks = Integer.parseInt(getParameter("baseNum")); if (getParameter("maxEnemies") != null) maxEnemies = Integer.parseInt(getParameter("maxEnemies")); if (getParameter("numWidgets") != null) numWidgets = Integer.parseInt(getParameter("numWidgets")); if (getParameter("flyingWidget") != null) flyingWidget = getParameter("flyingWidget"); else flyingWidget = "?"; if (getParameter("title") != null) title = getParameter("title"); else title = "Daleks!"; } public void init() { // get parameters from the calling HTML file getHTMLParameters(); // initialize dalek arrays dalX = new int[maxEnemies]; dalY = new int[maxEnemies]; dalF = new int[maxEnemies]; drStartX = maxX / 2; drStartY = maxY / 2; // create enough room to fit gameboard and status bar resize(maxX*imgW,maxY*imgH+25); // load game graphics doctorPic[0] = getImage(getCodeBase(),"dw1l.gif"); doctorPic[1] = getImage(getCodeBase(),"dw1r.gif"); doctorPic[2] = getImage(getCodeBase(),"dw2l.gif"); doctorPic[3] = doctorPic[2]; doctorPic[4] = getImage(getCodeBase(),"dw3l.gif"); doctorPic[5] = doctorPic[4]; doctorPic[6] = getImage(getCodeBase(),"dw4l.gif"); doctorPic[7] = getImage(getCodeBase(),"dw4r.gif"); doctorPic[8] = getImage(getCodeBase(),"dw5l.gif"); doctorPic[9] = getImage(getCodeBase(),"dw5r.gif"); dalekPic[0] = getImage(getCodeBase(),"dalekl.gif"); dalekPic[1] = getImage(getCodeBase(),"dalekr.gif"); rubblePic[0] = getImage(getCodeBase(),"daldl.gif"); rubblePic[1] = getImage(getCodeBase(),"daldr.gif"); deadPic = getImage(getCodeBase(),"drdead.gif"); // load graphic digits for (int j=0; j<10; j++) digit[j] = getImage(getCodeBase(),"green"+j+".gif"); tracker = new MediaTracker(this); for (int j=0; j<10; j++) { tracker.addImage(doctorPic[j], j); tracker.addImage(digit[j], j+10); } for (int j=0; j<2; j++) { tracker.addImage(dalekPic[j], 20+j); tracker.addImage(rubblePic[j], 22+j); } tracker.addImage(deadPic, 24); // start loading images tracker.checkAll(true); // create the off-screen bitmap nextScreen = createImage(maxX*imgW,maxY*imgH+25); offScreenGC = nextScreen.getGraphics(); prepareScreen(); animateIntro.setInfo(nextScreen, maxX, maxY, imgH, imgW, title, flyingWidget, numWidgets); animateIntro.start(); animIntro = true; repaint(); } void resetGame() { level = 0; score = 0; whichDoc = 0; screwdrivers = 1; } public void setupBoard() { level++; levelComplete = false; // based on level num, decide which player graphics to use... switch (level) { case 1: whichDoc = 0; break; // doc number 1 case 6: whichDoc = 2; break; // doc number 2 case 7: whichDoc = 4; break; // doc number 3 case 10: whichDoc = 6; break; // doc number 4 case 13: whichDoc = 8; break; // doc number 5 } screwdrivers += 1; if (level > 5) screwdrivers +=1; // help player out above L5! drX = drStartX; drY = drStartY; drA = true; allDead = false; animRegen = true; numDaleks = level * levelMultiple + baseNumDaleks; if (numDaleks > maxEnemies) numDaleks = maxEnemies; // randomly place daleks and set their initial properties for (int j=0; j drX) temp = faceLeft; else temp = dalF[whichDal]; dalF[whichDal] = temp; } public void calcSonic() { // destroy daleks immediately adjacent to player screwdrivers--; for (int j=0; j maxY) ? (int)(maxX/2) + 2 : (int)(maxY/2) + 2; for (int j=0; j8; j-=8) { g.drawLine(drX*imgW-j,drY*imgH-j,drX*imgW+j,drY*imgH-j); g.drawLine(drX*imgW-j,drY*imgH+j,drX*imgW+j,drY*imgH+j); pause(800); } animTele = false; } public void animateSonic(Graphics g) { // draw concentric rings when sonic screwdriver is used g.clipRect(0,0,maxX*imgW,maxY*imgH); g.setColor(Color.blue); for (int j=4; j<24; j+=2) { g.drawOval(drX*imgW-j+imgW/2,drY*imgH-j+imgH/2,j*2,j*2); pause(2000); } g.setColor(Color.white); screwdriverUsed = false; } public void animateLevel(Graphics g) { // clear the screen with rectangles between levels g.clipRect(0,0,maxX*imgW,maxY*imgH); g.setColor(Color.blue); for (int j=0; j 24) { doneLoading = true; prepareScreen(); } } repaint(); } else { if (animLevel) { g.drawImage(nextScreen,0,0,this); animateLevel(g); } if (animRegen) animateRegen(g); if (screwdriverUsed) animateSonic(g); if (animTele) animateTele(g); if (lastStand) { while ((!allDead) && (drA)) { moveDaleks(); checkDaleks(); if (newRubble) play(getCodeBase(), "crash.au"); prepareScreen(); g.drawImage(nextScreen,0,0,this); } if ((allDead) && (drA)) levelComplete = true; else playerDead = true; lastStand = false; } prepareScreen(); g.drawImage(nextScreen,0,0,this); } } public void paint(Graphics g) { // repaint the screen as necessary if (!animIntro) { prepareScreen(); g.drawImage(nextScreen,0,0,this); } else animateIntro.drawIntroScreen(g, doneLoading, currentPic); } public void paintNumber(int num, int xPos, int yPos) { // draw the number as a graphic at the specified position Integer numObj = new Integer(num); String stringNum = numObj.toString(); for (int j=0; j < stringNum.length(); j++) { char charDigit = stringNum.charAt(j); int intDigit = Character.digit(charDigit, 10); offScreenGC.drawImage(digit[intDigit], xPos + j*12, yPos-13, this); } } public synchronized void prepareScreen() { // draw the current game status on the off-screen bitmap offScreenGC.setColor(Color.white); offScreenGC.clipRect(0,0,maxX*imgW,maxY*imgH+25); offScreenGC.fillRect(0,0,maxX*imgW,maxY*imgH+4); // draw info bar on bottom offScreenGC.setColor(Color.darkGray); offScreenGC.drawLine(0, maxY*imgH+1, maxX*imgW, maxY*imgH+1); offScreenGC.drawLine(0, maxY*imgH+3, maxX*imgW, maxY*imgH+3); offScreenGC.setColor(Color.lightGray); offScreenGC.drawLine(0, maxY*imgH+2, maxX*imgW, maxY*imgH+2); offScreenGC.setColor(Color.black); offScreenGC.fillRect(0, maxY*imgH+4, maxX*imgW, 21); if (doneLoading) { offScreenGC.setFont(new Font("TimesRoman", Font.PLAIN, 12)); if (score > highScore) highScore = score; int yPos = maxY*imgH + 19; offScreenGC.setColor(Color.white); offScreenGC.drawString("SCORE: ", 5, yPos); paintNumber(score, 51, yPos); offScreenGC.drawString("SCREWDRIVERS: ", 124, yPos); paintNumber(screwdrivers, 221, yPos); offScreenGC.drawString("LEVEL: ", 260, yPos); paintNumber(level, 303, yPos); offScreenGC.drawString("HIGHSCORE: ", 338, yPos); paintNumber(highScore, 415, yPos); // draw the daleks for (int j=0; jmaxX-1) || (newY<0) || (newY>maxY-1)) validMove = false; // find an empty location if teleporting if (teleport) { boolean okLoc = false; while (!okLoc) { // loop until valid coordinates are found okLoc = true; newX = (int)(Math.random()*maxX); newY = (int)(Math.random()*maxY); for (int j=0; j drX) dalX[j]--; if (dalY[j] > drY) dalY[j]--; if ((dalX[j]==drX) && (dalY[j]==drY)) drA = false; // player has died } // check for collisions between daleks newRubble = false; for (int j=0; j