/** * @(#)Nelzan.java 1.0.1 98/12/04 *
* Copyright (C) 1998 David E. Wexler *
* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. See * license.txt for a full copy of the GNU GPL. *
* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. *
* To Contact the author send e-mail to vagabond@netdragon.com or send * snailmail to: 511 Bobcat Ct, Punta Gorda, FL 3398. */ import java.applet.Applet; import java.awt.*; import java.lang.*; import java.net.*; import java.io.*; import java.util.*; import EnemyShips; import HighScores; import MovingStars; import Player; import StoryLine; import ZipImageLoader; /** * Nelzan - A Space Arcade Game. *
* This Class handles state control, thread control, user input and * game level logic. *
* @author David Wexler (vagabond@netdragons.com)
* @version 1.0.1
* @since Nelzan1.0.1
*/
public class Nelzan extends Applet implements Runnable {
// Variables to store state values so the code it more readable.
private static final int GETSYSTEM = -4;
private static final int GETPLAYER = -3;
private static final int GETHIGH = - 2;
private static final int GAMEOVER = -1;
private static final int SHOWINST = 0;
private static final int LEVELIMAGE = 1;
private static final int LEVELDATA = 2;
private static final int LEVELDELAY = 3;
private static final int LEVELPLAY = 4;
private static final int LEVELPLOT = 5;
// What State do we Start in?
private int state = GETSYSTEM;
// How many calls to update() before we die?
private int TTL = 50;
Thread runner;
MovingStars ms;
ZipImageLoader zip;
Player me;
EnemyShips enemy;
HighScores high;
StoryLine plot;
Font bigFont = new Font("Helvetica", Font.BOLD, 22);
Font midFont = new Font("Helvetica", Font.BOLD, 16);
FontMetrics midFontSize = getFontMetrics(midFont);
Font smallFont = new Font("Helvetica", Font.PLAIN, 12);
// For Offscreen Drawing
Image offscreenI;
Graphics offscreenG;
/**
* Use To Tell if the Game is pasued or not.
*/
public boolean pause = false;
/**
* Variable hold what level the player is currently on
*/
public int level = 5;
Image system[];
Image ships[];
/**
* Starts that Applets execution
*/
public void init() {
setLayout(null);
this.requestFocus();
zip = new ZipImageLoader(getCodeBase().toString(), this);
high = new HighScores(this);
ms = new MovingStars(610,375,7,0,50);
}
/**
* Starts Thread execution
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
/**
* Stops thread execution.
*/
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
/**
* Checks to see when the mouse enters the Applet window. When it does,
* the game is unpasued automatically.
*
* @param evt the mouse event
* @param x x location mouse entered
* @param y y location mouse entered
* @return false always
*
* @since Nelzan1.0.1
*/
public boolean mouseEnter(Event evt, int x, int y) {
if (state == LEVELPLAY) {
pause = false;
this.requestFocus();
}
return false;
}
/**
* Checks to see when the mouse leaves the Applet window. When it does
* the game is paused automatically.
*
* @param evt the mouse event
* @param x x location mouse entered
* @param y y location mouse entered
* @return false always
*
* @since Nelzan1.0.1
*/
public boolean mouseExit(Event evt, int x, int y) {
if (state == LEVELPLAY)
pause = true;
return false;
}
/**
* Handles Events when Keys are pressed. All KeyEvents are handled by this function,
* to provide gameplay most like and arcade game tags inside of Player are
* changed to true on keyDown.
*
* @param evt The Event ID
* @param key The Key Pressed
* @return false if state is not handling user Input
* true otherwise
* @see Player#setMoveTrue
*/
public boolean keyDown(Event evt, int key) {
if (state < GAMEOVER)
return false;
else if (state == GAMEOVER || state == SHOWINST)
startLevel(level);
else if (state == LEVELPLOT && plot.canContinue())
startLevel(level);
else if (state < LEVELPLAY)
return false;
else if (key == 'p' || key == 'P')
pause = !pause;
else if (key == 1004 || key == '8')
me.setMoveTrue(0);
else if (key == 1005 || key == '2')
me.setMoveTrue(2);
else if (key == 1006 || key == '4')
me.setMoveTrue(3);
else if (key == 1007 || key == '6')
me.setMoveTrue(1);
else if (key == 'a' || key == 'A')
me.setActiveWeapon(0);
else if (key == 's' || key == 'S')
me.setActiveWeapon(1);
else if (key == 'd' || key == 'D')
me.setActiveWeapon(2);
else if (key == 'f' || key == 'F')
me.setActiveWeapon(3);
else if (key == ' ')
me.fire();
return true;
}
/**
* Handles Events when Keys are let go. All KeyEvents are canceled by this
* function, to provide gameplay most like an Arcade game tags inside of
* Player are changed to false on keyUp.
*
* @param evt The Event ID
* @param key The Key Pressed
* @return true always.
*/
public boolean keyUp(Event evt, int key) {
if (key == 1004 || key == '8')
me.setMoveFalse(0);
else if (key == 1005 || key == '2')
me.setMoveFalse(2);
else if (key == 1006 || key == '4')
me.setMoveFalse(3);
else if (key == 1007 || key == '6')
me.setMoveFalse(1);
return true;
}
/**
* Handles Thread execution. If game is not paused both gameLogic() and
* repaint() is called, otherwise just repaint() is called.
*/
public void run() {
while(true) {
if (!pause) gameLogic();
repaint();
sleep(50);
}
}
/**
* This fuction paints everything for the user to See. Depending on the
* state, different fuctions are called from different classes.
*
int value from s
*/
private int toInt(String s) {
Integer cToI = new Integer(s);
return cToI.intValue();
}
/**
* Load System Images.
*/
private void loadSystem() {
system = zip.getImages("system.zip");
}
/**
* Loads player Images and defines a new instance of Player.
*/
private void loadPlayer() {
me = new Player(zip.getImages("ship.zip"), 10, 200, this);
}
/**
* Sends High Score to CGI script and downloads new High Score Data.
*/
private void loadHighScores() {
high.sendHigh(me.score);
}
/**
* Loads Enemy Ship Images to be used in the upcoming Level.
*/
private void loadShipImages() {
ships = zip.getImages("" + level + ".zip");
}
/**
* Creates a new instance of EnemyShips
*/
private void loadLevelData() {
enemy = new EnemyShips(ships, level, this);
}
/**
* Loads the Plot line.
*
* @param i The level to load a plot for.
*/
private void loadPlot(int i) {
plot = null;
state = LEVELPLOT;
plot = new StoryLine(i, this);
System.gc();
}
/**
* Starts new level.
*
* @param i The level to start.
*/
private void startLevel(int i) {
if ((i%4) == 1 && plot == null) {
loadPlot(i);
} else {
plot = null;
if (i > toInt(this.getParameter("level")))
gameOver();
else
state = LEVELIMAGE;
}
me.level = i;
level = i;
}
/**
* Sets state to Game Over, and handles other logic that deals with
* the game ending.
*/
private void gameOver() {
TTL = 50;
high.sendHigh(me.score);
level = 1;
state = GAMEOVER;
for (int i = 0; i < 10; i++)
me.killMe();
me.score = 0;
me.lives = 3;
me.level = 1;
}
/**
* Display User Feedback. Shows Shield Level, Weapon selected, Weapon Level,
* Lives, and score.
*
* @param g The Graphics to paint to.
*/
private void paintPannel(Graphics g) {
g.setFont(smallFont);
g.setColor(Color.white);
g.drawString("Shields",5,388);
g.drawString("Score: " + me.score, 475, 388);
g.drawString("Lives ", 250, 388);
g.drawImage(system[me.getActiveWeapon()], 175, 378, this);
g.drawString("Lvl: " + me.getWeaponLevel(), 190, 388);
g.setColor(Color.cyan);
g.drawString("Nelzan 1.0.1", 390, 388);
for (int i = 0; i < me.lives; i++) {
g.drawImage(system[4], 285 + (i*15),378, this);
}
for (int i = 0; i < me.shields && i < 100; i++) {
g.setColor(me.shieldColor[i]);
g.drawLine(50+i,378,50+i,388);
}
if (me.shields > 100) {
g.drawLine(152, 383, 160, 383);
g.drawLine(156, 379, 156, 387);
}
}
/**
* Display State Information. This shows what the system is doing like,
* "Loading System . . ." and other relevent messages. It also display
* High Scores and Instrutions when needed.
*
* @param g The Graphics to paint to.
*/
private void drawState(Graphics g) {
String msg = "";
switch (state) {
case -4: msg = "Loading System . . .";
break;
case -3: msg = "Loading Player . . .";
break;
case -2: msg = "Loading High Scores.";
break;
case -1:
case 0: msg = "Hit Any Key to Start";
break;
}
g.setFont(bigFont);
g.setColor(Color.blue);
g.fillRect(200,75,200,200);
g.setColor(Color.black);
g.drawString("Nelzan", 262, 91);
g.setColor(Color.white);
offscreenG.drawString("Nelzan", 260, 90);
g.setFont(midFont);
g.setColor(Color.black);
g.drawString(msg, 301 - midFontSize.stringWidth(msg)/2, 271);
g.setColor(Color.white);
g.drawString(msg, 300 - midFontSize.stringWidth(msg)/2, 270);
if (state == -1)
high.paint(g);
else if (state == 0)
high.paintInstructions(g);
}
/**
* Display Level State Information. This shows what the level is doing like,
* "Loading Images . . ." and other relevent messages. It also display
* The Level number and if the level is a boss or not.
*
* @param g The Graphics to paint to.
*/
private void drawLevelState(Graphics g) {
g.setFont(bigFont);
g.setColor(Color.blue);
g.fillRect(200,150,200,65);
g.setColor(Color.black);
if (level % 4 != 0)
g.drawString("Level " + level, 212, 173);
else
g.drawString("Level " + level + " (Boss)", 212, 173);
g.setColor(Color.white);
if (level % 4 != 0)
g.drawString("Level " + level, 210, 172);
else
g.drawString("Level " + level + " (Boss)", 210, 172);
String msg = "Get Ready . . ." + (4-state);
g.setFont(midFont);
g.setColor(Color.black);
g.drawString(msg, 301 - midFontSize.stringWidth(msg)/2, 191);
g.setColor(Color.white);
g.drawString(msg, 300 - midFontSize.stringWidth(msg)/2, 190);
switch (state) {
case 1: msg = "Loading Images . . .";
break;
case 2: msg = "Loading Data . . .";
break;
case 3: msg = "- Systems Nominal -";
break;
}
g.setColor(Color.black);
g.drawString(msg, 301 - midFontSize.stringWidth(msg)/2, 211);
g.setColor(Color.white);
g.drawString(msg, 300 - midFontSize.stringWidth(msg)/2, 210);
}
}