first commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
/**
|
||||
* This is the parent of all the game state classes. A game state is
|
||||
* basically one screen - be it the splash screen, the main menu, or
|
||||
* the game screen itself.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public abstract class AbstractGameState implements ActionListener {
|
||||
|
||||
/**
|
||||
* The UI to display with this state.
|
||||
*/
|
||||
private LRootPane gui;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AbstractGameState</code> instance.
|
||||
*
|
||||
*/
|
||||
protected AbstractGameState() {
|
||||
gui = new LRootPane();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root pane with the UI associated with this state.
|
||||
*
|
||||
* @return a <code>LRootPane</code> value
|
||||
*/
|
||||
public final LRootPane getUI() {
|
||||
return gui;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new value of the root pane.
|
||||
*
|
||||
* @param pane a <code>LRootPane</code> value
|
||||
*/
|
||||
protected final void setUI(LRootPane pane) {
|
||||
gui = pane;
|
||||
}
|
||||
|
||||
//@roseuid 40651ACF00AB
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return True if the initialization was successful, and false if
|
||||
* it was not.
|
||||
*
|
||||
*/
|
||||
public abstract boolean initialize();
|
||||
|
||||
//@roseuid 40651B230193
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return True if the clean-up was successful, and false if it failed.
|
||||
*
|
||||
*/
|
||||
public abstract boolean cleanUp();
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobFactory;
|
||||
import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.IClickable;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
|
||||
//import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* Class GamePlayState: where the actual game is displayed and played
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AttractState extends GamePlayState {
|
||||
|
||||
|
||||
/**
|
||||
* Allow more bashers?
|
||||
*/
|
||||
private boolean basher = true;
|
||||
|
||||
/**
|
||||
* Allow more bashers?
|
||||
*/
|
||||
private boolean bridger = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param l , Level
|
||||
*/
|
||||
public AttractState(Level l) {
|
||||
super(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param l , string of level name
|
||||
*/
|
||||
public AttractState(String l) {
|
||||
super(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the special update.
|
||||
*/
|
||||
protected void specialUpdate() {
|
||||
Lemming currLem = null;
|
||||
// BufferedImage map = getLevel().getMap().getMap();
|
||||
List lemmings = getLevel().getActiveLemmings();
|
||||
int x;
|
||||
int y;
|
||||
|
||||
if (getLevel().getLemmingHeaven().size() == 20) {
|
||||
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
}
|
||||
|
||||
for (int i = 0; i < lemmings.size(); i++) {
|
||||
currLem = (Lemming) lemmings.get(i);
|
||||
x = currLem.getPosition().getX() + 5;
|
||||
y = currLem.getPosition().getY() + 5;
|
||||
// System.out.println("In special update x is " + x + "y is " + y);
|
||||
//check for digger
|
||||
if (x >= 156 && y < 122) {
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_DIGGER));
|
||||
}
|
||||
//check for exploder
|
||||
if (x >= 615 && x <= 620 && y >= 225 && y <= 230) {
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_EXPLODER));
|
||||
}
|
||||
//check for basher
|
||||
if (x >= 220 && x <= 250 && y >= 282 && y <= 288 && basher) {
|
||||
basher = false;
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_BASHER));
|
||||
}
|
||||
//check for climber
|
||||
if (x >= 210 && x <= 220 && y >= 590 && y <= 595) {
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_CLIMBER));
|
||||
}
|
||||
//check for floater
|
||||
if (x >= 130 && x <= 180 && y >= 220 && y <= 235) {
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_FLOATER));
|
||||
}
|
||||
//check for bridger
|
||||
if (x >= 340 && x <= 345 && y >= 282 && y <= 288 && bridger) {
|
||||
bridger = false;
|
||||
currLem.setOccupation(
|
||||
LemmingJobFactory.getInstance().makeJob(
|
||||
LemmingJobSettings.JOB_ID_BRIDGER));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
}
|
||||
/**
|
||||
* Whatever else needs to be initialized.
|
||||
*/
|
||||
protected void specialInitialize() {
|
||||
LComponent c = new LClickListener() {
|
||||
public void registerMouseClick(int button, Point coords) {
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
}
|
||||
};
|
||||
|
||||
c.setPosition(new Point(0, 0));
|
||||
c.setSize(new Dimension(800, 600));
|
||||
c.setShown(true);
|
||||
|
||||
getUI().addChild(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to keys and stuff.
|
||||
*/
|
||||
private abstract class LClickListener
|
||||
extends LLeafComponent implements IClickable {
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Jose:
|
||||
* Adds specific blood stuff
|
||||
*
|
||||
* Blood shouldn't bounce, rather it should hit the wall and die
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the BloodParticle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class BloodParticle extends Particle {
|
||||
|
||||
/**
|
||||
* Used to randomize velocity.
|
||||
*/
|
||||
private static final Random GENERATOR = new Random(new java.util.Date()
|
||||
.getTime());
|
||||
|
||||
/**
|
||||
* Particles to create when death should occur
|
||||
*/
|
||||
public static final int PARTICLESWHENDIE = 75;
|
||||
|
||||
/**
|
||||
* time to Live
|
||||
*/
|
||||
private int killMe;
|
||||
|
||||
/**
|
||||
* curve
|
||||
*/
|
||||
private int curve;
|
||||
|
||||
/**
|
||||
* Stores canDie
|
||||
*/
|
||||
private boolean canDie;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*/
|
||||
public BloodParticle() {
|
||||
super("blood");
|
||||
|
||||
getVelocity().setPolar(GENERATOR.nextInt(8), GENERATOR.nextInt(30));
|
||||
canDie = false;
|
||||
killMe = 0;
|
||||
curve = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @return <code>boolean</code> value
|
||||
*/
|
||||
public boolean getCanDie() {
|
||||
return canDie;
|
||||
|
||||
}
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @param a for candie <code>boolean</code> value
|
||||
*/
|
||||
public void setCanDie(boolean a) {
|
||||
|
||||
canDie = a;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (killMe > 25) {
|
||||
return true;
|
||||
}
|
||||
if (curve > 5) {
|
||||
return true;
|
||||
} else if (this.getVelocity().getJ() == 0) {
|
||||
curve++;
|
||||
}
|
||||
killMe++;
|
||||
return canDie;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Andrew:
|
||||
* Adds specific bone stuff
|
||||
*
|
||||
* bones reaches peak in curve three before disapearing
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the BoneParticle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class BoneParticle extends Particle {
|
||||
|
||||
/**
|
||||
* Used to randomize velocity.
|
||||
*/
|
||||
private static final Random GENERATOR = new Random(new java.util.Date()
|
||||
.getTime());
|
||||
|
||||
/**
|
||||
* Particles to create when death should occur
|
||||
*/
|
||||
public static final int PARTICLESWHENBONE = 3;
|
||||
|
||||
/**
|
||||
* curve
|
||||
*/
|
||||
private int curve;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*/
|
||||
public BoneParticle() {
|
||||
super("bone");
|
||||
|
||||
getVelocity().setPolar(GENERATOR.nextInt(8), GENERATOR.nextInt(30));
|
||||
curve = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (curve > 3) {
|
||||
return true;
|
||||
} else if (this.getVelocity().getJ() == 0) {
|
||||
curve++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class CreditsState: Displays the credits screen, and when we are
|
||||
* done - goes back to the main menu.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 15, 2004) - Created the CreditsState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 15, 2004
|
||||
*/
|
||||
public class CreditsState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreditsState</code> instance.
|
||||
*/
|
||||
public CreditsState() {
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C032F
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean initialize() {
|
||||
LRootPane np = new LRootPane();
|
||||
|
||||
LButton button = new LButton();
|
||||
button.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("credits"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
button.addActionListener(this);
|
||||
button.setShown(true);
|
||||
button.setPosition(new Point(0, 0));
|
||||
|
||||
np.addChild(button);
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C034D
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C037F
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ada
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
//The splash screen has been clicked.
|
||||
if (GameEngine.VERBOSE) {
|
||||
System.out.println("CreditsState: Transferrring to Main Menu...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Transfer to Main Menu.
|
||||
MainMenuState mms = new MainMenuState();
|
||||
GameEngine.getInstance().setCurrentState(mms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Andrew:
|
||||
* Adds specific dirt stuff
|
||||
*
|
||||
* Dirt reaches peak in curve twice before it disapears
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the DirtParticle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class DirtParticle extends Particle {
|
||||
|
||||
/**
|
||||
* Used to randomize velocity.
|
||||
*/
|
||||
private static final Random GENERATOR = new Random(new java.util.Date()
|
||||
.getTime());
|
||||
|
||||
/**
|
||||
* Particles to create when death should occur
|
||||
*/
|
||||
public static final int PARTICLESWHENDIG = 4;
|
||||
|
||||
/**
|
||||
* curve
|
||||
*/
|
||||
private int curve;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*/
|
||||
public DirtParticle() {
|
||||
super("dirt");
|
||||
|
||||
getVelocity().setPolar(GENERATOR.nextInt(8), GENERATOR.nextInt(30));
|
||||
curve = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*@param i i
|
||||
*@param j j
|
||||
*/
|
||||
|
||||
|
||||
public DirtParticle(int i, int j) {
|
||||
super("dirt");
|
||||
|
||||
getVelocity().setI(-i + GENERATOR.nextInt(3));
|
||||
getVelocity().setJ(-j + GENERATOR.nextInt(3));
|
||||
curve = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (curve > 2) {
|
||||
return true;
|
||||
} else if (this.getVelocity().getJ() == 0) {
|
||||
curve++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
|
||||
/**
|
||||
* Class EstablishingConnectionState: This state will load a level,
|
||||
* and then wait for a connection to be established. After both of the
|
||||
* conditions are met, it will go on to the actual game.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 15, 2004) - Created the EstablishingConnectionState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 15, 2004
|
||||
*/
|
||||
public class EstablishingConnectionState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* The level that we will be loading here.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Allows the user to continue on to play the level.
|
||||
*/
|
||||
// private LButton continueButton;
|
||||
|
||||
/**
|
||||
* The label to display our message to the user in.
|
||||
*/
|
||||
private LFancyLabel message;
|
||||
|
||||
/**
|
||||
* Describe variable <code>levelLoaded</code> here.
|
||||
*
|
||||
*/
|
||||
private boolean islevelLoaded;
|
||||
|
||||
/**
|
||||
* Contains true if the connection is established, and false if it
|
||||
* is not yet.
|
||||
*/
|
||||
private boolean connectionEstablished;
|
||||
|
||||
/**
|
||||
* Port.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* Host.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Describe variable <code>lemmingCount</code> here.
|
||||
*
|
||||
*/
|
||||
private int lemmingCount;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>EstablishingConnectionState</code> instance.
|
||||
*/
|
||||
public EstablishingConnectionState() {
|
||||
connectionEstablished = false;
|
||||
islevelLoaded = false;
|
||||
level = null;
|
||||
lemmingCount = 0;
|
||||
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance()
|
||||
.getTileSet("bg_loading"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize label:
|
||||
message = new LFancyLabel();
|
||||
message.setForeground(Color.black);
|
||||
message.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
message.setText("Establishing Connection...");
|
||||
message.setShown(true);
|
||||
message.setPosition(new Point(300, 300));
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(message);
|
||||
|
||||
setUI(np);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
level = null;
|
||||
connectionEstablished = false;
|
||||
islevelLoaded = false;
|
||||
port = 0;
|
||||
host = null;
|
||||
lemmingCount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
//The user can't click anything here, so...
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of lemmingCount.
|
||||
* @return value of lemmingCount.
|
||||
*/
|
||||
public int getLemmingCount() {
|
||||
return lemmingCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of lemmingCount.
|
||||
* @param v Value to assign to lemmingCount.
|
||||
*/
|
||||
public void setLemmingCount(int v) {
|
||||
this.lemmingCount = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>connectTo</code> method here.
|
||||
*
|
||||
* @param hostt a <code>String</code> value
|
||||
* @param portt an <code>int</code> value
|
||||
*/
|
||||
public void connectTo(String hostt, int portt) {
|
||||
host = hostt;
|
||||
port = portt;
|
||||
|
||||
//We are the client:
|
||||
if (LemmingNetworking.getInstance().connectTo(host, port)) {
|
||||
connectionEstablished();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>host</code> method here.
|
||||
*
|
||||
* @param portt an <code>int</code> value
|
||||
*/
|
||||
public void host(int portt) {
|
||||
port = portt;
|
||||
|
||||
//We are the server:
|
||||
if (LemmingNetworking.getInstance().listenForConnection(port)) {
|
||||
connectionEstablished();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the level with the specified id.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public synchronized void loadLevel(final String id) {
|
||||
level = LevelReader.getInstance().loadLevel(id);
|
||||
levelLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be done when the level is done loading.
|
||||
*/
|
||||
private synchronized void levelLoaded() {
|
||||
islevelLoaded = true;
|
||||
|
||||
//Set the number of lemmings on the level to fourty plus whatever
|
||||
//we have
|
||||
int num = 40 + lemmingCount;
|
||||
|
||||
level.setNumberOfLemmings(num);
|
||||
|
||||
if (LemmingNetworking.getInstance().isConnected()) {
|
||||
startLevel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called when the connection is established.
|
||||
*/
|
||||
private synchronized void connectionEstablished() {
|
||||
if (islevelLoaded) {
|
||||
startLevel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the level.
|
||||
*/
|
||||
private synchronized void startLevel() {
|
||||
GameEngine.getInstance()
|
||||
.setCurrentState(new MultiplayerGameplayState(level));
|
||||
|
||||
LemmingNetworking.getInstance().getConnection().startListening();
|
||||
LemmingNetworking.getInstance().getConnection().startSending();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Andrew:
|
||||
* Adds specific flame stuff
|
||||
*
|
||||
* flames shoot downward and live for five process calls
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the FlameParticle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class FlameParticle extends Particle {
|
||||
|
||||
/**
|
||||
* Particles to create when death should occur
|
||||
*/
|
||||
public static final int PARTICLESWHENFLAME = 3;
|
||||
|
||||
/**
|
||||
* Used to randomize velocity.
|
||||
*/
|
||||
private static final Random GENERATOR = new Random(new java.util.Date()
|
||||
.getTime());
|
||||
|
||||
/**
|
||||
* time to Live
|
||||
*/
|
||||
private int killMe;
|
||||
|
||||
/**
|
||||
* Stores canDie
|
||||
*/
|
||||
private boolean canDie;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*/
|
||||
public FlameParticle() {
|
||||
super("flame");
|
||||
|
||||
killMe = 0;
|
||||
getVelocity().setJ(2 + GENERATOR.nextInt(2));
|
||||
getVelocity().setI((-1 * GENERATOR.nextInt(1)) * GENERATOR.nextInt(2));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @return <code>boolean</code> value
|
||||
*/
|
||||
public boolean getCanDie() {
|
||||
return canDie;
|
||||
|
||||
}
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @param a for candie <code>boolean</code> value
|
||||
*/
|
||||
public void setCanDie(boolean a) {
|
||||
|
||||
canDie = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (killMe > 5 + GENERATOR.nextInt(3)) {
|
||||
return true;
|
||||
}
|
||||
killMe++;
|
||||
return canDie;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
|
||||
/**
|
||||
* Class FlingTrap: when the lemming comes close to this one, it flings him.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 22, 2004) - Created the FlingTrap class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 22, 2004
|
||||
*/
|
||||
public class FlingTrap extends Portal {
|
||||
|
||||
/**
|
||||
* Creates a new <code>FlingTrap</code> instance.
|
||||
*/
|
||||
public FlingTrap() {
|
||||
super(PortalFactory.PORTAL_TYPES[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called when a lemming enters this portal.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
*/
|
||||
public void processLemmingEntry(Lemming l) {
|
||||
int x = l.getVelocity().getI();
|
||||
x /= Math.abs(x); //normalize
|
||||
|
||||
l.getVelocity().setI(x * PhysicsSettings.getInstance()
|
||||
.getTerminalVelocity() / 2);
|
||||
l.getVelocity().setJ(-PhysicsSettings.getInstance().getTerminalVelocity());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LFader;
|
||||
import edu.gatech.cs2335.lemmings.gui.LApplication;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.networking.AbstractMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
/**
|
||||
* This class will manage the states of the game and their
|
||||
* transitions. It will know when to go to the splash screen or the
|
||||
* menu, or the game itself, and when to quit.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public class GameEngine {
|
||||
|
||||
/**
|
||||
* Display debug information?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Display a lot of debug information?
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*/
|
||||
private static GameEngine instance;
|
||||
|
||||
/**
|
||||
* This is the state that the game is currently in.
|
||||
*/
|
||||
private AbstractGameState currentState;
|
||||
|
||||
/**
|
||||
* This is the application that will be started when the game starts.
|
||||
*/
|
||||
private LApplication theApp;
|
||||
|
||||
/**
|
||||
* Cache this guy so we don't have to create him on the fly.
|
||||
*/
|
||||
private LoadLevelState loadLevelState;
|
||||
|
||||
/**
|
||||
* The cached d00d.
|
||||
*/
|
||||
private EstablishingConnectionState ecs;
|
||||
|
||||
/**
|
||||
* Like, another chached d00d, and stuff.
|
||||
*/
|
||||
private NetworkErrorState nes;
|
||||
|
||||
/**
|
||||
* Creates a new <code>GameEngine</code> instance.
|
||||
*
|
||||
*/
|
||||
private GameEngine() {
|
||||
if (VERBOSE) {
|
||||
System.out.println("GameEngine: Initializing...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
loadLevelState = new LoadLevelState();
|
||||
ecs = new EstablishingConnectionState();
|
||||
nes = new NetworkErrorState();
|
||||
|
||||
theApp = new LApplication("CS2335 Lemmings", null, null);
|
||||
theApp.startRenderer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*
|
||||
* @return a <code>GameEngine</code> value
|
||||
*/
|
||||
public static synchronized GameEngine getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new GameEngine();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a network error occurs, this function will be called.
|
||||
*
|
||||
* @param error a <code>String</code> value
|
||||
*/
|
||||
public synchronized void showNetworkError(String error) {
|
||||
//Show error:
|
||||
nes.setErrorMessage(error);
|
||||
setCurrentState(nes);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("GameEngine: Showing network error:");
|
||||
System.err.println(error);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
//Shut down networking:
|
||||
LemmingNetworking.getInstance().shutDownNetworking();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a single-player game with the specified level.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
*/
|
||||
public void startSingleLevel(String name) {
|
||||
setCurrentState(loadLevelState);
|
||||
|
||||
//Collect garbage now:
|
||||
System.gc();
|
||||
|
||||
//Now that we've cleaned shit up...
|
||||
loadLevelState.loadLevel(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for EstablishingConnectionState
|
||||
* @return EstablishingConnectionState
|
||||
*/
|
||||
public EstablishingConnectionState getEcs() {
|
||||
return ecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>startMultiGame</code> method here.
|
||||
*
|
||||
*/
|
||||
public void startMultiGame() {
|
||||
setCurrentState(ecs);
|
||||
|
||||
//Collect garbage now:
|
||||
System.gc();
|
||||
|
||||
ecs.loadLevel(LevelReader.getInstance().getLevelList()[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* stuff.
|
||||
*
|
||||
* @param count an <code>int</code> value
|
||||
* @param lemmings an <code>int</code> value
|
||||
*/
|
||||
public void startMultiLevel(int count, int lemmings) {
|
||||
setCurrentState(ecs);
|
||||
|
||||
//Collect garbage now:
|
||||
System.gc();
|
||||
|
||||
ecs.setLemmingCount(lemmings);
|
||||
|
||||
ecs.loadLevel(LevelReader.getInstance().getLevelList()[count]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the currentState property.
|
||||
*
|
||||
* @return the current value of the currentState property
|
||||
*/
|
||||
public AbstractGameState getCurrentState() {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the currentState property. If the value passed
|
||||
* in is NULL, will throw a NullPointerException.
|
||||
*
|
||||
* @param aCurrentState the new value of the currentState property
|
||||
*/
|
||||
public void setCurrentState(final AbstractGameState aCurrentState) {
|
||||
boolean shitHitTheFan = false;
|
||||
boolean fade = false;
|
||||
if (currentState != null) {
|
||||
fade = true;
|
||||
}
|
||||
|
||||
if (fade) {
|
||||
LFader f = new LFader();
|
||||
f.setBounds(new Rectangle(0, 0, 800, 600));
|
||||
f.setShown(true);
|
||||
theApp.getRootPane().addChild(f);
|
||||
f.fadeToForeground(1000);
|
||||
|
||||
currentState.cleanUp();
|
||||
|
||||
currentState = aCurrentState;
|
||||
currentState.initialize();
|
||||
|
||||
if (f.isFading()) {
|
||||
try {
|
||||
Thread.sleep(f.getTimeRemaining());
|
||||
} catch (Exception e) {
|
||||
//Too bad:
|
||||
//Don't mess with this! This exception is thrown when the
|
||||
//next screen loads faster than the fader fully fades to
|
||||
//black (because Java is screwed in the head and doesn't
|
||||
//support normal thread wake up.
|
||||
shitHitTheFan = true;
|
||||
// System.out.println("Exception in GameEngine\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentState = aCurrentState;
|
||||
currentState.initialize();
|
||||
}
|
||||
|
||||
//Set up the new root pane:
|
||||
theApp.setRootPane(currentState.getUI());
|
||||
theApp.getRootPane().makeDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>receiveMessage</code> method here.
|
||||
*
|
||||
* @param msg an <code>AbstractMessage</code> value
|
||||
*/
|
||||
public synchronized void receiveMessage(AbstractMessage msg) {
|
||||
if (msg == null) {
|
||||
System.err.println("GameEngine: receiveMessage got bad message\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//check if we're in the MultiplayerGameState
|
||||
if (currentState instanceof MultiplayerGameplayState) {
|
||||
((MultiplayerGameplayState) currentState).receiveMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,755 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
//import edu.gatech.cs2335.lemmings.networking.MessageFactory;
|
||||
//import edu.gatech.cs2335.lemmings.networking.MessageSettings;
|
||||
//import edu.gatech.cs2335.lemmings.networking.AbstractMessage;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.ITypable;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.JobContainer;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LToggleButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.MiniMap;
|
||||
|
||||
/**
|
||||
* The game state, where the actual game is displayed and played.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class GamePlayState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* How many times per second should we update the lemmings?
|
||||
*/
|
||||
public static final float UPDATE_FREQUENCY = 10;
|
||||
|
||||
/**
|
||||
* Delay between the updates.
|
||||
*/
|
||||
public static final long UPDATE_DELAY = (long) (1000.0f / UPDATE_FREQUENCY);
|
||||
|
||||
/**
|
||||
* The level associated with this game. It will be what the player plays on.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* True if the game is paused. False if it is not.
|
||||
*/
|
||||
//private boolean paused;
|
||||
|
||||
/**
|
||||
* Set to true when the state is killed.
|
||||
*/
|
||||
private boolean killed;
|
||||
|
||||
/**
|
||||
* The delay between the updates.
|
||||
*/
|
||||
private long gameSpeed;
|
||||
|
||||
/**
|
||||
* The label that shows the time...
|
||||
*/
|
||||
private LFancyLabel timeLabel;
|
||||
|
||||
/**
|
||||
* The label showing the number of lemmings released.
|
||||
*/
|
||||
private LFancyLabel releasedLabel;
|
||||
|
||||
/**
|
||||
* The label that will show how many lemmings have been saved.
|
||||
*/
|
||||
private LFancyLabel savedLabel;
|
||||
|
||||
/**
|
||||
* This label will show the number of lemmings out in the field.
|
||||
*/
|
||||
private LFancyLabel outLabel;
|
||||
|
||||
/**
|
||||
* Describe variable <code>jb</code> here.
|
||||
*
|
||||
*/
|
||||
private JobContainer jobs;
|
||||
|
||||
/**
|
||||
* Describe variable <code>pauseToggle</code> here.
|
||||
*
|
||||
*/
|
||||
private LToggleButton pauseToggle;
|
||||
|
||||
/**
|
||||
* Describe variable <code>speedToggle</code> here.
|
||||
*
|
||||
*/
|
||||
private LToggleButton speedToggle;
|
||||
|
||||
/**
|
||||
* Describe variable <code>nukeToggle</code> here.
|
||||
*
|
||||
*/
|
||||
private LToggleButton nukeToggle;
|
||||
|
||||
/**
|
||||
* Describe variable <code>gpp</code> here.
|
||||
*
|
||||
*/
|
||||
private GamePlayPanel gpp;
|
||||
|
||||
/**
|
||||
* The renderer used for this.
|
||||
*/
|
||||
private Renderer renderer;
|
||||
|
||||
/**
|
||||
* Will display the current lemming flow.
|
||||
*/
|
||||
private LFancyLabel lblLemmingFlow;
|
||||
|
||||
/**
|
||||
* time of last update
|
||||
*/
|
||||
private long lastUpdate;
|
||||
|
||||
/**
|
||||
* Number of Lemmings
|
||||
*/
|
||||
private int numLemmings;
|
||||
|
||||
/**
|
||||
* String representation of the number of lemmings
|
||||
*/
|
||||
private String strNumLemmings;
|
||||
|
||||
/**
|
||||
* How many lemmings have to be saved
|
||||
*/
|
||||
private int lemmingsToSave;
|
||||
|
||||
/**
|
||||
* String representation of the number of lemmings to save
|
||||
*/
|
||||
private String strLemmingsToSave;
|
||||
|
||||
/**
|
||||
* Number of released lemmings
|
||||
*/
|
||||
private int numReleasedLemmings;
|
||||
|
||||
/**
|
||||
* Number of lemmings out
|
||||
*/
|
||||
private int numLemmingsOut;
|
||||
|
||||
//@roseuid 406623D9022A
|
||||
/**
|
||||
* Creates a new GamePlayState instance.
|
||||
*
|
||||
* @param l The level that we would like to play on.
|
||||
*
|
||||
*/
|
||||
public GamePlayState(Level l) {
|
||||
level = l;
|
||||
|
||||
//paused = true;
|
||||
killed = false;
|
||||
gameSpeed = UPDATE_DELAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the level with the id passed in and uses that to play.
|
||||
*
|
||||
* @param levelName a <code>String</code> value
|
||||
*/
|
||||
public GamePlayState(String levelName) {
|
||||
this(LevelReader.getInstance().loadLevel(levelName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the level property.
|
||||
*
|
||||
* @return the current value of the level property
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
//Set up the game panel:
|
||||
LRootPane np = new LRootPane();
|
||||
Rectangle bounds = new Rectangle(0, 20, 800, 580);
|
||||
renderer = new Renderer(level, new Rectangle(bounds));
|
||||
gpp = new GamePlayPanel(renderer);
|
||||
jobs = new JobContainer(level);
|
||||
jobs.setShown(true);
|
||||
jobs.setPosition(new Point(30, 570));
|
||||
jobs.setArrangement(JobContainer.X_AXIS);
|
||||
for (int i = 0; i < LemmingJobSettings.ALL_JOB_NAMES.length; i++) {
|
||||
if (level.getJobsRemaining(LemmingJobSettings.ALL_JOB_NAMES[i]) > 0) {
|
||||
jobs.addJobButton(LemmingJobSettings.ALL_JOB_NAMES[i]);
|
||||
}
|
||||
}
|
||||
gpp.setBounds(new Rectangle(bounds));
|
||||
gpp.setShown(true);
|
||||
|
||||
initializeLabels();
|
||||
|
||||
//Buttons:
|
||||
initializeButtons();
|
||||
LButton ib = new LButton();
|
||||
ib.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("btn_increase"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
ib.addActionListener(this);
|
||||
ib.setActionCommand("increase");
|
||||
ib.setShown(true);
|
||||
ib.setPosition(new Point(10, 290));
|
||||
LButton db = new LButton();
|
||||
db.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("btn_decrease"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
db.addActionListener(this);
|
||||
db.setActionCommand("decrease");
|
||||
db.setShown(true);
|
||||
db.setPosition(new Point(10, 370));
|
||||
np.addChild(gpp);
|
||||
np.addChild(timeLabel);
|
||||
np.addChild(releasedLabel);
|
||||
np.addChild(savedLabel);
|
||||
np.addChild(outLabel);
|
||||
np.addChild(lblLemmingFlow);
|
||||
np.addChild(jobs);
|
||||
np.addChild(pauseToggle);
|
||||
np.addChild(speedToggle);
|
||||
np.addChild(nukeToggle);
|
||||
np.addChild(ib);
|
||||
np.addChild(db);
|
||||
|
||||
MiniMap mm = new MiniMap(level);
|
||||
mm.setShown(true);
|
||||
mm.setPosition(new Point(650, 450));
|
||||
mm.setSize(new Dimension(120, 120));
|
||||
|
||||
np.addChild(mm);
|
||||
|
||||
setUI(np);
|
||||
|
||||
//Update physics engine
|
||||
PhysicsEngine.getInstance().setCurrentMap(level.getMap().getMap());
|
||||
|
||||
specialInitialize();
|
||||
|
||||
np.addChild(new LKeyListener() {
|
||||
public void processKeyTyped(char key, int modifiers) {
|
||||
if (key == 'p') {
|
||||
//Pause the game.
|
||||
if (level.isPaused()) {
|
||||
pauseToggle.setSelected(false);
|
||||
handlePauseButton();
|
||||
} else {
|
||||
pauseToggle.setSelected(true);
|
||||
handlePauseButton();
|
||||
|
||||
}
|
||||
} else if (key == 'f') {
|
||||
//Fast forward.
|
||||
speedToggle.toggleSelected();
|
||||
handleSpeedupButton();
|
||||
|
||||
} else if (key == '+') {
|
||||
//Increase lemming flow:
|
||||
handleIncreaseButton();
|
||||
|
||||
} else if (key == '-') {
|
||||
//Decrease lemming flow:
|
||||
handleDecreaseButton();
|
||||
|
||||
} else if (key == 27) { //ESC
|
||||
try {
|
||||
level.pause();
|
||||
level.setLemmingsSaved(0);
|
||||
endLevel();
|
||||
} catch (NullPointerException npe) {
|
||||
System.err.println("NullPointerException"); //tooo bad
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Set up update thread:
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
lastUpdate = System.currentTimeMillis();
|
||||
numLemmings = level.getPendingLemmings().size();
|
||||
strNumLemmings = Integer.toString(numLemmings);
|
||||
lemmingsToSave = level.getData().getPercentToSave();
|
||||
lemmingsToSave = (numLemmings * lemmingsToSave) / 100;
|
||||
strLemmingsToSave = Integer.toString(lemmingsToSave);
|
||||
|
||||
level.unpause();
|
||||
|
||||
while (!killed) {
|
||||
//Update level:
|
||||
level.updateLevel();
|
||||
|
||||
if (level.isLevelOver()) {
|
||||
killed = true;
|
||||
endLevel();
|
||||
return;
|
||||
}
|
||||
|
||||
numReleasedLemmings
|
||||
= numLemmings - level.getPendingLemmings().size();
|
||||
numLemmingsOut = level.getActiveLemmings().size();
|
||||
|
||||
//Update UI:
|
||||
updateStuff();
|
||||
|
||||
//Sleep some:
|
||||
lastUpdate += gameSpeed;
|
||||
try {
|
||||
Thread.sleep(Math
|
||||
.max(0, lastUpdate - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
} finally {
|
||||
lastUpdate = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
// level.pause();
|
||||
|
||||
}
|
||||
}).start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes buttons.
|
||||
*/
|
||||
private void initializeButtons() {
|
||||
pauseToggle = new LToggleButton();
|
||||
pauseToggle.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("btn_pause"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
pauseToggle.addActionListener(this);
|
||||
pauseToggle.setActionCommand("pause");
|
||||
pauseToggle.setShown(true);
|
||||
pauseToggle.setPosition(new Point(10, 110));
|
||||
speedToggle = new LToggleButton();
|
||||
speedToggle.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("btn_speedup"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
speedToggle.addActionListener(this);
|
||||
speedToggle.setActionCommand("speedup");
|
||||
speedToggle.setShown(true);
|
||||
speedToggle.setPosition(new Point(10, 170));
|
||||
nukeToggle = new LToggleButton();
|
||||
nukeToggle.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("btn_nuke"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
nukeToggle.addActionListener(this);
|
||||
nukeToggle.setActionCommand("nuke");
|
||||
nukeToggle.setShown(true);
|
||||
nukeToggle.setPosition(new Point(10, 230));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the labels.
|
||||
*/
|
||||
private void initializeLabels() {
|
||||
timeLabel = new LFancyLabel();
|
||||
timeLabel.setForeground(Color.yellow);
|
||||
timeLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
timeLabel.setText("");
|
||||
timeLabel.setPosition(new Point(760, 50));
|
||||
timeLabel.setShown(true);
|
||||
|
||||
releasedLabel = new LFancyLabel();
|
||||
releasedLabel.setForeground(Color.yellow);
|
||||
releasedLabel
|
||||
.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
releasedLabel.setText("");
|
||||
releasedLabel.setPosition(new Point(10, 50));
|
||||
releasedLabel.setShown(true);
|
||||
|
||||
savedLabel = new LFancyLabel();
|
||||
savedLabel.setForeground(Color.yellow);
|
||||
savedLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
savedLabel.setText("");
|
||||
savedLabel.setPosition(new Point(10, 70));
|
||||
savedLabel.setShown(true);
|
||||
|
||||
outLabel = new LFancyLabel();
|
||||
outLabel.setForeground(Color.yellow);
|
||||
outLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
outLabel.setText("");
|
||||
outLabel.setPosition(new Point(10, 90));
|
||||
outLabel.setShown(true);
|
||||
|
||||
lblLemmingFlow = new LFancyLabel();
|
||||
lblLemmingFlow.setForeground(Color.black);
|
||||
lblLemmingFlow.setFont(LFancyLabel
|
||||
.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
lblLemmingFlow.setText("");
|
||||
lblLemmingFlow.setPosition(new Point(20, 360));
|
||||
lblLemmingFlow.setShown(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be initialized.
|
||||
*/
|
||||
protected void specialInitialize() { }
|
||||
|
||||
/**
|
||||
* Describe <code>updateStuff</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void updateStuff() {
|
||||
//Update UI:
|
||||
timeLabel.setText(Long.toString(level.getTimeRemaining() / 1000));
|
||||
releasedLabel.setText("Released: "
|
||||
+ Integer.toString(numReleasedLemmings)
|
||||
+ "/" + strNumLemmings);
|
||||
savedLabel.setText("Saved: "
|
||||
+ Integer.toString(level.getLemmingsSaved())
|
||||
+ "/" + strLemmingsToSave);
|
||||
outLabel.setText("Out: "
|
||||
+ Integer.toString(numLemmingsOut));
|
||||
lblLemmingFlow.setText(Integer
|
||||
.toString(101 - level.getLemmingFlow()));
|
||||
jobs.updateButtons();
|
||||
|
||||
specialUpdate();
|
||||
|
||||
renderer.updateCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the special update.
|
||||
*/
|
||||
protected void specialUpdate() { }
|
||||
|
||||
//@roseuid 4066242E013C
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
killed = true;
|
||||
level = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*This method will set the gamespeed;
|
||||
*@param speed for gamespeed
|
||||
*/
|
||||
public void setGameSpeed(long speed) {
|
||||
|
||||
gameSpeed = speed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the level and goes on to the next state.
|
||||
*/
|
||||
public void endLevel() {
|
||||
//Go to the level results state:
|
||||
level.pause();
|
||||
GameEngine.getInstance().setCurrentState(new LevelResultsState(level));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles it when the pause button is pressed.
|
||||
*/
|
||||
protected void handlePauseButton() {
|
||||
singlePauseButtonHandle();
|
||||
specialPauseHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>singlePauseButtonHandle</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void singlePauseButtonHandle() {
|
||||
boolean p = pauseToggle.isSelected();
|
||||
|
||||
if (p) {
|
||||
//We have paused:
|
||||
level.pause();
|
||||
|
||||
} else {
|
||||
//We have unpaused:
|
||||
level.unpause();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getPauseButton</code> method here.
|
||||
*
|
||||
* @return a <code>LToggleButton</code> value
|
||||
*/
|
||||
protected LToggleButton getPauseButton() {
|
||||
return pauseToggle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for pause.
|
||||
*/
|
||||
protected void specialPauseHandle() { }
|
||||
|
||||
/**
|
||||
* Handles it when the speedup button is pressed.
|
||||
*/
|
||||
protected void handleSpeedupButton() {
|
||||
singleSpeedupButtonHandle();
|
||||
specialSpeedupHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>singleSpeedupButtonHandle</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void singleSpeedupButtonHandle() {
|
||||
boolean s = speedToggle.isSelected();
|
||||
|
||||
if (s) {
|
||||
//We speed up:
|
||||
//NOTE here that the name of the variable "gameSpeed" is a
|
||||
//little misleading. It's really the delay between
|
||||
//updates. Hence, when we want to speed up, we decrease this
|
||||
//gamespeed.
|
||||
gameSpeed /= 10;
|
||||
|
||||
} else {
|
||||
//We slow down:
|
||||
gameSpeed *= 10;
|
||||
|
||||
}
|
||||
|
||||
//Update the Level's notion of time:
|
||||
level.setTimeIncrement(gameSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for speedup.
|
||||
*/
|
||||
protected void specialSpeedupHandle() { }
|
||||
|
||||
/**
|
||||
* Handles it when the nuke button is pressed.
|
||||
*/
|
||||
protected void handleNukeButton() {
|
||||
singleNukeButtonHandle();
|
||||
specialNukeHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>singleNukeButtonHandle</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void singleNukeButtonHandle() {
|
||||
boolean n = nukeToggle.isSelected();
|
||||
|
||||
if (n) {
|
||||
//Gotta Nuke:
|
||||
level.nukeEmALL();
|
||||
} else {
|
||||
//We are already nukin'
|
||||
nukeToggle.toggleSelected();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for nuke.
|
||||
*/
|
||||
protected void specialNukeHandle() { }
|
||||
|
||||
/**
|
||||
* Handles it when the increase button is pressed.
|
||||
*/
|
||||
protected void handleIncreaseButton() {
|
||||
singleIncreaseButtonHandle();
|
||||
specialIncreaseHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>singleIncreaseButtonHandle</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void singleIncreaseButtonHandle() {
|
||||
level.increaseLemmingFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for increase.
|
||||
*/
|
||||
protected void specialIncreaseHandle() { }
|
||||
|
||||
/**
|
||||
* Handles it when the decrease button is pressed.
|
||||
*/
|
||||
protected void handleDecreaseButton() {
|
||||
singleDecreaseButtonHandle();
|
||||
specialDecreaseHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>singleDecreaseButtonHandle</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void singleDecreaseButtonHandle() {
|
||||
level.decreaseLemmingFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for decrease.
|
||||
*/
|
||||
protected void specialDecreaseHandle() { }
|
||||
|
||||
//@roseuid 4066242E016E
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String a = ae.getActionCommand();
|
||||
|
||||
if (a.equals("pause")) {
|
||||
handlePauseButton();
|
||||
|
||||
} else if (a.equals("speedup")) {
|
||||
handleSpeedupButton();
|
||||
|
||||
} else if (a.equals("nuke")) {
|
||||
handleNukeButton();
|
||||
|
||||
} else if (a.equals("increase")) {
|
||||
handleIncreaseButton();
|
||||
|
||||
} else if (a.equals("decrease")) {
|
||||
handleDecreaseButton();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>isPauseSelected</code> method here.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean isPauseSelected() {
|
||||
return pauseToggle.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getGameSpeed</code> method here.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int getGameSpeed() {
|
||||
return (int) gameSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getLemmingFlow</code> method here.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int getLemmingFlow() {
|
||||
return (int) level.getLemmingFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to keys and stuff.
|
||||
*/
|
||||
private abstract class LKeyListener
|
||||
extends LLeafComponent implements ITypable {
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*accessor for gpp
|
||||
*@return GamePlayPanel
|
||||
*/
|
||||
public GamePlayPanel getGamePlayPanel() {
|
||||
return gpp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
//import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.Graphics;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.gui.ITypable;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.JobContainer;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LToggleButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
//import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
//import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class HelpState: Help screen...
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 21, 2004) - Created the HelpState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0, Apr. 21, 2004
|
||||
*/
|
||||
public class HelpState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Display debug information?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The label to display Help title.
|
||||
*/
|
||||
private LFancyLabel title;
|
||||
|
||||
/**
|
||||
* The label to display Help subtitle.
|
||||
*/
|
||||
private LFancyLabel subTitle;
|
||||
|
||||
/**
|
||||
* The label to display singleplayer info.
|
||||
*/
|
||||
private LFancyLabel single;
|
||||
|
||||
/**
|
||||
* The label to display singleplayer info.
|
||||
*/
|
||||
private LFancyLabel singlet;
|
||||
|
||||
/**
|
||||
* The label to display multiplayer info.
|
||||
*/
|
||||
private LFancyLabel multi;
|
||||
|
||||
/**
|
||||
* The label to display multiplayer info.
|
||||
*/
|
||||
private LFancyLabel multit;
|
||||
|
||||
/**
|
||||
* The label to display hostbox info.
|
||||
*/
|
||||
private LFancyLabel hostBox;
|
||||
|
||||
/**
|
||||
* The label to display hostbox info.
|
||||
*/
|
||||
private LFancyLabel hostBoxt;
|
||||
|
||||
/**
|
||||
* The label to display portbox info.
|
||||
*/
|
||||
private LFancyLabel portBox;
|
||||
|
||||
/**
|
||||
* The label to display portbox info.
|
||||
*/
|
||||
private LFancyLabel portBoxt;
|
||||
|
||||
/**
|
||||
* The label to display hostButton info.
|
||||
*/
|
||||
private LFancyLabel hostButton;
|
||||
|
||||
/**
|
||||
* The label to display hostButton info.
|
||||
*/
|
||||
private LFancyLabel hostButtont;
|
||||
|
||||
/**
|
||||
* The label to display connectButton info.
|
||||
*/
|
||||
private LFancyLabel connectButton;
|
||||
|
||||
/**
|
||||
* The label to display connectButton info.
|
||||
*/
|
||||
private LFancyLabel connectButtont;
|
||||
|
||||
/**
|
||||
* The label to display credits info.
|
||||
*/
|
||||
private LFancyLabel credits;
|
||||
|
||||
/**
|
||||
* The label to display credits info.
|
||||
*/
|
||||
private LFancyLabel creditst;
|
||||
|
||||
/**
|
||||
* The label to display help info.
|
||||
*/
|
||||
private LFancyLabel help;
|
||||
|
||||
/**
|
||||
* The label to display help info.
|
||||
*/
|
||||
private LFancyLabel helpt;
|
||||
|
||||
/**
|
||||
* The label to display quit info.
|
||||
*/
|
||||
private LFancyLabel quit;
|
||||
|
||||
/**
|
||||
* The label to display quit info.
|
||||
*/
|
||||
private LFancyLabel quitt;
|
||||
|
||||
/**
|
||||
* The label to display back info.
|
||||
*/
|
||||
private LFancyLabel back;
|
||||
|
||||
/**
|
||||
* The label to display back info.
|
||||
*/
|
||||
private LFancyLabel backt;
|
||||
|
||||
/**
|
||||
* The label to display mainmenu info.
|
||||
*/
|
||||
private LFancyLabel mainMenu;
|
||||
|
||||
/**
|
||||
* The label to display mainmenu info.
|
||||
*/
|
||||
private LFancyLabel mainMenut;
|
||||
|
||||
/**
|
||||
* The label to other gameplay info.
|
||||
*/
|
||||
private LFancyLabel gamePlay;
|
||||
|
||||
/**
|
||||
* Creates a new <code>HelpState</code> instance.
|
||||
*/
|
||||
public HelpState() {
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance()
|
||||
.getTileSet("background"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
title = new LFancyLabel();
|
||||
title.setForeground(Color.black);
|
||||
title.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 35.0f));
|
||||
title.setShown(true);
|
||||
|
||||
subTitle = new LFancyLabel();
|
||||
subTitle.setForeground(Color.black);
|
||||
subTitle.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
subTitle.setShown(true);
|
||||
|
||||
single = new LFancyLabel();
|
||||
single.setForeground(Color.black);
|
||||
single.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
single.setShown(true);
|
||||
|
||||
singlet = new LFancyLabel();
|
||||
singlet.setForeground(Color.black);
|
||||
singlet.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
singlet.setShown(true);
|
||||
|
||||
multi = new LFancyLabel();
|
||||
multi.setForeground(Color.black);
|
||||
multi.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
multi.setShown(true);
|
||||
|
||||
multit = new LFancyLabel();
|
||||
multit.setForeground(Color.black);
|
||||
multit.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
multit.setShown(true);
|
||||
|
||||
hostBox = new LFancyLabel();
|
||||
hostBox.setForeground(Color.black);
|
||||
hostBox.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 14.0f));
|
||||
hostBox.setShown(true);
|
||||
|
||||
hostBoxt = new LFancyLabel();
|
||||
hostBoxt.setForeground(Color.black);
|
||||
hostBoxt.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 12.0f));
|
||||
hostBoxt.setShown(true);
|
||||
|
||||
portBox = new LFancyLabel();
|
||||
portBox.setForeground(Color.black);
|
||||
portBox.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 14.0f));
|
||||
portBox.setShown(true);
|
||||
|
||||
portBoxt = new LFancyLabel();
|
||||
portBoxt.setForeground(Color.black);
|
||||
portBoxt.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 12.0f));
|
||||
portBoxt.setShown(true);
|
||||
|
||||
hostButton = new LFancyLabel();
|
||||
hostButton.setForeground(Color.black);
|
||||
hostButton.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 14.0f));
|
||||
hostButton.setShown(true);
|
||||
|
||||
hostButtont = new LFancyLabel();
|
||||
hostButtont.setForeground(Color.black);
|
||||
hostButtont.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 12.0f));
|
||||
hostButtont.setShown(true);
|
||||
|
||||
connectButton = new LFancyLabel();
|
||||
connectButton.setForeground(Color.black);
|
||||
connectButton.setFont(
|
||||
LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 14.0f));
|
||||
connectButton.setShown(true);
|
||||
|
||||
connectButtont = new LFancyLabel();
|
||||
connectButtont.setForeground(Color.black);
|
||||
connectButtont.setFont(
|
||||
LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 12.0f));
|
||||
connectButtont.setShown(true);
|
||||
|
||||
credits = new LFancyLabel();
|
||||
credits.setForeground(Color.black);
|
||||
credits.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
credits.setShown(true);
|
||||
|
||||
creditst = new LFancyLabel();
|
||||
creditst.setForeground(Color.black);
|
||||
creditst.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
creditst.setShown(true);
|
||||
|
||||
help = new LFancyLabel();
|
||||
help.setForeground(Color.black);
|
||||
help.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
help.setShown(true);
|
||||
|
||||
helpt = new LFancyLabel();
|
||||
helpt.setForeground(Color.black);
|
||||
helpt.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
helpt.setShown(true);
|
||||
|
||||
quit = new LFancyLabel();
|
||||
quit.setForeground(Color.black);
|
||||
quit.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
quit.setShown(true);
|
||||
|
||||
quitt = new LFancyLabel();
|
||||
quitt.setForeground(Color.black);
|
||||
quitt.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
quitt.setShown(true);
|
||||
|
||||
back = new LFancyLabel();
|
||||
back.setForeground(Color.black);
|
||||
back.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
back.setShown(true);
|
||||
|
||||
backt = new LFancyLabel();
|
||||
backt.setForeground(Color.black);
|
||||
backt.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
backt.setShown(true);
|
||||
|
||||
mainMenu = new LFancyLabel();
|
||||
mainMenu.setForeground(Color.black);
|
||||
mainMenu.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
mainMenu.setShown(true);
|
||||
|
||||
mainMenut = new LFancyLabel();
|
||||
mainMenut.setForeground(Color.black);
|
||||
mainMenut.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 16.0f));
|
||||
mainMenut.setShown(true);
|
||||
|
||||
gamePlay = new LFancyLabel();
|
||||
gamePlay.setForeground(Color.black);
|
||||
gamePlay.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.PLAIN, 18.0f));
|
||||
gamePlay.setShown(true);
|
||||
|
||||
//Initialize button:
|
||||
LButton goOn = new LButton();
|
||||
goOn.setPosition(new Point(10, 590));
|
||||
goOn.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mpb_back"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
goOn.addActionListener(this);
|
||||
goOn.setActionCommand("goOn");
|
||||
goOn.setShown(true);
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(goOn);
|
||||
np.addChild(title);
|
||||
np.addChild(subTitle);
|
||||
np.addChild(single);
|
||||
np.addChild(singlet);
|
||||
np.addChild(multi);
|
||||
np.addChild(multit);
|
||||
np.addChild(hostBox);
|
||||
np.addChild(hostBoxt);
|
||||
np.addChild(portBox);
|
||||
np.addChild(portBoxt);
|
||||
np.addChild(hostButton);
|
||||
np.addChild(hostButtont);
|
||||
np.addChild(connectButton);
|
||||
np.addChild(connectButtont);
|
||||
np.addChild(credits);
|
||||
np.addChild(creditst);
|
||||
np.addChild(help);
|
||||
np.addChild(helpt);
|
||||
np.addChild(quit);
|
||||
np.addChild(quitt);
|
||||
np.addChild(back);
|
||||
np.addChild(backt);
|
||||
np.addChild(mainMenu);
|
||||
np.addChild(mainMenut);
|
||||
np.addChild(gamePlay);
|
||||
|
||||
setUI(np);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
title.setText("Help");
|
||||
title.setPosition(new Point(30, 80));
|
||||
|
||||
subTitle.setText("Menu Navigation:");
|
||||
subTitle.setPosition(new Point(65, 125));
|
||||
|
||||
single.setText("\"SinglePlayer\" Button:");
|
||||
single.setPosition(new Point(100, 165));
|
||||
|
||||
singlet.setText("Starts a SinglePlayer game");
|
||||
singlet.setPosition(new Point(302, 165));
|
||||
|
||||
multi.setText("\"MultiPlayer\" Button:");
|
||||
multi.setPosition(new Point(100, 205));
|
||||
|
||||
multit.setText("Starts a MultiPlayer game");
|
||||
multit.setPosition(new Point(290, 205));
|
||||
|
||||
hostBox.setText("\"Host\" TextField:");
|
||||
hostBox.setPosition(new Point(135, 230));
|
||||
|
||||
hostBoxt.setText("IP address of host");
|
||||
hostBoxt.setPosition(new Point(260, 230));
|
||||
|
||||
portBox.setText("\"Port\" TextField:");
|
||||
portBox.setPosition(new Point(135, 255));
|
||||
|
||||
portBoxt.setText("Port on host");
|
||||
portBoxt.setPosition(new Point(260, 255));
|
||||
|
||||
hostButton.setText("\"Host\" Button:");
|
||||
hostButton.setPosition(new Point(135, 280));
|
||||
|
||||
hostButtont.setText("Hosts a multiplayer session");
|
||||
hostButtont.setPosition(new Point(247, 280));
|
||||
|
||||
connectButton.setText("\"Connect\" Button:");
|
||||
connectButton.setPosition(new Point(135, 302));
|
||||
|
||||
connectButtont.setText("Connects to a multiplayer session");
|
||||
connectButtont.setPosition(new Point(270, 302));
|
||||
|
||||
credits.setText("\"Credits\" Button:");
|
||||
credits.setPosition(new Point(100, 330));
|
||||
|
||||
creditst.setText("Displays information about the creators");
|
||||
creditst.setPosition(new Point(255, 330));
|
||||
|
||||
help.setText("\"Help\" Button:");
|
||||
help.setPosition(new Point(100, 365));
|
||||
|
||||
helpt.setText("Displays this screen");
|
||||
helpt.setPosition(new Point(233, 365));
|
||||
|
||||
quit.setText("\"Quit\" Button:");
|
||||
quit.setPosition(new Point(100, 405));
|
||||
|
||||
quitt.setText("Exits the game");
|
||||
quitt.setPosition(new Point(229, 405));
|
||||
|
||||
back.setText("\"Back\" Button:");
|
||||
back.setPosition(new Point(100, 445));
|
||||
|
||||
backt.setText("Returns to previous menu");
|
||||
backt.setPosition(new Point(236, 445));
|
||||
|
||||
mainMenu.setText("\"MainMenu\" Button:");
|
||||
mainMenu.setPosition(new Point(100, 482));
|
||||
|
||||
mainMenut.setText("Returns to the main menu");
|
||||
mainMenut.setPosition(new Point(280, 482));
|
||||
|
||||
gamePlay.setText("For help on game-play, refer to the html user manual.");
|
||||
gamePlay.setPosition(new Point(200, 540));
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("HelpState: I am initialized!");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
if (VERBOSE) {
|
||||
System.err.println("HelprState: I am cleaned up!");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (VERBOSE) {
|
||||
System.err.println("HelpState: Got some action - "
|
||||
+ ae.getActionCommand());
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
//Go back to the Multiplayer setup state:
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Interface ICleanable: The implementing objects will be able to be
|
||||
* cleaned up.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 15, 2004) - Created the ICleanable interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 15, 2004
|
||||
*/
|
||||
public interface ICleanable {
|
||||
|
||||
/**
|
||||
* Cleans up all references for the garbage collector.
|
||||
*/
|
||||
public void cleanUp();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsObject;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJob;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobFactory;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
/**
|
||||
* Represents a generic lemming, that can move around, and do
|
||||
* stuff. What exactly it does is decided by the lemming's occupation.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @see LemmingJob
|
||||
*/
|
||||
public final class Lemming extends PhysicsObject implements ICleanable {
|
||||
|
||||
/**
|
||||
* What the lemming does.
|
||||
*/
|
||||
private LemmingJob occupation;
|
||||
|
||||
/**
|
||||
* The physics object associated with the lemming.
|
||||
*/
|
||||
//private PhysicsObject physics;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Lemming</code> instance.
|
||||
*
|
||||
*/
|
||||
public Lemming() {
|
||||
//Set up physics:
|
||||
super();
|
||||
//physics = new PhysicsObject();
|
||||
|
||||
//Set Occupation:
|
||||
setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>cleanUp</code> method here.
|
||||
*
|
||||
*/
|
||||
public void cleanUp() {
|
||||
occupation.cleanUp();
|
||||
occupation = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the occupation property.
|
||||
*
|
||||
* @return the current value of the occupation property
|
||||
*/
|
||||
public LemmingJob getOccupation() {
|
||||
return occupation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the occupation property.
|
||||
*
|
||||
* @param id the id of the occupation to give this lemming.
|
||||
*/
|
||||
public void setOccupation(String id) {
|
||||
occupation = LemmingJobFactory.getInstance().makeJob(id);
|
||||
occupation.setOwner(this);
|
||||
updateDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setOccupation</code> method here.
|
||||
*
|
||||
* @param job a <code>LemmingJob</code> value
|
||||
*/
|
||||
public void setOccupation(LemmingJob job) {
|
||||
job.setOwner(this);
|
||||
occupation = job;
|
||||
updateDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the physics property.
|
||||
*
|
||||
* @return the current value of the physics property
|
||||
*/
|
||||
public PhysicsObject getPhysics() {
|
||||
//Should deprecate this. :( Really should.
|
||||
return this;
|
||||
// return physics;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method should be called whenever the lemming's direction
|
||||
* changes. It will update the current animation with the new
|
||||
* direction of movement.
|
||||
*/
|
||||
public void updateDirection() {
|
||||
int xVelocity = getVelocity().getI();
|
||||
Direction dir;
|
||||
|
||||
if (xVelocity == 0) {
|
||||
dir = Direction.NO_DIRECTION;
|
||||
} else if (xVelocity < 0) {
|
||||
dir = Direction.LEFT;
|
||||
} else {
|
||||
dir = Direction.RIGHT;
|
||||
}
|
||||
|
||||
if (occupation.getRegularAnimation().getMovementDirection() != dir) {
|
||||
occupation.getRegularAnimation().setMovementDirection(dir);
|
||||
}
|
||||
|
||||
if (occupation.getFallingAnimation().getMovementDirection() != dir) {
|
||||
occupation.getFallingAnimation().setMovementDirection(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of a lemming.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
sb.append("Lemming: (").append(occupation.getId()).append(")\n");
|
||||
sb.append(toString()).append("\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class LemmingDrown: This pretty sprite is created when the lemming
|
||||
* drowns.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the LemmingDrown class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public class LemmingDrown extends PrettySprite {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingDrown</code> instance.
|
||||
*/
|
||||
public LemmingDrown() {
|
||||
super("drown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (getAnimation().getCurrentFrame() == 0) {
|
||||
//The animation is through.
|
||||
//Create an angel:
|
||||
PrettySprite a = new LemmingsSoul();
|
||||
a.getPosition().setPoint(getPosition().getX(),
|
||||
getPosition().getY(),
|
||||
getPosition().getZ());
|
||||
|
||||
getLevel().addPrettySprite(a);
|
||||
|
||||
//We are done:
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class LemmingSplat: When the lemming falls too far and smashes into
|
||||
* the ground, this blood-splattering animation will be played.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 12, 2004) - Created the LemmingSplat class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 12, 2004
|
||||
*/
|
||||
public class LemmingSplat extends PrettySprite {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingSplat</code> instance.
|
||||
*/
|
||||
public LemmingSplat() {
|
||||
super("splat");
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (getAnimation().getCurrentFrame() == 0) {
|
||||
//The animation is through.
|
||||
//Create an angel:
|
||||
PrettySprite a = new LemmingsSoul();
|
||||
a.getPosition().setPoint(getPosition().getX(),
|
||||
getPosition().getY(),
|
||||
getPosition().getZ());
|
||||
|
||||
getLevel().addPrettySprite(a);
|
||||
|
||||
//We are done:
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class LemmingsSoul: You have failed, The lemming is DEAD, His soul
|
||||
* goes to heaven.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the LemmingsSoul class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class LemmingsSoul extends PrettySprite {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingsSoul</code> instance.
|
||||
*/
|
||||
public LemmingsSoul() {
|
||||
super("angel");
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
|
||||
if (getPosition().getY() <= 5) {
|
||||
//We are almost at the top of the screen... That's close enough.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,386 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
/**
|
||||
* This class contains the data associated with a certain level. It is
|
||||
* essentially your template to create playable levels.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public class LevelData {
|
||||
|
||||
/**
|
||||
* The thumbnail to display for the level.
|
||||
*/
|
||||
private BufferedImage thumbnail;
|
||||
|
||||
/**
|
||||
* The id of the level. This is essentially the name of the
|
||||
* directory that the file was loaded from.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* The name of the level.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The number of lemmings initially let out in the level.
|
||||
*/
|
||||
private int numLemmings;
|
||||
|
||||
/**
|
||||
* The percentage of lemmings we need to save. Needs to be between 0 and 1.
|
||||
*/
|
||||
private int percentToSave;
|
||||
|
||||
/**
|
||||
* The time limit for the level.
|
||||
*/
|
||||
private long timeLimit;
|
||||
|
||||
/**
|
||||
* The position of the entrance point on the map.
|
||||
*/
|
||||
private Point entrancePoint;
|
||||
|
||||
/**
|
||||
* The position of the exit point on the map.
|
||||
*/
|
||||
private Point exitPoint;
|
||||
|
||||
/**
|
||||
* The list of all portals available in this level.
|
||||
*/
|
||||
private List portals;
|
||||
|
||||
/**
|
||||
* This map will contain the number of jobs of each type available
|
||||
* for the level.
|
||||
*/
|
||||
private Map jobMap;
|
||||
|
||||
/**
|
||||
* The level of water on the level. Uhhh, yeah. -1 means there is no
|
||||
* water on the level.
|
||||
*/
|
||||
private int waterLevel;
|
||||
|
||||
/**
|
||||
* The lines of the briefing to display before the level.
|
||||
*/
|
||||
private String[] mapBriefing;
|
||||
|
||||
/**
|
||||
* The lines of the win statement to display after the level.
|
||||
*/
|
||||
private String[] winStatement;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelData</code> instance.
|
||||
*
|
||||
*/
|
||||
public LevelData() {
|
||||
thumbnail = null;
|
||||
|
||||
entrancePoint = new Point(0, 0);
|
||||
exitPoint = new Point(0, 0);
|
||||
jobMap = new HashMap(LemmingJobSettings.ALL_JOB_NAMES.length);
|
||||
portals = new Vector();
|
||||
|
||||
name = "";
|
||||
|
||||
numLemmings = 0;
|
||||
percentToSave = 0;
|
||||
timeLimit = 0;
|
||||
waterLevel = -1;
|
||||
mapBriefing = null;
|
||||
winStatement = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the thumbnail property.
|
||||
*
|
||||
* @return the current value of the thumbnail property
|
||||
*/
|
||||
public BufferedImage getThumbnail() {
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the thumbnail property.
|
||||
*
|
||||
* @param aThumbnail the new value of the thumbnail property
|
||||
*/
|
||||
public void setThumbnail(BufferedImage aThumbnail) {
|
||||
thumbnail = aThumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the name property.
|
||||
*
|
||||
* @return the current value of the name property
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the name property.
|
||||
*
|
||||
* @param aName the new value of the name property
|
||||
*/
|
||||
public void setName(String aName) {
|
||||
name = aName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the id property.
|
||||
*
|
||||
* @return the current value of the id property
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the id property.
|
||||
*
|
||||
* @param aId the new value of the id property
|
||||
*/
|
||||
public void setId(String aId) {
|
||||
id = aId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the numLemmings property.
|
||||
*
|
||||
* @return the current value of the numLemmings property
|
||||
*/
|
||||
public int getNumLemmings() {
|
||||
return numLemmings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the numLemmings property.
|
||||
*
|
||||
* @param aNumLemmings the new value of the numLemmings property
|
||||
*/
|
||||
public void setNumLemmings(int aNumLemmings) {
|
||||
numLemmings = aNumLemmings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the percentToSave property.
|
||||
*
|
||||
* @return the current value of the percentToSave property
|
||||
*/
|
||||
public int getPercentToSave() {
|
||||
return percentToSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the percentToSave property.
|
||||
*
|
||||
* @param aPercentToSave the new value of the percentToSave property
|
||||
*/
|
||||
public void setPercentToSave(int aPercentToSave) {
|
||||
percentToSave = aPercentToSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the timeLimit property.
|
||||
*
|
||||
* @return the current value of the timeLimit property
|
||||
*/
|
||||
public long getTimeLimit() {
|
||||
return timeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the timeLimit property.
|
||||
*
|
||||
* @param aTimeLimit the new value of the timeLimit property
|
||||
*/
|
||||
public void setTimeLimit(long aTimeLimit) {
|
||||
timeLimit = aTimeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of entrancePoint.
|
||||
* @return value of entrancePoint.
|
||||
*/
|
||||
public Point getEntrancePoint() {
|
||||
return entrancePoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of entrancePoint.
|
||||
* @param v Value to assign to entrancePoint.
|
||||
*/
|
||||
public void setEntrancePoint(Point v) {
|
||||
this.entrancePoint = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of entrancePoint.
|
||||
* @param x an <code>int</code> value
|
||||
* @param y an <code>int</code> value
|
||||
*/
|
||||
public void setEntrancePoint(int x, int y) {
|
||||
this.entrancePoint.x = x;
|
||||
this.entrancePoint.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of exitPoint.
|
||||
* @return value of exitPoint.
|
||||
*/
|
||||
public Point getExitPoint() {
|
||||
return exitPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of exitPoint.
|
||||
* @param v Value to assign to exitPoint.
|
||||
*/
|
||||
public void setExitPoint(Point v) {
|
||||
this.exitPoint = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of exitPoint.
|
||||
* @param x an <code>int</code> value
|
||||
* @param y an <code>int</code> value
|
||||
*/
|
||||
public void setExitPoint(int x, int y) {
|
||||
this.exitPoint.x = x;
|
||||
this.exitPoint.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of waterLevel.
|
||||
* @return value of waterLevel.
|
||||
*/
|
||||
public int getWaterLevel() {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of waterLevel. Note that -1 is a magic value which
|
||||
* means there is no water on the level. Other negative numbers will
|
||||
* be ABSed before application.
|
||||
* @param v Value to assign to waterLevel.
|
||||
*/
|
||||
public void setWaterLevel(int v) {
|
||||
if (v < -1) {
|
||||
this.waterLevel = -v;
|
||||
} else {
|
||||
this.waterLevel = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the number of jobs for the appropriate job id for the level.
|
||||
*
|
||||
* @param idd a <code>String</code> value
|
||||
* @param num an <code>int</code> value
|
||||
*/
|
||||
public void addJob(String idd, int num) {
|
||||
jobMap.put(idd, new Integer(num));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of jobs of the specified type for this level.
|
||||
*
|
||||
* @param idd a <code>String</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public int getNumJobs(String idd) {
|
||||
if (!jobMap.containsKey(idd)) { return 0; }
|
||||
|
||||
Integer i = (Integer) jobMap.get(idd);
|
||||
|
||||
return i.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the job map.
|
||||
*
|
||||
* @return a <code>Map</code> value
|
||||
*/
|
||||
public Map getJobMap() {
|
||||
return jobMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job map
|
||||
* @param jm , map of jobs to set
|
||||
*/
|
||||
public void setJobMap(Map jm) {
|
||||
jobMap = jm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getPortals</code> method here.
|
||||
*
|
||||
* @return a <code>List</code> value
|
||||
*/
|
||||
public List getPortals() {
|
||||
return portals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>addPortal</code> method here.
|
||||
*
|
||||
* @param type a <code>String</code> value
|
||||
* @param value a <code>String</code> value
|
||||
*/
|
||||
public void addPortal(String type, String value) {
|
||||
Portal p = PortalFactory.getInstance().makePortal(type, value);
|
||||
|
||||
if (p != null) {
|
||||
portals.add(p);
|
||||
|
||||
if (type.equals(PortalFactory.PORTAL_TYPES[0])) {
|
||||
entrancePoint.x = p.getPhysics().getPosition().getX();
|
||||
entrancePoint.y = p.getPhysics().getPosition().getY();
|
||||
} else if (type.equals(PortalFactory.PORTAL_TYPES[1])) {
|
||||
exitPoint.x = p.getPhysics().getPosition().getX();
|
||||
exitPoint.y = p.getPhysics().getPosition().getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of the level.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
sb.append("Level (").append(getId()).append(")\n");
|
||||
sb.append("\tName: ").append(getName()).append("\n");
|
||||
sb.append("\tLemmings: ").append(getNumLemmings()).append("\n");
|
||||
sb.append("\tSave: ").append(getPercentToSave() * 100).append("%\n");
|
||||
sb.append("\tTime Limit: ").append(getTimeLimit()).append(" sec\n");
|
||||
sb.append("\tEntrance: (").append(getEntrancePoint().x)
|
||||
.append(", ").append(getEntrancePoint().y).append(")\n");
|
||||
sb.append("\tExit: (").append(getExitPoint().x)
|
||||
.append(", ").append(getExitPoint().y).append(")\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class LevelEntrance: This is where lemmings enter a level.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 28, 2004) - Created the LevelEntrance class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 28, 2004
|
||||
*/
|
||||
public class LevelEntrance extends Portal {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelEntrance</code> instance.
|
||||
*/
|
||||
public LevelEntrance() {
|
||||
super(PortalFactory.PORTAL_TYPES[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called when a lemming enters this portal.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
*/
|
||||
public void processLemmingEntry(Lemming l) {
|
||||
//This is an *entry* nothing to do with the lemming.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class LevelExit: This is where lemmings exit a level.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 28, 2004) - Created the LevelExit class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 28, 2004
|
||||
*/
|
||||
public class LevelExit extends Portal {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelExit</code> instance.
|
||||
*/
|
||||
public LevelExit() {
|
||||
super(PortalFactory.PORTAL_TYPES[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called when a lemming enters this portal.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
*/
|
||||
public void processLemmingEntry(Lemming l) {
|
||||
//This lemming has been saved. Wohoo!
|
||||
if (GameEngine.VERBOSE) {
|
||||
System.out.println("Homie's home (aka a Lemming has been saved)");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
getParent().killLemming(l, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
//import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
//import java.util.Random;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class LevelResultsState: Shows the results of a level.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the LevelResultsState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public class LevelResultsState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The level, whose results we are showing.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Contains the name of the level.
|
||||
*/
|
||||
private LFancyLabel lblLevelName;
|
||||
|
||||
/**
|
||||
* Something to show when the user has won/lost.
|
||||
*/
|
||||
private LLabel[] lblSayings;
|
||||
|
||||
/**
|
||||
* How many lemmings were saved.
|
||||
*/
|
||||
private LLabel lblLemmingsSaved;
|
||||
|
||||
/**
|
||||
* How many lemmings were not saved.
|
||||
*/
|
||||
private LLabel lblLemmingsKilled;
|
||||
|
||||
/**
|
||||
* How much time did it take?
|
||||
*/
|
||||
private LLabel lblTimeTaken;
|
||||
|
||||
/**
|
||||
* Describe variable <code>lemmingsSaved</code> here.
|
||||
*
|
||||
*/
|
||||
private int lemmingsSaved;
|
||||
|
||||
/**
|
||||
* Describe variable <code>lemmingsToSave</code> here.
|
||||
*
|
||||
*/
|
||||
private int lemmingsToSave;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelResultsState</code> instance.
|
||||
*@param l len
|
||||
*/
|
||||
public LevelResultsState(Level l) {
|
||||
level = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
LRootPane np = new LRootPane();
|
||||
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance().getTileSet("bg_result"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Buttons:
|
||||
LButton back = new LButton();
|
||||
back
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("rb_back"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
back.setPosition(new Point(10, 590));
|
||||
back.setShown(true);
|
||||
back.setActionCommand("back");
|
||||
back.addActionListener(this);
|
||||
|
||||
LButton play = new LButton();
|
||||
play
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("rb_play"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
play.setPosition(new Point(680, 590));
|
||||
play.setShown(true);
|
||||
play.setActionCommand("play");
|
||||
play.addActionListener(this);
|
||||
|
||||
//Labels:
|
||||
lblLevelName = new LFancyLabel();
|
||||
lblLevelName.setFont(LFancyLabel.DEFAULT_FONT
|
||||
.deriveFont(Font.BOLD, 30.0f));
|
||||
lblLevelName.setText(level.getData().getName());
|
||||
lblLevelName.setPosition(new Point(250, 180));
|
||||
lblLevelName.setShown(true);
|
||||
|
||||
//TODOXC: Set this to whatever it needs to be eventually.
|
||||
lblSayings = null;
|
||||
|
||||
lemmingsSaved = level.getLemmingsSaved();
|
||||
lemmingsToSave = level.getData().getPercentToSave();
|
||||
lemmingsToSave *= level.getData().getNumLemmings();
|
||||
lemmingsToSave /= 100;
|
||||
|
||||
lblLemmingsSaved = new LLabel();
|
||||
lblLemmingsSaved.setText("Lemmings Saved: " + lemmingsSaved
|
||||
+ "/" + lemmingsToSave);
|
||||
lblLemmingsSaved.setPosition(new Point(300, 220));
|
||||
lblLemmingsSaved.setShown(true);
|
||||
|
||||
lblLemmingsKilled = new LLabel();
|
||||
lblLemmingsKilled
|
||||
.setText("Lemmings Dead: "
|
||||
+ Math.max(level.getData().getNumLemmings()
|
||||
- level.getLemmingsSaved(), 0));
|
||||
lblLemmingsKilled.setPosition(new Point(300, 240));
|
||||
lblLemmingsKilled.setShown(true);
|
||||
|
||||
lblTimeTaken = new LLabel();
|
||||
lblTimeTaken
|
||||
.setText("Time Taken: "
|
||||
+ (level.getData().getTimeLimit()
|
||||
- (level.getTimeRemaining() / 1000)));
|
||||
lblTimeTaken.setPosition(new Point(300, 260));
|
||||
lblTimeTaken.setShown(true);
|
||||
|
||||
np.addChild(bg);
|
||||
np.addChild(lblLevelName);
|
||||
np.addChild(lblLemmingsSaved);
|
||||
np.addChild(lblLemmingsKilled);
|
||||
np.addChild(lblTimeTaken);
|
||||
np.addChild(back);
|
||||
np.addChild(play);
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
level.cleanUp();
|
||||
level = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String a = ae.getActionCommand();
|
||||
|
||||
if (a.equals("back")) {
|
||||
//Go back to the main menu:
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
|
||||
} else if (a.equals("play")) {
|
||||
//Load next level if this one was passed, and this level, if it
|
||||
//was failed.
|
||||
String name = level.getData().getId();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LevelResultsState: Want to play again...");
|
||||
System.out.println("\tLemmings Saved: " + lemmingsSaved);
|
||||
System.out.println("\tRequired to Advance: " + lemmingsToSave);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if (lemmingsSaved >= lemmingsToSave) {
|
||||
//The player saved enough lemmings.
|
||||
String nextLevel = LevelReader.getInstance().findNextLevel(name);
|
||||
|
||||
if (nextLevel == null) {
|
||||
//Went through all levels...
|
||||
|
||||
//Show some kind of "You Win!" screen????? Would be
|
||||
//good. But it's too late now.
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
|
||||
} else {
|
||||
//Go to the next level:
|
||||
GameEngine.getInstance().startSingleLevel(nextLevel);
|
||||
}
|
||||
} else {
|
||||
//Go to same level:
|
||||
GameEngine.getInstance().startSingleLevel(name);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getLevel</code> method here.
|
||||
*
|
||||
* @return a <code>Level</code> value
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setLevel</code> method here.
|
||||
*
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public void setLevel(Level l) {
|
||||
level = l;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LevelContainer;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
/**
|
||||
* This is the main menu state. It displays the main menu stuff, which
|
||||
* allows the player to select to play the single player game, the
|
||||
* multiplayer game, or quit.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public class LevelSelectionState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* The container with the levels.
|
||||
*/
|
||||
private LevelContainer container;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelSelectionState</code> instance.
|
||||
*
|
||||
*/
|
||||
public LevelSelectionState() {
|
||||
//Make sure that the resources we want are loaded:
|
||||
TileSetManager.getInstance().getTileSet("background");
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D005F
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean initialize() {
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance()
|
||||
.getTileSet("background"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize Levels:
|
||||
container = new LevelContainer();
|
||||
String[] levels = LevelReader.getInstance().getLevelList();
|
||||
container.setShown(true);
|
||||
container.setPosition(new Point(20, 40));
|
||||
container.setSize(new Dimension(770, 500));
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
container.addLevelButton(levels[i]);
|
||||
}
|
||||
|
||||
//Initialize buttons:
|
||||
LButton back = new LButton();
|
||||
back
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("lb_back"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
back.setPosition(new Point(10, 590));
|
||||
back.setShown(true);
|
||||
back.setActionCommand("back");
|
||||
back.addActionListener(this);
|
||||
|
||||
LButton play = new LButton();
|
||||
play
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("lb_play"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
play.setPosition(new Point(680, 590));
|
||||
play.setShown(true);
|
||||
play.setActionCommand("play");
|
||||
play.addActionListener(this);
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(container);
|
||||
np.addChild(back);
|
||||
np.addChild(play);
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D0073
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D0091
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String a = ae.getActionCommand();
|
||||
|
||||
if (a.equals("back")) {
|
||||
//Go back to the main menu:
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
} else if (a.equals("play")) {
|
||||
//Play!
|
||||
GameEngine.getInstance().startSingleLevel(container.getSelectedLevel());
|
||||
}
|
||||
|
||||
/*
|
||||
//The button has been clicked. Start the level:
|
||||
|
||||
//Transfer to game now:
|
||||
GamePlayState gps = new GamePlayState("test_level");
|
||||
GameEngine.getInstance().setCurrentState(gps);
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class LoadLevelState: The display to show random humorous messages
|
||||
* while the user is waiting for the level to load.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 01, 2004) - Created the LoadLevelState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 01, 2004
|
||||
*/
|
||||
public class LoadLevelState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* The level that we will be loading here.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Number of millis we want to pass between the sayings.
|
||||
*/
|
||||
// private final long SAYING_DELAY = 4000;
|
||||
|
||||
/**
|
||||
* List of things to say to the user.
|
||||
*/
|
||||
private final String[] sayings = {
|
||||
"Drawing graffiti..",
|
||||
"Circlin' da 'hood...",
|
||||
"Intimidating nubs...",
|
||||
"Chillin'...",
|
||||
"Doing stuff...",
|
||||
"Bling Blingin'...",
|
||||
"You should be playin' Doom now...",
|
||||
"Makin' Waves...",
|
||||
"Writin' da JUnit tests...",
|
||||
"Tracin' rays...",
|
||||
"Studyin' Physics...",
|
||||
"Renderin' Sprites...",
|
||||
"Drawing pretty graphics...",
|
||||
"Checkstylin'...",
|
||||
"Floatin'...",
|
||||
"Makin' final preparations...",
|
||||
"Updatin' the repository...",
|
||||
"Writing clever sayings...",
|
||||
"Isn't it annoying to wait like this?",
|
||||
"Blockin' unnecessary movement...",
|
||||
"Givin' out the drills...",
|
||||
"Assessing the llama population...",
|
||||
};
|
||||
|
||||
/**
|
||||
* The label to display our message to the user in.
|
||||
*/
|
||||
private LFancyLabel message;
|
||||
|
||||
/**
|
||||
* Random number generator.
|
||||
*/
|
||||
private Random generator;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LoadLevelState</code> instance.
|
||||
*/
|
||||
public LoadLevelState() {
|
||||
level = null;
|
||||
|
||||
generator = new Random(System.currentTimeMillis());
|
||||
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance()
|
||||
.getTileSet("bg_loading"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize label:
|
||||
message = new LFancyLabel();
|
||||
message.setForeground(Color.black);
|
||||
message.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
message.setText("");
|
||||
message.setShown(true);
|
||||
message.setPosition(new Point(300, 300));
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(message);
|
||||
|
||||
setUI(np);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
updateText();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
level = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4066242E016E
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
//The user can't click anything here, so...
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the level with the specified id.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public synchronized void loadLevel(final String id) {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
level = LevelReader.getInstance().loadLevel(id);
|
||||
levelLoaded();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be done when the level is done loading.
|
||||
*/
|
||||
private void levelLoaded() {
|
||||
//Transfer control to Game Play State:
|
||||
GameEngine.getInstance()
|
||||
.setCurrentState(new GamePlayState(level));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the text in the label.
|
||||
*/
|
||||
private void updateText() {
|
||||
message.setText(sayings[generator.nextInt(sayings.length)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
import edu.gatech.cs2335.lemmings.gui.ITypable;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* This is the main menu state. It displays the main menu stuff, which
|
||||
* allows the player to select to play the single player game, the
|
||||
* multiplayer game, or quit.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public class MainMenuState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Creates a new <code>MainMenuState</code> instance.
|
||||
*
|
||||
*/
|
||||
public MainMenuState() {
|
||||
//Make sure that the resources we want are loaded:
|
||||
TileSetManager.getInstance().getTileSet("bg_main");
|
||||
TileSetManager.getInstance().getTileSet("mmb_single");
|
||||
TileSetManager.getInstance().getTileSet("mmb_multi");
|
||||
TileSetManager.getInstance().getTileSet("mmb_quit");
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D005F
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean initialize() {
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance().getTileSet("bg_main"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize Buttons:
|
||||
Point pos = new Point(63, 278);
|
||||
LButton single = new LButton();
|
||||
single.setPosition(new Point(pos));
|
||||
single.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mmb_single"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
single.addActionListener(this);
|
||||
single.setActionCommand("single");
|
||||
single.setShown(true);
|
||||
|
||||
pos.x = 575;
|
||||
pos.y = 292;
|
||||
LButton multi = new LButton();
|
||||
multi.setPosition(new Point(pos));
|
||||
multi.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mmb_multi"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
multi.addActionListener(this);
|
||||
multi.setActionCommand("multi");
|
||||
multi.setShown(true);
|
||||
|
||||
pos.x = 315;
|
||||
pos.y = 278;
|
||||
LButton cred = new LButton();
|
||||
cred.setPosition(new Point(pos));
|
||||
cred.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mmb_credits"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
cred.addActionListener(this);
|
||||
cred.setActionCommand("cred");
|
||||
cred.setShown(true);
|
||||
|
||||
pos.x = 15;
|
||||
pos.y = 530;
|
||||
LButton help = new LButton();
|
||||
help.setPosition(new Point(pos));
|
||||
help.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mmb_help"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
help.addActionListener(this);
|
||||
help.setActionCommand("help");
|
||||
help.setShown(true);
|
||||
|
||||
pos.x = 690;
|
||||
pos.y = 515;
|
||||
LButton quit = new LButton();
|
||||
quit.setPosition(new Point(pos));
|
||||
quit.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mmb_quit"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
quit.addActionListener(this);
|
||||
quit.setActionCommand("quit");
|
||||
quit.setShown(true);
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(single);
|
||||
np.addChild(multi);
|
||||
np.addChild(cred);
|
||||
np.addChild(help);
|
||||
np.addChild(quit);
|
||||
|
||||
np.addChild(new LKeyListener() {
|
||||
public void processKeyTyped(char key, int modifiers) {
|
||||
if (key == 'a') {
|
||||
GameEngine.getInstance()
|
||||
.setCurrentState(new AttractState("Attract"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D0073
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29D0091
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String ac = ae.getActionCommand();
|
||||
|
||||
if (GameEngine.VERBOSE) {
|
||||
System.out.println("MainMenuState: Button clicked - " + ac);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if ("single".equals(ac)) {
|
||||
//Go to level selection:
|
||||
GameEngine.getInstance().setCurrentState(new LevelSelectionState());
|
||||
|
||||
} else if ("multi".equals(ac)) {
|
||||
//Go to multiplayer setup screen:
|
||||
GameEngine.getInstance().setCurrentState(new MultiplayerSetupState());
|
||||
|
||||
} else if ("cred".equals(ac)) {
|
||||
//Go to the credits screen:
|
||||
GameEngine.getInstance().setCurrentState(new CreditsState());
|
||||
|
||||
} else if ("help".equals(ac)) {
|
||||
GameEngine.getInstance().setCurrentState(new HelpState());
|
||||
|
||||
} else if ("quit".equals(ac)) {
|
||||
System.exit(0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to keys and stuff.
|
||||
*/
|
||||
private abstract class LKeyListener
|
||||
extends LLeafComponent implements ITypable {
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,473 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
//import java.awt.Rectangle;
|
||||
import java.awt.AlphaComposite;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSet;
|
||||
import edu.gatech.cs2335.lemmings.graphics.ImageLoader;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
/**
|
||||
* The map on which stuff will be happening.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
*/
|
||||
public class Map {
|
||||
|
||||
/**
|
||||
* The background image to display in this map.
|
||||
*/
|
||||
private BufferedImage background;
|
||||
|
||||
/**
|
||||
* The texture image to use for the ground.
|
||||
*/
|
||||
private BufferedImage texture;
|
||||
|
||||
/**
|
||||
* The unbreakable texture used for ground
|
||||
*/
|
||||
private BufferedImage unbreakableTexture;
|
||||
|
||||
/**
|
||||
* This is the map itself. It is not technically a "map", but rather
|
||||
* a color key for the map.
|
||||
*/
|
||||
private BufferedImage map;
|
||||
|
||||
/**
|
||||
* Unbreakable map
|
||||
*/
|
||||
private BufferedImage unbreakableMap;
|
||||
|
||||
/**
|
||||
* This is the actual displayed map
|
||||
*/
|
||||
private BufferedImage gameMap;
|
||||
|
||||
/**
|
||||
* This is the indestructable game Map
|
||||
*/
|
||||
private BufferedImage indestructGameMap;
|
||||
|
||||
/**
|
||||
* The water animation displayed on the map.
|
||||
*/
|
||||
private AnimatedSprite waterAnimation;
|
||||
|
||||
|
||||
|
||||
//////////////////
|
||||
// Constructors //
|
||||
//////////////////
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>Map</code> instance.
|
||||
*
|
||||
*/
|
||||
public Map() {
|
||||
background = null;
|
||||
map = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// Accessors / Modifiers //
|
||||
///////////////////////////
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access method for the background property.
|
||||
*
|
||||
* @return the current value of the background property
|
||||
*/
|
||||
public BufferedImage getBackground() {
|
||||
return background;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the background property.
|
||||
*
|
||||
* @param aBackground the new value of the background property
|
||||
*/
|
||||
public void setBackground(BufferedImage aBackground) {
|
||||
background = aBackground;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the texture property.
|
||||
*
|
||||
* @return the current value of the texture property
|
||||
*/
|
||||
public BufferedImage getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the texture property.
|
||||
*
|
||||
* @param aTexture the new value of the texture property
|
||||
*/
|
||||
public void setTexture(BufferedImage aTexture) {
|
||||
texture = aTexture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setUnbreakableTexture
|
||||
*
|
||||
*
|
||||
* @param unbreakableTexture ub
|
||||
*
|
||||
*/
|
||||
public void setUnbreakableTexture(BufferedImage unbreakableTexture) {
|
||||
this.unbreakableTexture = unbreakableTexture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getUnbreakableTexture
|
||||
*
|
||||
*
|
||||
* @return BufferedImage
|
||||
*
|
||||
*/
|
||||
public BufferedImage getUnbreakableTexture() {
|
||||
return (this.unbreakableTexture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the map property.
|
||||
*
|
||||
* @return the current value of the map property
|
||||
*/
|
||||
public BufferedImage getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the map property.
|
||||
*
|
||||
* @param aMap the new value of the map property
|
||||
*/
|
||||
public void setMap(BufferedImage aMap) {
|
||||
map = aMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getGameMap</code> method here.
|
||||
*
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage getGameMap() {
|
||||
return (this.gameMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the size property.
|
||||
*
|
||||
* @return the current value of the size property
|
||||
*/
|
||||
public Dimension getSize() {
|
||||
return new Dimension(map.getWidth(), map.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the water animation.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getWaterAnimation() {
|
||||
return waterAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setWaterAnimation</code> method here.
|
||||
*
|
||||
* @param set a <code>TileSet</code> value
|
||||
*
|
||||
*/
|
||||
public void setWaterAnimation(TileSet set) {
|
||||
waterAnimation = new AnimatedSprite(set,
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.INFINITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////
|
||||
// Methods //
|
||||
/////////////
|
||||
|
||||
|
||||
/**
|
||||
* This will create a Game Map for use in drawing to screen.
|
||||
* Parses the Mask and Texture File to spit out a map.
|
||||
*
|
||||
* @return the new gameMap to draw to screen.
|
||||
*/
|
||||
public BufferedImage createGameMap() {
|
||||
|
||||
//ensure that the map and textures are loaded
|
||||
if (map == null || texture == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Set up variables
|
||||
int mapWidth = map.getWidth() ,
|
||||
mapHeight = map.getHeight() ,
|
||||
texWidth = texture.getWidth() ,
|
||||
texHeight = texture.getHeight();
|
||||
|
||||
int x, y, i, j, i2, j2; //x,y -> map, i,j -> texture
|
||||
|
||||
//initialize the game Map
|
||||
this.gameMap =
|
||||
ImageLoader.getInstance()
|
||||
.createBlankImage(map.getWidth(), map.getHeight());
|
||||
|
||||
this.indestructGameMap = ImageLoader.getInstance()
|
||||
.createBlankImage(map.getWidth(), map.getHeight());
|
||||
|
||||
this.unbreakableMap = ImageLoader.getInstance()
|
||||
.createBlankImage(map.getWidth(), map.getHeight());
|
||||
// Graphics2D g = gameMap.createGraphics();
|
||||
|
||||
//Go through the map and stick everything where its supposed to be
|
||||
i = 0;
|
||||
j = 0;
|
||||
i2 = 0;
|
||||
j2 = 0;
|
||||
for (x = 0; x < mapWidth; x++) {
|
||||
for (y = 0; y < mapHeight; y++) {
|
||||
|
||||
if (map.getRGB(x, y)
|
||||
== MapSettings.getInstance().getUnbreakableColor()) {
|
||||
gameMap.setRGB(x, y, unbreakableTexture.getRGB(i2, j2));
|
||||
indestructGameMap.setRGB(x, y, unbreakableTexture.getRGB(i2, j2));
|
||||
unbreakableMap.setRGB(x, y, MapSettings.getUnbreakableColor());
|
||||
} else if (map.getRGB(x, y) != -16777216) {
|
||||
gameMap.setRGB(x, y, texture.getRGB(i, j));
|
||||
}
|
||||
|
||||
if (++j >= texHeight) {
|
||||
j = 0;
|
||||
}
|
||||
if (++j2 >= unbreakableTexture.getHeight()) {
|
||||
j2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (++i >= texWidth) {
|
||||
i = 0;
|
||||
}
|
||||
if (++i2 >= unbreakableTexture.getWidth()) {
|
||||
i2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return gameMap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//@roseuid 40660B3403D2
|
||||
/**
|
||||
* When someone creates something on the map, the thing will be
|
||||
* added to the map. Use this method.
|
||||
*
|
||||
* @param shape The shape to add to the map.
|
||||
* @param color The color of the shape
|
||||
*
|
||||
*/
|
||||
public void addShape(Shape shape, Color color) {
|
||||
Graphics2D g = (Graphics2D) PhysicsEngine.getInstance()
|
||||
.getCurrentMap().getGraphics();
|
||||
Graphics2D g2 = (Graphics2D) this.gameMap.getGraphics();
|
||||
|
||||
g.setColor(color);
|
||||
g.fill(shape);
|
||||
|
||||
g2.setColor(color);
|
||||
g2.fill(shape);
|
||||
}
|
||||
|
||||
//@roseuid 40660B8C017F
|
||||
/**
|
||||
* When something explodes, digs, or mines, some part of the map can
|
||||
* be destroyed. This is where this function is called. The shape
|
||||
* passed in is what will be removed from the map. Note that only
|
||||
* "diggable" elements will be removed. The undiggable ones will
|
||||
* still persist.
|
||||
*
|
||||
* @param shape The shape to remove from the map.
|
||||
*
|
||||
*/
|
||||
public void subtractShape(Shape shape) {
|
||||
Graphics2D g = (Graphics2D) PhysicsEngine.getInstance()
|
||||
.getCurrentMap().getGraphics();
|
||||
Graphics2D g2 = (Graphics2D) this.gameMap.getGraphics();
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.fill(shape);
|
||||
|
||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
|
||||
g2.fill(shape);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the GUI and show it. For thread safety,
|
||||
* this method should be invoked from the
|
||||
* event-dispatching thread.
|
||||
*/
|
||||
private static void createAndShowGUI() {
|
||||
//Make sure we have nice window decorations.
|
||||
//javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
|
||||
|
||||
//Create and set up the window.
|
||||
final javax.swing.JFrame frame
|
||||
= new javax.swing
|
||||
.JFrame("Map Test",
|
||||
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration());
|
||||
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
//Display the window.
|
||||
frame.setSize(800, 600);
|
||||
frame.setVisible(true);
|
||||
|
||||
//Initialize double buffering:
|
||||
//frame.createBufferStrategy(2);
|
||||
|
||||
//Create and set up the content pane.
|
||||
final Level l = edu.gatech.cs2335.lemmings.file.LevelReader.getInstance()
|
||||
.loadLevel("test_level");
|
||||
|
||||
javax.swing.JPanel newContentPane
|
||||
= new javax.swing.JPanel(new java.awt.BorderLayout());
|
||||
//newContentPane.add(tst, java.awt.BorderLayout.CENTER);
|
||||
newContentPane.setOpaque(true); //content panes must be opaque
|
||||
frame.setContentPane(newContentPane);
|
||||
|
||||
//Initialize double buffering:
|
||||
frame.createBufferStrategy(2);
|
||||
final java.awt.image.BufferStrategy strategy = frame.getBufferStrategy();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
long lastFrame = System.currentTimeMillis();
|
||||
BufferedImage im = l.getMap().createGameMap();
|
||||
|
||||
System.out.println("\n\n\n\n\n\n\n");
|
||||
System.out.println("Image: \n" + im);
|
||||
System.out.println("\n\n\n\n\n\n\n");
|
||||
System.out.flush();
|
||||
|
||||
while (true) {
|
||||
int width = frame.getWidth();
|
||||
int height = frame.getHeight();
|
||||
|
||||
//Get the graphics context from buffer strategy:
|
||||
java.awt.Graphics2D g =
|
||||
(java.awt.Graphics2D) strategy.getDrawGraphics();
|
||||
|
||||
//Do the drawing:
|
||||
g.setColor(java.awt.Color.gray);
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
|
||||
g.drawImage(im, null, 0, 0);
|
||||
|
||||
//Flip buffer:
|
||||
strategy.show();
|
||||
|
||||
//Cap the frame rate:
|
||||
lastFrame += 20; //Frame rate
|
||||
try {
|
||||
Thread.sleep(Math.max(0,
|
||||
lastFrame - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main
|
||||
* @param args args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
//Schedule a job for the event-dispatching thread:
|
||||
//creating and showing this application's GUI.
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
createAndShowGUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* Map Settings, thanks to PMD, a Singleton class
|
||||
*
|
||||
* Holds Physics Constants
|
||||
*
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
*/
|
||||
public class MapSettings {
|
||||
|
||||
/**
|
||||
* The unbreakable color
|
||||
*/
|
||||
private static final int UNBREAKABLECOLOR = -8421505;
|
||||
|
||||
/**
|
||||
* The passable color
|
||||
*/
|
||||
private static final int PASSABLECOLOR = -16777216;
|
||||
|
||||
/**
|
||||
* TRANSPARENT Color
|
||||
*/
|
||||
public static final Color TRANSPARENT = new Color(255, 255, 255, 100);
|
||||
|
||||
/**
|
||||
* The Singleton Map Settings
|
||||
*/
|
||||
private static MapSettings instance = new MapSettings();
|
||||
|
||||
/**
|
||||
* Creates a new <code>MapSettings</code> instance.
|
||||
*
|
||||
*/
|
||||
private MapSettings() { }
|
||||
|
||||
|
||||
/**
|
||||
* Method getUnbreakableColor
|
||||
*
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public static int getUnbreakableColor() {
|
||||
return (MapSettings.UNBREAKABLECOLOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getPassableColor
|
||||
*
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public static int getPassableColor() {
|
||||
return (MapSettings.PASSABLECOLOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getInstance
|
||||
*
|
||||
*
|
||||
* @return mapsettings
|
||||
*
|
||||
*/
|
||||
public static MapSettings getInstance() {
|
||||
return (MapSettings.instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
//import java.util.Random;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class MultiLevelResultsState: this is the multilevel result state.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 16, 2004) - Created the MultiLevelResultsState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 16, 2004
|
||||
*/
|
||||
public final class MultiLevelResultsState extends LevelResultsState {
|
||||
|
||||
/**
|
||||
* Describe variable <code>numCarryOver</code> here.
|
||||
*
|
||||
*/
|
||||
private int numCarryOver;
|
||||
|
||||
/**
|
||||
* Describe variable <code>otherCarryOver</code> here.
|
||||
*
|
||||
*/
|
||||
private int otherCarryOver;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private LLabel lblCarryOver;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private int n;
|
||||
|
||||
/**
|
||||
* Describe variable <code>lblOtherPlayer</code> here.
|
||||
*
|
||||
*/
|
||||
private LLabel lblOtherPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private AbstractGameState target;
|
||||
|
||||
/**
|
||||
* Creates a new <code>MultiLevelResultsState</code> instance.
|
||||
*@param l l
|
||||
*@param num num
|
||||
*@param otherNum on
|
||||
*/
|
||||
public MultiLevelResultsState(Level l, int num, int otherNum) {
|
||||
super(l);
|
||||
setNumCarryOver(num);
|
||||
setOtherCarryOver(otherNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
super.initialize();
|
||||
|
||||
lblCarryOver = new LLabel();
|
||||
lblCarryOver
|
||||
.setText("Your Carry Over Lemmings: " + numCarryOver);
|
||||
lblCarryOver.setPosition(new Point(300, 280));
|
||||
lblCarryOver.setShown(true);
|
||||
|
||||
lblOtherPlayer = new LLabel();
|
||||
lblOtherPlayer
|
||||
.setText("Your Opponent's Carry Over Lemmings: " + otherCarryOver);
|
||||
lblOtherPlayer.setPosition(new Point(300, 300));
|
||||
lblOtherPlayer.setShown(true);
|
||||
|
||||
LRootPane u = getUI();
|
||||
|
||||
u.addChild(lblCarryOver);
|
||||
u.addChild(lblOtherPlayer);
|
||||
|
||||
if (numCarryOver < 1) {
|
||||
LFancyLabel resultLabel = new LFancyLabel();
|
||||
resultLabel.setForeground(Color.red);
|
||||
resultLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD,
|
||||
20.0f));
|
||||
resultLabel.setText("You Lose!");
|
||||
resultLabel.setPosition(new Point(300, 400));
|
||||
resultLabel.setShown(true);
|
||||
|
||||
u.addChild(resultLabel);
|
||||
|
||||
target = new MainMenuState();
|
||||
} else if (otherCarryOver < 1) {
|
||||
LFancyLabel resultLabel = new LFancyLabel();
|
||||
resultLabel.setForeground(Color.red);
|
||||
resultLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD,
|
||||
20.0f));
|
||||
resultLabel.setText("You Win!");
|
||||
resultLabel.setPosition(new Point(300, 400));
|
||||
resultLabel.setShown(true);
|
||||
|
||||
target = new MainMenuState();
|
||||
|
||||
u.addChild(resultLabel);
|
||||
}
|
||||
|
||||
//The player saved enough lemmings.
|
||||
String name = getLevel().getData().getId();
|
||||
String[] levels = LevelReader.getInstance().getLevelList();
|
||||
boolean found = false;
|
||||
n = 0;
|
||||
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
if (name.equals(levels[i])) {
|
||||
if (i == levels.length - 1) {
|
||||
LFancyLabel resultLabel = new LFancyLabel();
|
||||
resultLabel.setForeground(Color.red);
|
||||
resultLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD,
|
||||
20.0f));
|
||||
resultLabel.setPosition(new Point(300, 400));
|
||||
resultLabel.setShown(true);
|
||||
|
||||
if (numCarryOver > otherCarryOver) {
|
||||
resultLabel.setText("You Win!");
|
||||
} else if (numCarryOver < otherCarryOver) {
|
||||
resultLabel.setText("You Lose!");
|
||||
} else {
|
||||
resultLabel.setText("It's a Tie...");
|
||||
}
|
||||
|
||||
target = new MainMenuState();
|
||||
|
||||
u.addChild(resultLabel);
|
||||
} else {
|
||||
n = i + 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of otherCarryOver.
|
||||
* @return value of otherCarryOver.
|
||||
*/
|
||||
public int getOtherCarryOver() {
|
||||
return otherCarryOver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of otherCarryOver.
|
||||
* @param v Value to assign to otherCarryOver.
|
||||
*/
|
||||
public void setOtherCarryOver(int v) {
|
||||
this.otherCarryOver = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of numCarryOver.
|
||||
* @return value of numCarryOver.
|
||||
*/
|
||||
public int getNumCarryOver() {
|
||||
return numCarryOver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of numCarryOver.
|
||||
* @param v Value to assign to numCarryOver.
|
||||
*/
|
||||
public void setNumCarryOver(int v) {
|
||||
this.numCarryOver = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String a = ae.getActionCommand();
|
||||
|
||||
if (a.equals("back")) {
|
||||
//Go back to the main menu:
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
} else if (a.equals("play")) {
|
||||
if (target != null) {
|
||||
GameEngine.getInstance().setCurrentState(target);
|
||||
} else {
|
||||
//Go to the next level:
|
||||
GameEngine.getInstance().startMultiLevel(n, numCarryOver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.networking.PauseMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.UpdateMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.ChangeSpeedMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.NukeRequestMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.ChangeLemmingFlowMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.IdentificationMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
import edu.gatech.cs2335.lemmings.networking.MessageFactory;
|
||||
import edu.gatech.cs2335.lemmings.networking.AbstractMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.StatsMessage;
|
||||
import edu.gatech.cs2335.lemmings.networking.LevelFinishMessage;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.event.ActionEvent;
|
||||
//import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
//import java.awt.event.ActionEvent;
|
||||
//import java.awt.event.ActionListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.gui.ITypable;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.JobContainer;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LToggleButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
//import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
import edu.gatech.cs2335.lemmings.networking.MessageSettings;
|
||||
//import edu.gatech.cs2335.lemmings.networking.MessageFactory;
|
||||
//import edu.gatech.cs2335.lemmings.networking.AbstractMessage;
|
||||
|
||||
|
||||
//import java.util.Vector;
|
||||
//import java.util.List;
|
||||
|
||||
/**
|
||||
* The mutiplayer game state, where the actual game is displayed and played.
|
||||
*
|
||||
* Koala Update - fixed
|
||||
*
|
||||
* @author <A href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class MultiplayerGameplayState extends GamePlayState {
|
||||
|
||||
/**
|
||||
* bDebug is for turning debugging output on and off
|
||||
*/
|
||||
//private final boolean bDebug = false;
|
||||
|
||||
/**
|
||||
* Boolean for VERBOSE output
|
||||
*/
|
||||
private static final boolean VERBOSE = true;
|
||||
|
||||
/**
|
||||
* True if other player has requested a NUKE
|
||||
*/
|
||||
private boolean otherPlayerRequestedNuke = false;
|
||||
|
||||
/**
|
||||
* True if this player has requested a NUKE
|
||||
*/
|
||||
private boolean playerRequestedNuke = false;
|
||||
|
||||
/**
|
||||
* Holds the Level information for the other player
|
||||
*/
|
||||
private Level otherPlayerLevel;
|
||||
|
||||
/**
|
||||
* The label showing the number of lemmings released.
|
||||
*/
|
||||
private LFancyLabel releasedLabel;
|
||||
|
||||
/**
|
||||
* The label that will show how many lemmings have been saved.
|
||||
*/
|
||||
private LFancyLabel savedLabel;
|
||||
|
||||
/**
|
||||
* This label will show the number of lemmings out in the field.
|
||||
*/
|
||||
private LFancyLabel outLabel;
|
||||
|
||||
/**
|
||||
*dead
|
||||
*/
|
||||
|
||||
private int deadLemmings;
|
||||
/**
|
||||
*saved
|
||||
*/
|
||||
private int savedLemmings;
|
||||
/**
|
||||
*released
|
||||
*/
|
||||
private int releasedLemmings;
|
||||
/**
|
||||
*total
|
||||
*/
|
||||
private int totalLemmings;
|
||||
|
||||
/**
|
||||
* Has one player done the thing?
|
||||
*/
|
||||
private boolean flag;
|
||||
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*@param l level
|
||||
*
|
||||
*/
|
||||
public MultiplayerGameplayState (Level l) {
|
||||
super(l);
|
||||
this.otherPlayerLevel = l.duplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>specialInitialize</code> method here.
|
||||
*
|
||||
*/
|
||||
protected synchronized void specialInitialize() {
|
||||
releasedLabel = new LFancyLabel();
|
||||
releasedLabel.setForeground(Color.green);
|
||||
releasedLabel
|
||||
.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
releasedLabel.setText("");
|
||||
releasedLabel.setPosition(new Point(600, 50));
|
||||
releasedLabel.setShown(true);
|
||||
|
||||
savedLabel = new LFancyLabel();
|
||||
savedLabel.setForeground(Color.green);
|
||||
savedLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
savedLabel.setText("");
|
||||
savedLabel.setPosition(new Point(600, 70));
|
||||
savedLabel.setShown(true);
|
||||
|
||||
outLabel = new LFancyLabel();
|
||||
outLabel.setForeground(Color.green);
|
||||
outLabel.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 20.0f));
|
||||
outLabel.setText("");
|
||||
outLabel.setPosition(new Point(600, 90));
|
||||
outLabel.setShown(true);
|
||||
|
||||
LRootPane u = getUI();
|
||||
|
||||
u.addChild(releasedLabel);
|
||||
u.addChild(savedLabel);
|
||||
u.addChild(outLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for pause.
|
||||
*/
|
||||
protected void specialPauseHandle() {
|
||||
List data = new Vector();
|
||||
|
||||
|
||||
data.add("MrPause");
|
||||
data.add(Boolean.valueOf(isPauseSelected()));
|
||||
|
||||
AbstractMessage am = MessageFactory.getInstance().
|
||||
createMessage(MessageSettings.TYPE_PAUSE, data);
|
||||
|
||||
LemmingNetworking.getInstance().sendMessage(am);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for speedup.
|
||||
*/
|
||||
protected void specialSpeedupHandle() {
|
||||
List data = new Vector();
|
||||
|
||||
data.add("MrSpeed");
|
||||
data.add(new Integer(getGameSpeed()));
|
||||
|
||||
AbstractMessage am = MessageFactory.getInstance().
|
||||
createMessage(MessageSettings.TYPE_SPEED, data);
|
||||
|
||||
LemmingNetworking.getInstance().sendMessage(am);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for nuke.
|
||||
*/
|
||||
protected void specialNukeHandle() {
|
||||
requestNuke();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for increase.
|
||||
*/
|
||||
protected void specialIncreaseHandle() {
|
||||
List data = new Vector();
|
||||
data.add("MrRate");
|
||||
|
||||
data.add(new Integer(getLemmingFlow()));
|
||||
|
||||
AbstractMessage am = MessageFactory.getInstance().
|
||||
createMessage(MessageSettings.TYPE_FLOW, data);
|
||||
|
||||
LemmingNetworking.getInstance().sendMessage(am);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whatever else needs to be done for decrease.
|
||||
*/
|
||||
protected void specialDecreaseHandle() {
|
||||
List data = new Vector();
|
||||
data.add("MrRate");
|
||||
|
||||
data.add(new Integer(getLemmingFlow()));
|
||||
|
||||
AbstractMessage am = MessageFactory.getInstance().
|
||||
createMessage(MessageSettings.TYPE_FLOW, data);
|
||||
|
||||
LemmingNetworking.getInstance().sendMessage(am);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>specialUpdate</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void specialUpdate() {
|
||||
releasedLabel.setText("Released: "
|
||||
+ Integer.toString(releasedLemmings)
|
||||
+ "/" + Integer.toString(totalLemmings));
|
||||
savedLabel.setText("Saved: "
|
||||
+ Integer.toString(savedLemmings));
|
||||
outLabel.setText("Out: "
|
||||
+ Integer.toString(deadLemmings));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates both players levels based on msg data
|
||||
* @param msg , network message holding game state updates
|
||||
*/
|
||||
public void receiveMessage(AbstractMessage msg) {
|
||||
if (msg instanceof StatsMessage) {
|
||||
deadLemmings = ((StatsMessage) msg).getLemmingsDead();
|
||||
savedLemmings = ((StatsMessage) msg).getLemmingsSaved();
|
||||
releasedLemmings = ((StatsMessage) msg).getLemmingsReleased();
|
||||
totalLemmings = ((StatsMessage) msg).getLemmingsTotal();
|
||||
|
||||
} else if (msg instanceof NukeRequestMessage) {
|
||||
//Seeing if we have to nuke and nuking if so
|
||||
otherPlayerRequestedNuke = true;
|
||||
if (playerRequestedNuke) {
|
||||
//Send Nuke Message
|
||||
List data = new Vector();
|
||||
data.add(new String("NukeMessage"));
|
||||
|
||||
//Nuke them all
|
||||
getLevel().nukeEmALL();
|
||||
}
|
||||
|
||||
} else if (msg instanceof LevelFinishMessage) {
|
||||
otherPlayerEnded();
|
||||
|
||||
} else if (msg instanceof UpdateMessage) {
|
||||
getOtherPlayerLevel().updateLevel(msg);
|
||||
|
||||
} else if (msg instanceof PauseMessage) {
|
||||
getPauseButton().setSelected(((PauseMessage) msg).getPause());
|
||||
singlePauseButtonHandle();
|
||||
|
||||
if (((PauseMessage) msg).getPause()) {
|
||||
getOtherPlayerLevel().pause();
|
||||
|
||||
} else {
|
||||
getOtherPlayerLevel().unpause();
|
||||
|
||||
}
|
||||
|
||||
} else if (msg instanceof ChangeLemmingFlowMessage) {
|
||||
this.getOtherPlayerLevel().setLemmingFlow(
|
||||
((ChangeLemmingFlowMessage) msg).getLemmingFlow());
|
||||
|
||||
} else if (msg instanceof ChangeSpeedMessage) {
|
||||
//Do we really want the other player controlling speed?
|
||||
// this.setGameSpeed(((ChangeSpeedMessage) msg).getSpeed());
|
||||
int stuff = 0;
|
||||
stuff++;
|
||||
|
||||
} else if (msg instanceof IdentificationMessage) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("IdentificationMessage received during play");
|
||||
}
|
||||
} else {
|
||||
//This would be bad
|
||||
System.err.println("MultiplayerGameplayState:receiveMessage: "
|
||||
+ "Msg was not correct type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the level and goes on to the next state.
|
||||
*/
|
||||
public synchronized void endLevel() {
|
||||
//Go to the level results state:
|
||||
getLevel().pause();
|
||||
|
||||
//Send out the endmessage
|
||||
AbstractMessage am = MessageFactory.getInstance()
|
||||
.makeBlankMessage(MessageSettings.TYPE_LEVELEND, "nUb");
|
||||
LemmingNetworking.getInstance().sendMessage(am);
|
||||
|
||||
if (flag) {
|
||||
int lemmingsSaved = getLevel().getLemmingsSaved();
|
||||
GameEngine.getInstance()
|
||||
.setCurrentState(new
|
||||
MultiLevelResultsState(getLevel(),
|
||||
lemmingsSaved, //My lemmings
|
||||
savedLemmings)); //Opponent's
|
||||
//lemmings
|
||||
} else {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Konchil on.
|
||||
*/
|
||||
public synchronized void otherPlayerEnded() {
|
||||
if (flag) {
|
||||
int lemmingsSaved = getLevel().getLemmingsSaved();
|
||||
GameEngine.getInstance()
|
||||
.setCurrentState(new
|
||||
MultiLevelResultsState(getLevel(),
|
||||
lemmingsSaved, //My lemmings
|
||||
savedLemmings)); //Opponent's
|
||||
//lemmings
|
||||
} else {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for otherPlayerlevel
|
||||
* @return Level , Level of remote player
|
||||
*/
|
||||
public Level getOtherPlayerLevel() {
|
||||
return otherPlayerLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the little guys should be nuked and nukes.
|
||||
*/
|
||||
public void requestNuke() {
|
||||
playerRequestedNuke = true;
|
||||
List data = new Vector();
|
||||
data.add(new String("NukeMessage"));
|
||||
AbstractMessage nukem =
|
||||
MessageFactory.getInstance().createMessage("NUKE", data);
|
||||
LemmingNetworking.getInstance().sendMessage(nukem);
|
||||
|
||||
if (otherPlayerRequestedNuke) {
|
||||
//Nuke them all
|
||||
getLevel().nukeEmALL();
|
||||
getOtherPlayerLevel().nukeEmALL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
import edu.gatech.cs2335.lemmings.gui.LLabel;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LTextField;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.networking.LemmingNetworking;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
/**
|
||||
* Class MultiplayerSetupState: This is where the player can either
|
||||
* start up the server, or join an existing game.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the MultiplayerSetupState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public class MultiplayerSetupState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* The text field that will contain the IP of the host to connect to.
|
||||
*/
|
||||
private LTextField ipField;
|
||||
|
||||
/**
|
||||
* Port.
|
||||
*/
|
||||
private LTextField portField;
|
||||
|
||||
/**
|
||||
* Creates a new <code>MultiplayerSetupState</code> instance.
|
||||
*/
|
||||
public MultiplayerSetupState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean initialize() {
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance().getTileSet("bg_mp"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize labels:
|
||||
LLabel lblHost = new LLabel();
|
||||
lblHost.setText("Host: ");
|
||||
lblHost.setShown(true);
|
||||
lblHost.setPosition(new Point(300, 150));
|
||||
|
||||
LLabel lblPort = new LLabel();
|
||||
lblPort.setText("Port: ");
|
||||
lblPort.setShown(true);
|
||||
lblPort.setPosition(new Point(300, 200));
|
||||
|
||||
ipField = new LTextField("localhost");
|
||||
ipField.setShown(true);
|
||||
ipField.setPosition(new Point(350, 150));
|
||||
ipField.end();
|
||||
|
||||
portField = new LTextField("3333");
|
||||
portField.setShown(true);
|
||||
portField.setPosition(new Point(350, 200));
|
||||
portField.end();
|
||||
|
||||
//Initialize Buttons:
|
||||
LButton back = new LButton();
|
||||
back
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mpb_back"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
back.setPosition(new Point(10, 590));
|
||||
back.setShown(true);
|
||||
back.setActionCommand("back");
|
||||
back.addActionListener(this);
|
||||
|
||||
LButton host = new LButton();
|
||||
host
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mpb_host"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
host.setPosition(new Point(345, 590));
|
||||
host.setShown(true);
|
||||
host.setActionCommand("host");
|
||||
host.addActionListener(this);
|
||||
|
||||
LButton connect = new LButton();
|
||||
connect
|
||||
.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mpb_connect"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
connect.setPosition(new Point(680, 590));
|
||||
connect.setShown(true);
|
||||
connect.setActionCommand("connect");
|
||||
connect.addActionListener(this);
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(lblHost);
|
||||
np.addChild(lblPort);
|
||||
np.addChild(back);
|
||||
np.addChild(host);
|
||||
np.addChild(connect);
|
||||
np.addChild(portField);
|
||||
np.addChild(ipField);
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getHost</code> method here.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
private String getHost() {
|
||||
return ipField.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getPort</code> method here.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
private int getPort() {
|
||||
try {
|
||||
return Integer.parseInt(portField.getText());
|
||||
} catch (NumberFormatException nfe) {
|
||||
return 3333;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
String a = ae.getActionCommand();
|
||||
|
||||
if ("back".equals(a)) {
|
||||
GameEngine.getInstance().setCurrentState(new MainMenuState());
|
||||
} else if ("host".equals(a)) {
|
||||
//Host an mp game:
|
||||
int port = getPort();
|
||||
|
||||
GameEngine.getInstance().startMultiGame();
|
||||
|
||||
GameEngine.getInstance().getEcs().host(port);
|
||||
} else if ("connect".equals(a)) {
|
||||
//Connect to an existing game:
|
||||
String host = getHost();
|
||||
int port = getPort();
|
||||
|
||||
GameEngine.getInstance().startMultiGame();
|
||||
|
||||
GameEngine.getInstance().getEcs().connectTo(host, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Font;
|
||||
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.Graphics;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.gui.ITypable;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LLeafComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LComponent;
|
||||
//import edu.gatech.cs2335.lemmings.gui.JobContainer;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LToggleButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
//import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
//import java.awt.Point;
|
||||
|
||||
//import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class NetworkErrorState: Displays a network error...
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 21, 2004) - Created the NetworkErrorState class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 21, 2004
|
||||
*/
|
||||
public class NetworkErrorState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Display debug information?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The label to display our message to the user in.
|
||||
*/
|
||||
private LFancyLabel message;
|
||||
|
||||
/**
|
||||
* Creates a new <code>NetworkErrorState</code> instance.
|
||||
*/
|
||||
public NetworkErrorState() {
|
||||
//Initialize background:
|
||||
LIcon bg = new LIcon(TileSetManager.getInstance()
|
||||
.getTileSet("bg_ne"));
|
||||
bg.setShown(true);
|
||||
bg.setPosition(new Point(0, 0));
|
||||
|
||||
//Initialize label:
|
||||
message = new LFancyLabel();
|
||||
message.setForeground(Color.black);
|
||||
message.setFont(LFancyLabel.DEFAULT_FONT.deriveFont(Font.BOLD, 18.0f));
|
||||
message.setText("");
|
||||
message.setShown(true);
|
||||
message.setPosition(new Point(300, 300));
|
||||
|
||||
//Initialize button:
|
||||
LButton goOn = new LButton();
|
||||
goOn.setPosition(new Point(10, 590));
|
||||
goOn.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("mpb_back"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
goOn.addActionListener(this);
|
||||
goOn.setActionCommand("goOn");
|
||||
goOn.setShown(true);
|
||||
|
||||
//Initialize UI:
|
||||
LRootPane np = new LRootPane();
|
||||
np.addChild(bg);
|
||||
np.addChild(message);
|
||||
np.addChild(goOn);
|
||||
|
||||
setUI(np);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean initialize() {
|
||||
if (VERBOSE) {
|
||||
System.err.println("NetworkErrorState: I am initialized!");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
setErrorMessage("");
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("NetworkErrorState: I am cleaned up!");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the error message.
|
||||
*
|
||||
* @param msg a <code>String</code> value
|
||||
*/
|
||||
public void setErrorMessage(String msg) {
|
||||
message.setText(new String(msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (VERBOSE) {
|
||||
System.err.println("NetworkErrorState: Got some action - "
|
||||
+ ae.getActionCommand());
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
//Go back to the Multiplayer setup state:
|
||||
GameEngine.getInstance().setCurrentState(new MultiplayerSetupState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Jose:
|
||||
* The particle class, used for ! particle effects !
|
||||
*
|
||||
* Nothing special to do here, the Physics Engine will handle the
|
||||
* actual effects. The single function is used to test whether or
|
||||
* not the particle should be killed.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v2.0 (2004 - 4 - 20) - Made abstract
|
||||
* v1.0 (Apr. 11, 2004) - Created the Particle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public abstract class Particle extends PrettySprite {
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*@param s s
|
||||
*/
|
||||
public Particle(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected abstract boolean canKillSelf();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSet;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsObject;
|
||||
|
||||
/**
|
||||
* Class Portal: Represents a portal in the map. It can be either an
|
||||
* entrance, an exit, or a portal from one part of the map to another.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 28, 2004) - Created the Portal class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 28, 2004
|
||||
*/
|
||||
public abstract class Portal implements ICleanable {
|
||||
|
||||
/**
|
||||
* The physics object associated with the portal.
|
||||
*/
|
||||
private PhysicsObject physics;
|
||||
|
||||
/**
|
||||
* The animation associated with the portal.
|
||||
*/
|
||||
private AnimatedSprite animation;
|
||||
|
||||
/**
|
||||
* The level that the portal is associated with.
|
||||
*/
|
||||
private Level parent;
|
||||
|
||||
/**
|
||||
* The extent of the portal. If the lemming is within the
|
||||
* rectangle, then it will be processed.
|
||||
*/
|
||||
private Rectangle extent;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Portal</code> instance.
|
||||
*
|
||||
* @param anim The name of the animation tileset to use.
|
||||
*/
|
||||
public Portal(String anim) {
|
||||
//Set up physics:
|
||||
physics = new PhysicsObject();
|
||||
animation = new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet(anim),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.INFINITE);
|
||||
setAnimation(anim); //Hack... Setting animation twice?? :/
|
||||
|
||||
parent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up all references for the garbage collector.
|
||||
*/
|
||||
public void cleanUp() {
|
||||
parent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the animation for this portal.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the animation with the specified name.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
*/
|
||||
protected final synchronized void setAnimation(String name) {
|
||||
TileSet set = TileSetManager.getInstance().getTileSet(name);
|
||||
Rectangle rect = set.getExtent(0);
|
||||
|
||||
setExtent(new Rectangle(rect));
|
||||
|
||||
animation.setAnimation(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the physics object associated with this portal.
|
||||
*
|
||||
* @return a <code>PhysicsObject</code> value
|
||||
*/
|
||||
public PhysicsObject getPhysics() {
|
||||
return physics;
|
||||
}
|
||||
/**
|
||||
* Returns the physics object associated with this portal.
|
||||
*
|
||||
* @return a <code>PhysicsObject</code> value
|
||||
*/
|
||||
public Rectangle getExtent() {
|
||||
return extent;
|
||||
}
|
||||
/**
|
||||
* Returns the physics object associated with this portal.
|
||||
*
|
||||
* @param ext a <code>PhysicsObject</code> value
|
||||
*/
|
||||
public final synchronized void setExtent(Rectangle ext) {
|
||||
extent = ext;
|
||||
}
|
||||
/**
|
||||
* Returns the physics object associated with this portal.
|
||||
*
|
||||
* @return a <code>PhysicsObject</code> value
|
||||
*/
|
||||
public Level getParent() {
|
||||
return parent;
|
||||
}
|
||||
/**
|
||||
* Returns the physics object associated with this portal.
|
||||
*
|
||||
* @param l a <code>PhysicsObject</code> value
|
||||
*/
|
||||
public void setParent(Level l) {
|
||||
parent = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called when a lemming enters this portal.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
*/
|
||||
public abstract void processLemmingEntry(Lemming l);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Class PortalFactory: Creates different portals.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 22, 2004) - Created the PortalFactory class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 22, 2004
|
||||
*/
|
||||
public class PortalFactory {
|
||||
|
||||
/**
|
||||
* All the different kinds of portals.
|
||||
*/
|
||||
public static final String[] PORTAL_TYPES = {
|
||||
"entrance",
|
||||
"exit",
|
||||
"fling_trap"
|
||||
};
|
||||
|
||||
/**
|
||||
* Describe constant <code>INSTANCE</code> here.
|
||||
*
|
||||
*/
|
||||
private static final PortalFactory INSTANCE = new PortalFactory();
|
||||
|
||||
/**
|
||||
* Creates a new <code>PortalFactory</code> INSTANCE.
|
||||
*/
|
||||
private PortalFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getInstance</code> method here.
|
||||
*
|
||||
* @return a <code>PortalFactory</code> value
|
||||
*/
|
||||
public static PortalFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>makePortal</code> method here.
|
||||
*@param type type
|
||||
*@param value value
|
||||
* @return a <code>Portal</code> value
|
||||
*/
|
||||
public Portal makePortal(String type, String value) {
|
||||
//Try to parse the coordinates out of the value first:
|
||||
StringTokenizer st = new StringTokenizer(value);
|
||||
|
||||
int x;
|
||||
int y;
|
||||
|
||||
if (!st.hasMoreTokens()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
x = Integer.parseInt(st.nextToken());
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!st.hasMoreTokens()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
y = Integer.parseInt(st.nextToken());
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Got coordinates of the portal:
|
||||
Portal result = null;
|
||||
if (PORTAL_TYPES[0].equals(type)) {
|
||||
result = new LevelEntrance();
|
||||
|
||||
} else if (PORTAL_TYPES[1].equals(type)) {
|
||||
result = new LevelExit();
|
||||
|
||||
} else if (PORTAL_TYPES[2].equals(type)) {
|
||||
result = new FlingTrap();
|
||||
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
result.getPhysics().getPosition().setX(x);
|
||||
result.getPhysics().getPosition().setY(y);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsObject;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
|
||||
/**
|
||||
* Class PrettySprite: This is basically an eye-candy sprite. These
|
||||
* will be things that happen to lemmings, for instance, or maybe some
|
||||
* other effects, like a random bird flying by.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the PrettySprite class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public abstract class PrettySprite extends PhysicsObject
|
||||
implements ICleanable {
|
||||
|
||||
/**
|
||||
* The animation associated with this sprite.
|
||||
*/
|
||||
private AnimatedSprite animation;
|
||||
|
||||
/**
|
||||
* The level that the sprite is associated with.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Creates a new <code>PrettySprite</code> instance.
|
||||
*@param animType anime
|
||||
*/
|
||||
public PrettySprite(String animType) {
|
||||
level = null;
|
||||
|
||||
animation = new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet(animType),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.INFINITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the animation property.
|
||||
*
|
||||
* @return the current value of the animation property
|
||||
*/
|
||||
public AnimatedSprite getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setAnimation</code> method here.
|
||||
*
|
||||
* @param type a <code>String</code> value
|
||||
*/
|
||||
public final void setAnimation(String type) {
|
||||
animation.setAnimation(TileSetManager.getInstance().getTileSet(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called at every frame to update the sprite.
|
||||
*/
|
||||
public final void updateSprite() {
|
||||
//Process my own special:
|
||||
//specialUpdate();
|
||||
|
||||
//Update position:
|
||||
try {
|
||||
PhysicsEngine.getInstance().calculateNextPoint(this);
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Update animation:
|
||||
animation.nextFrameNumber();
|
||||
|
||||
//Check if we are ready to die:
|
||||
if (canKillSelf()) {
|
||||
//Commit suicide:
|
||||
level.killPrettySprite(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getLevel</code> method here.
|
||||
*
|
||||
* @return a <code>Level</code> value
|
||||
*/
|
||||
public final Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setLevel</code> method here.
|
||||
*
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public final void setLevel(Level l) {
|
||||
level = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up all references for the garbage collector.
|
||||
*/
|
||||
public void cleanUp() {
|
||||
level = null;
|
||||
animation = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected abstract boolean canKillSelf();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* This class will essentially run the Lemmings game. It is the driver.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ProgramRunner {
|
||||
|
||||
//@roseuid 406519600375
|
||||
/**
|
||||
* Creates a new instance of the runner.
|
||||
*
|
||||
*/
|
||||
private ProgramRunner() { }
|
||||
|
||||
//@roseuid 406515D202EA
|
||||
/**
|
||||
* Runs the game.
|
||||
*
|
||||
*/
|
||||
public void execute() {
|
||||
if (GameEngine.VERBOSE) {
|
||||
System.out.println("The program is running...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Create Splash Screen State:
|
||||
AbstractGameState gs = new SplashScreenState();
|
||||
//gs.initialize();
|
||||
|
||||
//Start up the game:
|
||||
GameEngine.getInstance().setCurrentState(gs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method.
|
||||
*
|
||||
* @param args a <code>String[]</code> value
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
new ProgramRunner().execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
/**
|
||||
* Class SavedLemming: This thing will basically show the animation of
|
||||
* the lemming going upstairs into the exit.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the SavedLemming class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class SavedLemming extends PrettySprite {
|
||||
|
||||
/**
|
||||
* Creates a new <code>SavedLemming</code> instance.
|
||||
*/
|
||||
public SavedLemming() {
|
||||
super("saved_lemming");
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (getAnimation().getCurrentFrame() == 0) {
|
||||
//The animation is through. We are done:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* This state basically represents the splash screen. It's just a
|
||||
* fancy graphics, which when the player clicks, disappears.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public class SplashScreenState extends AbstractGameState {
|
||||
|
||||
/**
|
||||
* Creates a new <code>SplashScreenState</code> instance.
|
||||
*
|
||||
*/
|
||||
public SplashScreenState() {
|
||||
//Make sure that the resources we want are loaded:
|
||||
TileSetManager.getInstance().getTileSet("splash");
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C032F
|
||||
/**
|
||||
* This method will initialize the state that it belongs to. It will
|
||||
* then return true upon success, and false upon failure.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean initialize() {
|
||||
LRootPane np = new LRootPane();
|
||||
|
||||
LButton button = new LButton();
|
||||
button.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("splash"),
|
||||
Direction.NO_DIRECTION, Looping.NONE));
|
||||
button.addActionListener(this);
|
||||
button.setShown(true);
|
||||
button.setPosition(new Point(0, 0));
|
||||
|
||||
np.addChild(button);
|
||||
|
||||
setUI(np);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C034D
|
||||
/**
|
||||
* This method will perform all of the necessary clean up operations
|
||||
* once the object is no longer needed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//@roseuid 4065D29C037F
|
||||
/**
|
||||
* This function essentially processes the action event that may
|
||||
* have been thrown by the UI.
|
||||
*
|
||||
* @param ae ae
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
//The splash screen has been clicked.
|
||||
if (GameEngine.VERBOSE) {
|
||||
System.out.println("SplashScreenState: Transferrring to Main Menu...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Transfer to Main Menu.
|
||||
MainMenuState mms = new MainMenuState();
|
||||
// mms.initialize();
|
||||
GameEngine.getInstance().setCurrentState(mms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package edu.gatech.cs2335.lemmings.engine;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class Particle: When a lemming blows up, he makes particles. Well,
|
||||
* here they are. :)
|
||||
*
|
||||
* Description from Jose:
|
||||
* Adds specific blood stuff
|
||||
*
|
||||
* Blood shouldn't bounce, rather it should hit the wall and die
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the BloodParticle class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public class WaterParticle extends Particle {
|
||||
|
||||
/**
|
||||
* Used to randomize velocity.
|
||||
*/
|
||||
private static final Random GENERATOR = new Random(new java.util.Date()
|
||||
.getTime());
|
||||
|
||||
/**
|
||||
* Particles to create when death should occur
|
||||
*/
|
||||
public static final int PARTICLESWHENDIE = 50;
|
||||
|
||||
/**
|
||||
* time to Live
|
||||
*/
|
||||
private int killMe;
|
||||
|
||||
/**
|
||||
* curve
|
||||
*/
|
||||
private int curve;
|
||||
|
||||
/**
|
||||
* Stores canDie
|
||||
*/
|
||||
private boolean canDie;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>Particle</code> instance.
|
||||
*/
|
||||
public WaterParticle() {
|
||||
super("water");
|
||||
|
||||
getVelocity().setPolar(GENERATOR.nextInt(8), GENERATOR.nextInt(30));
|
||||
canDie = false;
|
||||
killMe = 0;
|
||||
curve = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @return <code>boolean</code> value
|
||||
*/
|
||||
public boolean getCanDie() {
|
||||
return canDie;
|
||||
|
||||
}
|
||||
/**
|
||||
* Should return canDie
|
||||
*
|
||||
* @param a for candie <code>boolean</code> value
|
||||
*/
|
||||
public void setCanDie(boolean a) {
|
||||
|
||||
canDie = a;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should return true when the sprite is ready to kill self.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean canKillSelf() {
|
||||
if (killMe > 25) {
|
||||
return true;
|
||||
}
|
||||
if (curve > 1) {
|
||||
return true;
|
||||
} else if (this.getVelocity().getJ() == 0) {
|
||||
curve++;
|
||||
}
|
||||
killMe++;
|
||||
return canDie;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.DirtParticle;
|
||||
import edu.gatech.cs2335.lemmings.engine.PrettySprite;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.5 - Jose Caban - added process() handling
|
||||
* TOnotDO: correct problem with non-breakable areas
|
||||
* getting nicked slightly
|
||||
*
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.5
|
||||
*/
|
||||
public class BasherJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* The Rectangle used to break the gameMap
|
||||
*/
|
||||
private Rectangle rectangle;
|
||||
|
||||
/**
|
||||
* Creates a new <code>BasherJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public BasherJob() {
|
||||
super(LemmingJobSettings.JOB_ID_BASHER);
|
||||
rectangle = new Rectangle(5, 40);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*
|
||||
*/
|
||||
public void process() {
|
||||
BufferedImage currentMap = PhysicsEngine.getInstance().getCurrentMap();
|
||||
Map map = ((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().getMap();
|
||||
|
||||
Lemming lem = this.getOwner();
|
||||
|
||||
PhysicsVector currentVelocity = lem.getVelocity();
|
||||
Point currentPoint = lem.getPosition();
|
||||
|
||||
//going to check whether or not this lemming can still be a basher
|
||||
int rayI = currentPoint.getX();
|
||||
// int max = LemmingJobSettings.BASHDISTANCE + rayI;
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("Calculating Basher Stuff...");
|
||||
System.out.println("rayI1..." + rayI);
|
||||
System.out.println("currentVelocity..." + currentVelocity.getI());
|
||||
}
|
||||
|
||||
if (currentVelocity.getI() > 0) {
|
||||
currentVelocity.setI(1);
|
||||
for (int i = 0; i < LemmingJobSettings.BASHDISTANCE; rayI++, i++) {
|
||||
|
||||
if (currentMap.getRGB(rayI, currentPoint.getY())
|
||||
== MapSettings.getInstance().getUnbreakableColor()) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
currentVelocity.setI(PhysicsSettings.getInitialX());
|
||||
return;
|
||||
} else if (currentMap.getRGB(rayI, currentPoint.getY())
|
||||
!= MapSettings.getInstance().getPassableColor()) {
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("rayI..." + rayI);
|
||||
}
|
||||
|
||||
rectangle.x = currentPoint.getX();
|
||||
rectangle.y = currentPoint.getY() - 39;
|
||||
map.subtractShape(rectangle);
|
||||
|
||||
//Make the debris
|
||||
PrettySprite ps;
|
||||
for (int j = 0; j < DirtParticle.PARTICLESWHENDIG; j++) {
|
||||
ps =
|
||||
new DirtParticle(currentVelocity.getI(),
|
||||
currentVelocity.getJ());
|
||||
ps.getPosition().setPoint(getOwner().getPosition().getX(),
|
||||
getOwner().getPosition().getY() - 20,
|
||||
getOwner().getPosition().getZ());
|
||||
((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().addPrettySprite(ps);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentVelocity.setI(-1);
|
||||
for (int i = LemmingJobSettings.BASHDISTANCE; i > 0; rayI--, i--) {
|
||||
|
||||
if (currentMap.getRGB(rayI, currentPoint.getY())
|
||||
== MapSettings.getInstance().getUnbreakableColor()) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
currentVelocity.setI(-PhysicsSettings.getInitialX());
|
||||
return;
|
||||
} else if (currentMap.getRGB(rayI, currentPoint.getY())
|
||||
!= MapSettings.getInstance().getPassableColor()) {
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("rayI2..." + rayI);
|
||||
}
|
||||
|
||||
rectangle.x = currentPoint.getX() - rectangle.width;
|
||||
rectangle.y = currentPoint.getY() - 39;
|
||||
map.subtractShape(rectangle);
|
||||
|
||||
//Make the debris
|
||||
PrettySprite ps;
|
||||
for (int j = 0; j < DirtParticle.PARTICLESWHENDIG; j++) {
|
||||
ps = new DirtParticle(currentVelocity.getI(), currentVelocity.getJ());
|
||||
ps.getPosition().setPoint(getOwner().getPosition().getX(),
|
||||
getOwner().getPosition().getY(),
|
||||
getOwner().getPosition().getZ());
|
||||
((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().addPrettySprite(ps);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
//import java.awt.geom.Ellipse2D;
|
||||
//import java.awt.geom.Ellipse2D.Float;
|
||||
|
||||
//import java.awt.image.BufferedImage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
//import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.5 Jose - Completed Blocker
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.5
|
||||
*/
|
||||
public class BlockerJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Creates a new <code>BlockerJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public BlockerJob() {
|
||||
super(LemmingJobSettings.JOB_ID_BLOCKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called whenever the owner is set and it is
|
||||
* not NULL.
|
||||
*/
|
||||
protected void onSetOwner() {
|
||||
getOwner().getVelocity().setI(0);
|
||||
getOwner().updateDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
Level level
|
||||
= ((GamePlayState) GameEngine.getInstance().getCurrentState()).getLevel();
|
||||
Lemming lem = this.getOwner();
|
||||
Point blockerPoint = lem.getPosition();
|
||||
List list = level.getActiveLemmings();
|
||||
|
||||
Lemming currLem;
|
||||
Point currentPoint;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
currLem = (Lemming) list.get(i);
|
||||
currentPoint = currLem.getPosition();
|
||||
|
||||
if (Math.abs(blockerPoint.getX() - currentPoint.getX())
|
||||
< LemmingJobSettings.BLOCKERTOLERANCE
|
||||
&& Math.abs(blockerPoint.getY() - currentPoint.getY())
|
||||
< LemmingJobSettings.BLOCKERTOLERANCE) {
|
||||
|
||||
if (Math.abs(currentPoint.getX() + currLem.getVelocity().getI()
|
||||
- blockerPoint.getX())
|
||||
> Math.abs(currentPoint.getX() - blockerPoint.getX())) {
|
||||
return;
|
||||
}
|
||||
currLem.getVelocity().setI(-1 * currLem.getVelocity().getI());
|
||||
currLem.updateDirection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
//import java.awt.image.BufferedImage;
|
||||
import java.awt.Color;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
//import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.4 - Turn around stop bridging
|
||||
*
|
||||
* v1.2 - Basic Bridging
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.4
|
||||
*/
|
||||
public class BridgerJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Stores the current number of bricks laid down
|
||||
*/
|
||||
private int bricks;
|
||||
|
||||
/**
|
||||
* Stores the current wait time
|
||||
*/
|
||||
private int waitTime;
|
||||
|
||||
/**
|
||||
* The rectangle brick
|
||||
*/
|
||||
private Rectangle rectangle;
|
||||
|
||||
/**
|
||||
* The direction
|
||||
*/
|
||||
private int direction;
|
||||
|
||||
/**
|
||||
* Creates a new <code>BridgerJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public BridgerJob() {
|
||||
super(LemmingJobSettings.JOB_ID_BRIDGER);
|
||||
rectangle = new Rectangle(10, 2);
|
||||
bricks = 0;
|
||||
direction = 0;
|
||||
waitTime = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
|
||||
// BufferedImage currentMap = PhysicsEngine.
|
||||
//getInstance().getCurrentMap();
|
||||
Map map = ((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().getMap();
|
||||
|
||||
Lemming lem = this.getOwner();
|
||||
|
||||
PhysicsVector currentVelocity = lem.getVelocity();
|
||||
Point currentPoint = lem.getPosition();
|
||||
|
||||
if (direction == 0) {
|
||||
direction = (currentVelocity.getI() > 0) ? 1 : -1;
|
||||
} else if (currentVelocity.getI() > 0 && direction != 1) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
return;
|
||||
} else if (currentVelocity.getI() < 0 && direction != -1) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bricks == 72) {
|
||||
currentVelocity.setI(0);
|
||||
if (waitTime >= LemmingJobSettings.BRIDGERDONETIME) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("waitTime: " + waitTime);
|
||||
}
|
||||
waitTime++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentVelocity.getI() > 0) {
|
||||
if (bricks % 3 == 0) {
|
||||
rectangle.x = currentPoint.getX() + rectangle.width;
|
||||
rectangle.y = currentPoint.getY();
|
||||
map.addShape(rectangle, Color.PINK);
|
||||
}
|
||||
bricks++;
|
||||
|
||||
} else {
|
||||
if (bricks % 3 == 0) {
|
||||
rectangle.x = currentPoint.getX()
|
||||
- (rectangle.width * 2);
|
||||
rectangle.y = currentPoint.getY();
|
||||
map.addShape(rectangle, Color.PINK);
|
||||
}
|
||||
bricks++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*accessort
|
||||
*@return int
|
||||
*/
|
||||
public int getDirection() {
|
||||
return (this.direction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
//import java.awt.image.BufferedImage;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
//import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
//import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
//import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
//import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ClimberJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private boolean isClimbing;
|
||||
|
||||
/**
|
||||
* the lemming direction
|
||||
*/
|
||||
private int direction;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ClimberJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public ClimberJob() {
|
||||
super(LemmingJobSettings.JOB_ID_CLIMBER,
|
||||
LemmingJobSettings.JOB_ID_CLIMBER + "_"
|
||||
+ LemmingJobSettings.REGULAR_FALLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
if (((Lemming) this.getOwner()).getVelocity().getI() > 0) {
|
||||
direction = 1;
|
||||
} else if (((Lemming) this.getOwner()).getVelocity().getI() < 0) {
|
||||
direction = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method setIsClimbing
|
||||
*
|
||||
*
|
||||
* @param isClimbing boolean
|
||||
*
|
||||
*/
|
||||
public void setIsClimbing(boolean isClimbing) {
|
||||
this.isClimbing = isClimbing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getIsClimbing
|
||||
*
|
||||
*
|
||||
* @return boolean , whether or not the lemming is climbing
|
||||
*
|
||||
*/
|
||||
public boolean isClimbing() {
|
||||
return (this.isClimbing);
|
||||
}
|
||||
|
||||
/**
|
||||
*mutator
|
||||
*@param direction direction
|
||||
*/
|
||||
public void setDirection(int direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
/**
|
||||
*accessor
|
||||
*@return int
|
||||
*/
|
||||
public int getDirection() {
|
||||
return (this.direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import java.awt.geom.Ellipse2D;
|
||||
//import java.awt.geom.Ellipse2D.Float;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.DirtParticle;
|
||||
import edu.gatech.cs2335.lemmings.engine.PrettySprite;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.5 - Jose Caban - added process() handling
|
||||
* TOnotDO: correct problem with non-breakable areas
|
||||
* getting nicked slightly
|
||||
*
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.5
|
||||
*/
|
||||
public class DiggerJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Dig a Circle!
|
||||
*/
|
||||
private Ellipse2D.Float circle;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DiggerJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public DiggerJob() {
|
||||
super(LemmingJobSettings.JOB_ID_DIGGER);
|
||||
circle = new Ellipse2D.Float(0, 0, 20, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
|
||||
BufferedImage currentMap = PhysicsEngine.getInstance().getCurrentMap();
|
||||
Map map = ((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().getMap();
|
||||
|
||||
Lemming lem = this.getOwner();
|
||||
|
||||
PhysicsVector currentVelocity = lem.getVelocity();
|
||||
Point currentPoint = lem.getPosition();
|
||||
|
||||
//going to check whether or not this lemming can still be a basher
|
||||
int rayJ = currentPoint.getY();
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("Calculating Basher Stuff...");
|
||||
System.out.println("rayJ1..." + rayJ);
|
||||
System.out.println("currentVelocity..." + currentVelocity.getJ());
|
||||
}
|
||||
|
||||
for (int i = 0; i < LemmingJobSettings.DIGDISTANCE; rayJ++, i++) {
|
||||
|
||||
if (currentMap.getRGB(currentPoint.getX(), rayJ) == MapSettings
|
||||
.getInstance().getUnbreakableColor()) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
return;
|
||||
} else if (currentMap.getRGB(currentPoint.getX(), rayJ)
|
||||
!= MapSettings.getInstance().getPassableColor()) {
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("rayJ..." + rayJ);
|
||||
}
|
||||
|
||||
circle.x = currentPoint.getX() - (circle.width) / 2;
|
||||
circle.y = currentPoint.getY() - (circle.height) / 2;
|
||||
map.subtractShape(circle);
|
||||
|
||||
//Make the debris
|
||||
PrettySprite ps;
|
||||
for (int j = 0; j < DirtParticle.PARTICLESWHENDIG; j++) {
|
||||
ps = new DirtParticle(currentVelocity.getI(), currentVelocity.getJ());
|
||||
ps.getPosition().setPoint(getOwner().getPosition().getX(),
|
||||
getOwner().getPosition().getY(),
|
||||
getOwner().getPosition().getZ());
|
||||
((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().addPrettySprite(ps);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import java.awt.geom.Ellipse2D;
|
||||
//import java.awt.geom.Ellipse2D.Float;
|
||||
|
||||
//import java.awt.image.BufferedImage;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
//import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSet;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.2 - Basic Exploding
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.2
|
||||
*/
|
||||
public class ExploderJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Time to blow
|
||||
*/
|
||||
private int timeLeftOnEarth;
|
||||
|
||||
/**
|
||||
* Explosion thing
|
||||
*/
|
||||
private Ellipse2D.Float circle;
|
||||
|
||||
/**
|
||||
* The tileset with the numbers.
|
||||
*/
|
||||
// private TileSet numbers;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ExploderJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public ExploderJob() {
|
||||
super(LemmingJobSettings.JOB_ID_EXPLODER);
|
||||
timeLeftOnEarth = LemmingJobSettings.BLOWUPTIME;
|
||||
circle = new Ellipse2D.Float(0, 0,
|
||||
LemmingJobSettings.EXPLOSIONDIAMETER,
|
||||
LemmingJobSettings.EXPLOSIONDIAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getTimeLeftOnEarth</code> method here.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public int getTimeLeftOnEarth() {
|
||||
return timeLeftOnEarth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
if (timeLeftOnEarth == 0) {
|
||||
Level level = ((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel();
|
||||
Lemming lem = this.getOwner();
|
||||
Point currentPoint = lem.getPosition();
|
||||
|
||||
circle.x = currentPoint.getX() - (circle.width / 2);
|
||||
circle.y = currentPoint.getY() - (circle.width / 2) - 6;
|
||||
|
||||
level.getMap().subtractShape(circle);
|
||||
|
||||
level.killLemming(lem, false);
|
||||
|
||||
}
|
||||
timeLeftOnEarth--;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class FloaterJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Creates a new <code>FloaterJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public FloaterJob() {
|
||||
super(LemmingJobSettings.JOB_ID_FLOATER,
|
||||
LemmingJobSettings.JOB_ID_FLOATER + "_"
|
||||
+ LemmingJobSettings.REGULAR_FALLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
///yeah...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.PrettySprite;
|
||||
import edu.gatech.cs2335.lemmings.engine.FlameParticle;
|
||||
//import edu.gatech.cs2335.lemmings.engine.*;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg184g@mail.gatech.edu">Jose Caban</A>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class HandGliderJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Used to keep track of when to reset out little AE major
|
||||
*/
|
||||
private boolean hasFlown;
|
||||
|
||||
/**
|
||||
* Creates a new <code>HandGliderJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public HandGliderJob() {
|
||||
super(LemmingJobSettings.JOB_ID_HAND_GLIDER,
|
||||
LemmingJobSettings.JOB_ID_HAND_GLIDER + "_"
|
||||
+ LemmingJobSettings.REGULAR_FALLER);
|
||||
|
||||
hasFlown = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called whenever the owner is set and it is
|
||||
* not NULL.
|
||||
*/
|
||||
protected void onSetOwner() {
|
||||
}
|
||||
|
||||
/**
|
||||
*@return boolean
|
||||
*/
|
||||
public boolean hasFlown() {
|
||||
return hasFlown;
|
||||
}
|
||||
|
||||
/**
|
||||
*@param b boolean
|
||||
*/
|
||||
public void setFlown(boolean b) {
|
||||
this.hasFlown = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
//No need for this, Physics handles it
|
||||
PrettySprite ps;
|
||||
for (int i = 0; i < FlameParticle.PARTICLESWHENFLAME; i++) {
|
||||
ps = new FlameParticle();
|
||||
ps.getPosition().setPoint(getOwner().getPosition().getX(),
|
||||
getOwner().getPosition().getY(),
|
||||
getOwner().getPosition().getZ());
|
||||
((GamePlayState)
|
||||
GameEngine.getInstance().getCurrentState()).getLevel().addPrettySprite(ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class JumperJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Creates a new <code>JumperJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public JumperJob() {
|
||||
super(LemmingJobSettings.JOB_ID_JUMPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
//Jose is a nUb.
|
||||
Lemming lem = getOwner();
|
||||
|
||||
if (lem.getVelocity().getJ() == 0) {
|
||||
lem.getVelocity().setJ(PhysicsSettings.getInstance().getLaunchSpeed());
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class LemmingJob {
|
||||
|
||||
/**
|
||||
* The string id of the lemming job.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* The lemming, with which this job is associated.
|
||||
*/
|
||||
private Lemming owner;
|
||||
|
||||
/**
|
||||
* The regular animation associated with the job.
|
||||
*/
|
||||
private AnimatedSprite regularAnimation;
|
||||
|
||||
/**
|
||||
* The falling animation associated with the job.
|
||||
*/
|
||||
private AnimatedSprite fallingAnimation;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingJob</code> instance.
|
||||
*/
|
||||
protected LemmingJob() {
|
||||
this(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingJob</code> instance.
|
||||
*
|
||||
* @param jobId a <code>String</code> value
|
||||
*/
|
||||
protected LemmingJob(String jobId) {
|
||||
this(jobId, LemmingJobSettings.REGULAR_FALLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingJob</code> instance.
|
||||
*
|
||||
* @param regularId a <code>String</code> value
|
||||
* @param fallingId a <code>String</code> value
|
||||
*/
|
||||
protected LemmingJob(String regularId, String fallingId) {
|
||||
//Set up Job Id:
|
||||
id = regularId;
|
||||
|
||||
//Set up Owner:
|
||||
owner = null;
|
||||
|
||||
//Set up animations:
|
||||
regularAnimation
|
||||
= new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet(regularId),
|
||||
Direction.RIGHT,
|
||||
Looping.INFINITE);
|
||||
fallingAnimation = new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet(fallingId),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.INFINITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>cleanUp</code> method here.
|
||||
*
|
||||
*/
|
||||
public void cleanUp() {
|
||||
id = null;
|
||||
owner = null;
|
||||
regularAnimation = null;
|
||||
fallingAnimation = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the id property.
|
||||
*
|
||||
* @return the current value of the id property
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the owner property.
|
||||
*
|
||||
* @return the current value of the owner property
|
||||
*/
|
||||
public Lemming getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the owner property.
|
||||
*
|
||||
* @param aOwner the new value of the owner property
|
||||
*/
|
||||
public void setOwner(Lemming aOwner) {
|
||||
owner = aOwner;
|
||||
|
||||
if (owner != null) {
|
||||
onSetOwner();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the animation property.
|
||||
*
|
||||
* @return the current value of the animation property
|
||||
*/
|
||||
public AnimatedSprite getAnimation() {
|
||||
if (owner.getPhysics().isFalling()) {
|
||||
return fallingAnimation;
|
||||
} else {
|
||||
return regularAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the regular animation for this lemming.
|
||||
*
|
||||
* @param animation an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
protected void setRegularAnimation(AnimatedSprite animation) {
|
||||
regularAnimation.setAnimation(animation.getAnimation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getRegularAnimation</code> method here.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getRegularAnimation() {
|
||||
return regularAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getFallingAnimation</code> method here.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getFallingAnimation() {
|
||||
return fallingAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the falling animation for this lemming.
|
||||
*
|
||||
* @param animation an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
protected void setFallingAnimation(AnimatedSprite animation) {
|
||||
fallingAnimation.setAnimation(animation.getAnimation());
|
||||
}
|
||||
|
||||
//@roseuid 4065FCD300AE
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*
|
||||
*/
|
||||
public abstract void process();
|
||||
|
||||
/**
|
||||
* This function will be called whenever the owner is set and it is
|
||||
* not NULL.
|
||||
*/
|
||||
protected void onSetOwner() { }
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
/**
|
||||
* Creates lemming jobs.
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LemmingJobFactory {
|
||||
|
||||
/**
|
||||
* Singleton Implementation.
|
||||
*/
|
||||
private static LemmingJobFactory instance;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingJobFactory</code> instance.
|
||||
*
|
||||
*/
|
||||
private LemmingJobFactory() { }
|
||||
|
||||
/**
|
||||
* Access method for the instance property.
|
||||
*
|
||||
* @return the current value of the instance property.
|
||||
*/
|
||||
public static LemmingJobFactory getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new LemmingJobFactory();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
//@roseuid 406602CE0394
|
||||
/**
|
||||
* Creates a lemming job with the specified id and initializes it
|
||||
* appropriately.
|
||||
*
|
||||
* @param id The id of the job type to create.
|
||||
* @return The new lemming job.
|
||||
*
|
||||
*/
|
||||
public LemmingJob makeJob(String id) {
|
||||
LemmingJob result = null;
|
||||
|
||||
if (LemmingJobSettings.JOB_ID_BASHER.equals(id)) {
|
||||
result = new BasherJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_BLOCKER.equals(id)) {
|
||||
result = new BlockerJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_BRIDGER.equals(id)) {
|
||||
result = new BridgerJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_CLIMBER.equals(id)) {
|
||||
result = new ClimberJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_DIGGER.equals(id)) {
|
||||
result = new DiggerJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_EXPLODER.equals(id)) {
|
||||
result = new ExploderJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_FLOATER.equals(id)) {
|
||||
result = new FloaterJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_HAND_GLIDER.equals(id)) {
|
||||
result = new HandGliderJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_JUMPER.equals(id)) {
|
||||
result = new JumperJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_MINER.equals(id)) {
|
||||
result = new MinerJob();
|
||||
|
||||
} else if (LemmingJobSettings.JOB_ID_WALKER.equals(id)) {
|
||||
result = new WalkerJob();
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Bad job id");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
/**
|
||||
* Contains some settings for the lemming jobs.
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
*/
|
||||
public final class LemmingJobSettings {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final boolean BDEBUG = false;
|
||||
|
||||
/**
|
||||
* The id the basher job type.
|
||||
*/
|
||||
public static final String JOB_ID_BASHER = "basher";
|
||||
|
||||
/**
|
||||
* The id the blocker job type.
|
||||
*/
|
||||
public static final String JOB_ID_BLOCKER = "blocker";
|
||||
|
||||
/**
|
||||
* The id the bridger job type.
|
||||
*/
|
||||
public static final String JOB_ID_BRIDGER = "bridger";
|
||||
|
||||
/**
|
||||
* The id the climber job type.
|
||||
*/
|
||||
public static final String JOB_ID_CLIMBER = "climber";
|
||||
|
||||
/**
|
||||
* The id the digger job type.
|
||||
*/
|
||||
public static final String JOB_ID_DIGGER = "digger";
|
||||
|
||||
/**
|
||||
* The id the exploder job type.
|
||||
*/
|
||||
public static final String JOB_ID_EXPLODER = "exploder";
|
||||
|
||||
/**
|
||||
* The id the floater job type.
|
||||
*/
|
||||
public static final String JOB_ID_FLOATER = "floater";
|
||||
|
||||
/**
|
||||
* The id the hand_glider job type.
|
||||
*/
|
||||
public static final String JOB_ID_HAND_GLIDER = "hand_glider";
|
||||
|
||||
/**
|
||||
* The id the jumper job type.
|
||||
*/
|
||||
public static final String JOB_ID_JUMPER = "jumper";
|
||||
|
||||
/**
|
||||
* The id the launcher job type.
|
||||
*/
|
||||
public static final String JOB_ID_LAUNCHER = "launcher";
|
||||
|
||||
/**
|
||||
* The id the miner job type.
|
||||
*/
|
||||
public static final String JOB_ID_MINER = "miner";
|
||||
|
||||
/**
|
||||
* The id the walker job type.
|
||||
*/
|
||||
public static final String JOB_ID_WALKER = "walker";
|
||||
|
||||
/**
|
||||
* The id of the regular faller animation.
|
||||
*/
|
||||
public static final String REGULAR_FALLER = "faller";
|
||||
|
||||
/**
|
||||
* Contains all of the job names in a nice little array.
|
||||
*/
|
||||
public static final String[] ALL_JOB_NAMES = {
|
||||
JOB_ID_BASHER,
|
||||
JOB_ID_BLOCKER,
|
||||
JOB_ID_BRIDGER,
|
||||
JOB_ID_CLIMBER,
|
||||
JOB_ID_DIGGER,
|
||||
JOB_ID_EXPLODER,
|
||||
JOB_ID_FLOATER,
|
||||
JOB_ID_HAND_GLIDER,
|
||||
JOB_ID_JUMPER,
|
||||
JOB_ID_LAUNCHER,
|
||||
JOB_ID_MINER,
|
||||
JOB_ID_WALKER,
|
||||
};
|
||||
|
||||
/**
|
||||
* The max distance between a basher and a wall to bash
|
||||
*/
|
||||
public static final int BASHDISTANCE = 75;
|
||||
|
||||
/**
|
||||
* The distance to the point to dig
|
||||
*/
|
||||
public static final int DIGDISTANCE = 8;
|
||||
|
||||
/**
|
||||
* The distance to the point to mine
|
||||
*/
|
||||
public static final int MINEDISTANCE = 20;
|
||||
|
||||
/**
|
||||
* Time to blow
|
||||
*/
|
||||
public static final int BLOWUPTIME = 30;
|
||||
|
||||
/**
|
||||
* Explosion Diameter
|
||||
*/
|
||||
public static final int EXPLOSIONDIAMETER = 42;
|
||||
|
||||
/**
|
||||
* Blocker Tolerance (distance to change direction)
|
||||
*/
|
||||
public static final int BLOCKERTOLERANCE = 10;
|
||||
|
||||
/**
|
||||
* Bridger wait time
|
||||
*/
|
||||
public static final int BRIDGERDONETIME = 50;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingJobSettings</code> instance.
|
||||
*/
|
||||
private LemmingJobSettings() { }
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import java.awt.geom.Ellipse2D;
|
||||
//import java.awt.geom.Ellipse2D.Float;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsEngine;
|
||||
//import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsVector;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Map;
|
||||
import edu.gatech.cs2335.lemmings.engine.MapSettings;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.DirtParticle;
|
||||
import edu.gatech.cs2335.lemmings.engine.PrettySprite;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* v1.5 - Jose Caban - added process() handling
|
||||
* TOnotDO: correct problem with non-breakable areas
|
||||
* getting nicked slightly
|
||||
*
|
||||
*
|
||||
* @author <a href="mailto:gtg184g@mail.gatech.edu">Jose Caban</a>
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.5
|
||||
*/
|
||||
public class MinerJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Dig a Circle!
|
||||
*/
|
||||
private Ellipse2D.Float circle;
|
||||
|
||||
/**
|
||||
* Creates a new <code>MinerJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public MinerJob() {
|
||||
super(LemmingJobSettings.JOB_ID_MINER);
|
||||
circle = new Ellipse2D.Float(0, 0, 20, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
BufferedImage currentMap = PhysicsEngine.getInstance().getCurrentMap();
|
||||
Map map = ((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().getMap();
|
||||
|
||||
Lemming lem = this.getOwner();
|
||||
|
||||
PhysicsVector currentVelocity = lem.getVelocity();
|
||||
Point currentPoint = lem.getPosition();
|
||||
|
||||
//going to check whether or not this lemming can still be a basher
|
||||
int rayI = currentPoint.getX();
|
||||
// int max = LemmingJobSettings.MINEDISTANCE + rayI;
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("Calculating Miner Stuff...");
|
||||
System.out.println("rayI1..." + rayI);
|
||||
System.out.println("currentVelocity..." + currentVelocity.getI());
|
||||
}
|
||||
|
||||
boolean bFoundDirt = false;
|
||||
|
||||
if (currentVelocity.getI() > 0) {
|
||||
for (int i = 0; i < LemmingJobSettings.MINEDISTANCE; rayI++, i++) {
|
||||
|
||||
if (currentMap.getRGB(rayI, currentPoint.getY() + i)
|
||||
== MapSettings.getInstance().getUnbreakableColor()) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
return;
|
||||
} else if (currentMap.getRGB(rayI, currentPoint.getY() + i)
|
||||
!= MapSettings.getInstance().getPassableColor()) {
|
||||
bFoundDirt = true;
|
||||
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("rayI..." + rayI);
|
||||
}
|
||||
|
||||
}
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("Currently at " + rayI
|
||||
+ (currentPoint.getY() + i));
|
||||
}
|
||||
}
|
||||
if (bFoundDirt) {
|
||||
circle.x = currentPoint.getX();
|
||||
circle.y = currentPoint.getY();
|
||||
map.subtractShape(circle);
|
||||
|
||||
//Make the debris
|
||||
PrettySprite ps;
|
||||
for (int j = 0; j < DirtParticle.PARTICLESWHENDIG; j++) {
|
||||
ps = new DirtParticle(currentVelocity.getI(), currentVelocity.getJ());
|
||||
ps.getPosition().setPoint(getOwner().getPosition().getX(),
|
||||
getOwner().getPosition().getY(),
|
||||
getOwner().getPosition().getZ());
|
||||
((GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState()).getLevel().addPrettySprite(ps);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < LemmingJobSettings.MINEDISTANCE; rayI--, i++) {
|
||||
|
||||
if (currentMap.getRGB(rayI, currentPoint.getY() + i)
|
||||
== MapSettings.getInstance().getUnbreakableColor()) {
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
return;
|
||||
} else if (currentMap.getRGB(rayI, currentPoint.getY() + i)
|
||||
!= MapSettings.getInstance().getPassableColor()) {
|
||||
bFoundDirt = true;
|
||||
}
|
||||
if (LemmingJobSettings.BDEBUG) {
|
||||
System.out.println("Currently at " + rayI
|
||||
+ (currentPoint.getY() + i));
|
||||
}
|
||||
}
|
||||
if (bFoundDirt) {
|
||||
circle.x = currentPoint.getX() - 20;
|
||||
circle.y = currentPoint.getY();
|
||||
map.subtractShape(circle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lem.setOccupation(LemmingJobSettings.JOB_ID_WALKER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package edu.gatech.cs2335.lemmings.engine.lemmingjob;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.physics.PhysicsSettings;
|
||||
|
||||
/**
|
||||
* This class represents a lemming job. Essentially, it defines what
|
||||
* the lemming does in the world, what kind of effect it has, etc.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class WalkerJob extends LemmingJob {
|
||||
|
||||
/**
|
||||
* Creates a new <code>WalkerJob</code> instance.
|
||||
*
|
||||
*/
|
||||
public WalkerJob() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called whenever the owner is set and it is
|
||||
* not NULL.
|
||||
*/
|
||||
protected void onSetOwner() {
|
||||
if (getOwner().getVelocity().getI() >= 0) {
|
||||
getOwner().getVelocity().setI(PhysicsSettings.getInstance()
|
||||
.getInitialX());
|
||||
} else {
|
||||
getOwner().getVelocity().setI(-PhysicsSettings.getInstance()
|
||||
.getInitialX());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the effect of the lemming on the world, as well as the
|
||||
* lemming's position in the world.
|
||||
*/
|
||||
public void process() {
|
||||
//Since this is a plain walker lemming, there is really nothing to
|
||||
//do here.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
package edu.gatech.cs2335.lemmings.file;
|
||||
|
||||
import java.util.Map;
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
//import java.awt.image.BufferedImage;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
import edu.gatech.cs2335.lemmings.engine.LevelData;
|
||||
import edu.gatech.cs2335.lemmings.engine.PortalFactory;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobSettings;
|
||||
import edu.gatech.cs2335.lemmings.graphics.ImageLoader;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSet;
|
||||
import edu.gatech.cs2335.lemmings.graphics.ImprovedTileSet;
|
||||
|
||||
/**
|
||||
* Allows us to read level data, maps and other nice stuff. The string
|
||||
* passed in to any of the "load" methods is basically the id of the
|
||||
* level. The loader then tests if there is a directory with the same
|
||||
* name in the levels list. If there is one, then it loads the level
|
||||
* from it. If there is no such directory, then is appends a .lmf
|
||||
* extension to it and checks wether there is a file with that
|
||||
* name. If there is, it extracts the file and then loads the level
|
||||
* from that. If there is no such file, then the loading fails and
|
||||
* null is returned.
|
||||
*
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LevelReader {
|
||||
|
||||
/**
|
||||
* Display debug stuff?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Singleton Implementation.
|
||||
*/
|
||||
private static final LevelReader INSTANCE = new LevelReader();
|
||||
|
||||
/**
|
||||
* The level data is not going to change over the course of the
|
||||
* game. Thus, if we've loaded it once, we are not going to load it
|
||||
* again. It will be stored here, instead.
|
||||
*/
|
||||
private Map data;
|
||||
|
||||
/**
|
||||
* A map of maps... :/
|
||||
*/
|
||||
private Map maps;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelReader</code> INSTANCE.
|
||||
*
|
||||
*/
|
||||
private LevelReader() {
|
||||
data = new HashMap();
|
||||
maps = new HashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the INSTANCE property.
|
||||
*
|
||||
* @return the current value of the INSTANCE property
|
||||
*/
|
||||
public static LevelReader getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
//@roseuid 4066356A0190
|
||||
/**
|
||||
* Returns the list of all levels available. The elements in the
|
||||
* list returned are String ids of the available levels.
|
||||
* @return The array of ids of the levels.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public String[] getLevelList() /*throws Exception*/ {
|
||||
String path = "levels";
|
||||
File f = new File(path);
|
||||
|
||||
if (!f.exists() || !f.isDirectory()) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("Could not find the levels directory.");
|
||||
}
|
||||
//throw new Exception("Could not find the levels directory.");
|
||||
}
|
||||
|
||||
String[] levels = f.list(new LevelNameFilter());
|
||||
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
int index = levels[i].lastIndexOf(".");
|
||||
if (index > 0) {
|
||||
levels[i] = levels[i].substring(0, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LevelReader: List of available levels:");
|
||||
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
System.out.println("\t" + levels[i]);
|
||||
}
|
||||
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the id of a level, finds the next level. Basically, if the
|
||||
* level id cannot be found in the list, returns the first element
|
||||
* of the list. If the level id is the last level, returns null.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String findNextLevel(String id) {
|
||||
String[] levels = getLevelList();
|
||||
int index = -1;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("LevelReader.findNextLevel - Current level:");
|
||||
System.err.println("\t\"" + id + "\"");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
if (id == null || id.equals("")) {
|
||||
return levels[0];
|
||||
}
|
||||
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
if (id.equals(levels[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
//Did not find a level with this name:
|
||||
return levels[0];
|
||||
}
|
||||
|
||||
if (index == levels.length - 1) {
|
||||
//Got last level:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("LevelReader.findNextLevel - next level:");
|
||||
System.err.println("\t\"" + levels[index + 1] + "\"");
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
return levels[index + 1];
|
||||
}
|
||||
|
||||
//@roseuid 40663BFF008F
|
||||
/**
|
||||
* Loads the level with the name specified if possible. Otherwise,
|
||||
* returns null.
|
||||
*
|
||||
* @param name The name of the level to load.
|
||||
* @return Level
|
||||
*
|
||||
*/
|
||||
public Level loadLevel(String name) {
|
||||
Level result = null;
|
||||
|
||||
result = new Level();
|
||||
|
||||
result.setMap(loadMap(name));
|
||||
result.setData(loadLevelData(name));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the map for the level with the specified name.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @return a <code>Map</code> value
|
||||
*/
|
||||
public edu.gatech.cs2335.lemmings.engine.Map loadMap(String name) {
|
||||
//Note here we have to use this ugly qualified name with the
|
||||
//package, because otherwise, it will conflict with java.util.Map
|
||||
//that we are also using here.
|
||||
edu.gatech.cs2335.lemmings.engine.Map m = null;
|
||||
File f = null;
|
||||
|
||||
if (maps.containsKey(name)) {
|
||||
return (edu.gatech.cs2335.lemmings.engine.Map) maps.get(name);
|
||||
}
|
||||
|
||||
m = new edu.gatech.cs2335.lemmings.engine.Map();
|
||||
f = getFile(name);
|
||||
|
||||
if (f == null) { return null; }
|
||||
|
||||
//Set up files:
|
||||
File bgFile = new File(f, "background.png");
|
||||
File mapFile = new File(f, "terrain.png");
|
||||
File txFile = new File(f, "texture.png");
|
||||
File utxFile = new File(f, "unbreakableTexture.png");
|
||||
File waterFile = new File(f, "water.png");
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\nLoading Map:");
|
||||
System.out.println("\tBG: " + bgFile.getAbsolutePath());
|
||||
System.out.println("\t\tExists? " + bgFile.exists());
|
||||
System.out.println("\tMP: " + mapFile.getAbsolutePath());
|
||||
System.out.println("\t\tExists? " + mapFile.exists());
|
||||
System.out.println("\tTX: " + txFile.getAbsolutePath());
|
||||
System.out.println("\t\tExists? " + txFile.exists());
|
||||
System.out.println("\tWT: " + waterFile.getAbsolutePath());
|
||||
System.out.println("\t\tExists? " + waterFile.exists());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\n\nLoading Water tileset:");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
TileSet ts = new ImprovedTileSet();
|
||||
ts.loadTileset(waterFile.getAbsolutePath());
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\nDone... Loaded " + ts.getTileCount() + " frames.");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
m.setBackground(ImageLoader.getInstance().loadImage(bgFile));
|
||||
m.setMap(ImageLoader.getInstance().loadImage(mapFile));
|
||||
m.setTexture(ImageLoader.getInstance().loadImage(txFile));
|
||||
m.setUnbreakableTexture(ImageLoader.getInstance().loadImage(utxFile));
|
||||
m.setWaterAnimation(ts);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
//@roseuid 40663C5300B7
|
||||
/**
|
||||
* Loads the data for the level with the specified name.
|
||||
*
|
||||
* @param name The name of the level to load the data for.
|
||||
* @return LevelData
|
||||
*
|
||||
*/
|
||||
public LevelData loadLevelData(String name) {
|
||||
File f = null;
|
||||
LevelData result = null;
|
||||
|
||||
if (data.containsKey(name)) {
|
||||
//The level data has already been loaded. Just return it:
|
||||
return (LevelData) data.get(name);
|
||||
}
|
||||
|
||||
f = getFile(name);
|
||||
result = new LevelData();
|
||||
|
||||
if (f == null) {
|
||||
throw new IllegalArgumentException("Could not find level " + name);
|
||||
}
|
||||
|
||||
if (f.isDirectory()) {
|
||||
//Load from the directory:
|
||||
|
||||
//Load the properties first:
|
||||
FileInputStream fis = null;
|
||||
Properties p = new Properties();
|
||||
File pf = new File(f.getAbsolutePath(), "data.dat");
|
||||
|
||||
//Open up the resource properties file:
|
||||
try {
|
||||
fis = new FileInputStream(pf);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("LevelReader: Could not open data file...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
p.load(fis);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("LevelReader: Could not "
|
||||
+ "read the data file...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LevelReader: Loaded the following properties");
|
||||
System.out.println(p);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//ID
|
||||
result.setId(name);
|
||||
|
||||
//Fill the data with properties:
|
||||
loadLevelData(result, p);
|
||||
|
||||
//Load the thumbnail:
|
||||
result.setThumbnail(ImageLoader.getInstance()
|
||||
.loadImage(new File(f.getAbsolutePath(),
|
||||
"thumb.png")));
|
||||
|
||||
}
|
||||
|
||||
//Would have been nice to actually implement loading from archive...
|
||||
|
||||
if (result != null) {
|
||||
data.put(name, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* After the properties have been read from a file, this function
|
||||
* will load the level data with them.
|
||||
*
|
||||
* @param result a <code>LevelData</code> value
|
||||
* @param p a <code>Properties</code> value
|
||||
*/
|
||||
private void loadLevelData(LevelData result, Properties p) {
|
||||
//Name
|
||||
result.setName(p.getProperty("name", "Default Level"));
|
||||
|
||||
//Number of Lemmings:
|
||||
try {
|
||||
result.setNumLemmings(Integer.parseInt(p.getProperty("num_lemmings",
|
||||
"10")));
|
||||
} catch (NumberFormatException nfe) {
|
||||
result.setNumLemmings(10);
|
||||
}
|
||||
|
||||
//Percent to Save:
|
||||
try {
|
||||
result.setPercentToSave(Integer.parseInt(p.getProperty("save_percent",
|
||||
"50")));
|
||||
} catch (NumberFormatException nfe) {
|
||||
result.setPercentToSave(50);
|
||||
}
|
||||
|
||||
//Time Limit:
|
||||
try {
|
||||
result.setTimeLimit(Long.parseLong(p.getProperty("time_limit",
|
||||
"600")));
|
||||
} catch (NumberFormatException nfe) {
|
||||
result.setTimeLimit(600);
|
||||
}
|
||||
|
||||
//Portals:
|
||||
for (int i = 0; i < PortalFactory.PORTAL_TYPES.length; i++) {
|
||||
String s = p.getProperty(PortalFactory.PORTAL_TYPES[i]);
|
||||
|
||||
if (s == null) {
|
||||
//No portals of this type in the level.
|
||||
continue;
|
||||
}
|
||||
|
||||
//Different portals of the same type delimited by commas:
|
||||
StringTokenizer st = new StringTokenizer(s, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
result.addPortal(PortalFactory.PORTAL_TYPES[i], st.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
// //Entrance:
|
||||
// try {
|
||||
// int x = 0;
|
||||
// int y = 0;
|
||||
|
||||
// x = Integer.parseInt(p.getProperty("entrance_x", "0"));
|
||||
// y = Integer.parseInt(p.getProperty("entrance_y", "0"));
|
||||
|
||||
// result.setEntrancePoint(x, y);
|
||||
// } catch (NumberFormatException nfe) {
|
||||
// result.setEntrancePoint(0, 0);
|
||||
// }
|
||||
|
||||
// //Exit:
|
||||
// try {
|
||||
// int x = 0;
|
||||
// int y = 0;
|
||||
|
||||
// x = Integer.parseInt(p.getProperty("exit_x", "0"));
|
||||
// y = Integer.parseInt(p.getProperty("exit_y", "0"));
|
||||
|
||||
// result.setExitPoint(x, y);
|
||||
// } catch (NumberFormatException nfe) {
|
||||
// result.setExitPoint(0, 0);
|
||||
// }
|
||||
|
||||
//Load the jobs:
|
||||
for (int i = 0; i < LemmingJobSettings.ALL_JOB_NAMES.length; i++) {
|
||||
int num = 0;
|
||||
|
||||
try {
|
||||
num = Integer
|
||||
.parseInt(p.getProperty(LemmingJobSettings.ALL_JOB_NAMES[i], "0"));
|
||||
} catch (NumberFormatException nfe) {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
//Set the number of appropriate jobs in the level data.
|
||||
if (VERBOSE) {
|
||||
System.out.print("LevelReader: Got " + num + " jobs of type ");
|
||||
System.out.println("\""
|
||||
+ LemmingJobSettings.ALL_JOB_NAMES[i] + "\"");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
result.addJob(LemmingJobSettings.ALL_JOB_NAMES[i], num);
|
||||
}
|
||||
}
|
||||
|
||||
//Load water level:
|
||||
try {
|
||||
result.setWaterLevel(Integer.parseInt(p.getProperty("water_level",
|
||||
"-1")));
|
||||
} catch (NumberFormatException nfe) {
|
||||
result.setWaterLevel(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a name of the level, returns a file for where the thing is
|
||||
* located. Or null, if it is not present.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @return a <code>File</code> value
|
||||
*/
|
||||
private File getFile(String name) {
|
||||
String path = "levels/" + name;
|
||||
File f = new File(path);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LevelReader: Got file - " + f.getAbsolutePath());
|
||||
System.out.println(" File Exists? " + f.exists());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if (f.exists()) {
|
||||
return f;
|
||||
} else { //Do NOT make this recursive
|
||||
path += ".lmf";
|
||||
f = new File(path);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LevelReader: Got file - " + f.getAbsolutePath());
|
||||
System.out.println(" File Exists? " + f.exists());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if (f.exists()) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*@param args args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
LevelReader lr = new LevelReader();
|
||||
|
||||
System.out.println("Loaded data:");
|
||||
System.out.println(lr.loadLevelData("test_level"));
|
||||
System.out.flush();
|
||||
|
||||
try {
|
||||
lr.getLevelList();
|
||||
} catch (Exception e) {
|
||||
//sux
|
||||
System.out.println(e.getMessage());
|
||||
System.out.flush();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out the non-level files from the file dir.
|
||||
*/
|
||||
private class LevelNameFilter implements java.io.FilenameFilter {
|
||||
|
||||
/**
|
||||
* Tests if a specified file should be included in a file list.
|
||||
*
|
||||
* @param dir the directory in which the file was found.
|
||||
* @param name the name of the file.
|
||||
* @return true if and only if the name should be included in the
|
||||
* file list; false otherwise.
|
||||
*/
|
||||
public boolean accept(File dir, String name) {
|
||||
File testFile = new File(dir, name);
|
||||
|
||||
if (!testFile.exists()) { return false; }
|
||||
|
||||
if (testFile.isDirectory()) {
|
||||
//Check that the dir contains all the stuff we need:
|
||||
File bgFile = new File(testFile, "background.png");
|
||||
if (!bgFile.exists()) { return false; }
|
||||
|
||||
File datFile = new File(testFile, "data.dat");
|
||||
if (!datFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File terrainFile = new File(testFile, "terrain.png");
|
||||
if (!terrainFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File textureFile = new File(testFile, "texture.png");
|
||||
if (!textureFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File ubTextureFile = new File(testFile, "unbreakableTexture.png");
|
||||
if (!ubTextureFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File thumbFile = new File(testFile, "thumb.png");
|
||||
if (!thumbFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File waterFile = new File(testFile, "water.png");
|
||||
if (!waterFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
//Check that the file has the correct extension:
|
||||
String extn;
|
||||
int index = name.lastIndexOf('.');
|
||||
|
||||
if (index <= 0) {
|
||||
//The file doesn't have *any* extension
|
||||
return false;
|
||||
}
|
||||
|
||||
extn = name.substring(index);
|
||||
if (extn.equalsIgnoreCase(".lmf")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Class AnimatedSprite: This animated sprite will be used to render
|
||||
* all things animated onto the screen. It will be created using a
|
||||
* TileSet, and will treat the frames as follows: it will keep track
|
||||
* of which direction the sprite is moving in. If we are moving in a
|
||||
* certain direction, we will only use half of the frames - which half
|
||||
* depends on where we are moving - from left to right means using the
|
||||
* first half of the frames, and from right to left - the second
|
||||
* half. If the sprite is not moving in any direction, all frames will
|
||||
* be used in the animation.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 12, 2004) - Created the AnimatedSprite class
|
||||
* </PRE>
|
||||
*
|
||||
* @see TileSet
|
||||
* @see TileSetManager
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 12, 2004
|
||||
*/
|
||||
public final class AnimatedSprite {
|
||||
|
||||
/**
|
||||
* The direction in which the sprite is currently moving.
|
||||
*/
|
||||
private Direction movementDirection;
|
||||
|
||||
/**
|
||||
* The looping mode for the animation.
|
||||
*/
|
||||
private Looping loopingMode;
|
||||
|
||||
/**
|
||||
* The tileset holding the frames of animation.
|
||||
*/
|
||||
private TileSet animation;
|
||||
|
||||
/**
|
||||
* The frame to be displayed.
|
||||
*/
|
||||
private int currentFrame;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnimatedSprite</code> instance.
|
||||
*/
|
||||
public AnimatedSprite() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnimatedSprite</code> instance.
|
||||
*
|
||||
* @param anim a <code>TileSet</code> value
|
||||
*/
|
||||
public AnimatedSprite(TileSet anim) {
|
||||
this(anim, Direction.NO_DIRECTION, Looping.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnimatedSprite</code> instance.
|
||||
*
|
||||
* @param anim a <code>TileSet</code> value
|
||||
* @param dir a <code>Direction</code> value
|
||||
* @param loop a <code>Looping</code> value
|
||||
*/
|
||||
public AnimatedSprite(TileSet anim, Direction dir, Looping loop) {
|
||||
setAnimation(anim);
|
||||
setMovementDirection(dir);
|
||||
setLoopingMode(loop);
|
||||
resetFrameNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the sprite is initialized with animation already,
|
||||
* and false f it is not yet.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public synchronized boolean isInitialized() {
|
||||
return animation != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of frames in a complete loop of animation.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected synchronized int getNumFrames() {
|
||||
if (!isInitialized()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((Direction.LEFT == movementDirection)
|
||||
|| (Direction.RIGHT == movementDirection)) {
|
||||
return animation.getTileCount() / 2;
|
||||
} else if (Direction.NO_DIRECTION == movementDirection) {
|
||||
return animation.getTileCount();
|
||||
} else {
|
||||
System.err.println("AnimatedSprite: Got bad value for the direction.");
|
||||
System.err.flush();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direction in which the sprite is moving.
|
||||
*
|
||||
* @return a <code>Direction</code> value
|
||||
*/
|
||||
public synchronized Direction getMovementDirection() {
|
||||
return (this.movementDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a direction in which the sprite is moving. If the value
|
||||
* passed in is NULL, an exception will be thrown.
|
||||
*
|
||||
* @param v a <code>Direction</code> value
|
||||
*/
|
||||
public synchronized void setMovementDirection(Direction v) {
|
||||
if (v == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
this.movementDirection = v;
|
||||
|
||||
resetFrameNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the looping mode.
|
||||
*
|
||||
* @return a <code>Looping</code> value
|
||||
*/
|
||||
public synchronized Looping getLoopingMode() {
|
||||
return (this.loopingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new looping mode. If the value passed in is NULL, an
|
||||
* exception will be thrown.
|
||||
*
|
||||
* @param v a <code>Looping</code> value
|
||||
*/
|
||||
public synchronized void setLoopingMode(Looping v) {
|
||||
if (v == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
this.loopingMode = v;
|
||||
|
||||
resetFrameNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset associated with the sprite.
|
||||
*
|
||||
* @return a <code>TileSet</code> value
|
||||
*/
|
||||
public synchronized TileSet getAnimation() {
|
||||
return (this.animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new animation for the sprite.
|
||||
*
|
||||
* @param v a <code>TileSet</code> value
|
||||
*/
|
||||
public synchronized void setAnimation(TileSet v) {
|
||||
this.animation = v;
|
||||
|
||||
resetFrameNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current frame number.
|
||||
*
|
||||
* @return an <code>int</code> value.
|
||||
*/
|
||||
public synchronized int getCurrentFrame() {
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the current frame number.
|
||||
*/
|
||||
private synchronized void resetFrameNumber() {
|
||||
if (isInitialized()) {
|
||||
if (getMovementDirection() == Direction.LEFT) {
|
||||
currentFrame = getNumFrames();
|
||||
} else {
|
||||
currentFrame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next frame number and increments the counter.
|
||||
*
|
||||
* @return an <code>int</code> value.
|
||||
*/
|
||||
public synchronized int nextFrameNumber() {
|
||||
Looping l = getLoopingMode();
|
||||
Direction d = getMovementDirection();
|
||||
boolean endAnimation = false;
|
||||
|
||||
if (Looping.NONE == l) {
|
||||
//Static sprite. Nothing more to do.
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
//Next frame:
|
||||
currentFrame++;
|
||||
|
||||
if (Direction.NO_DIRECTION == d || Direction.RIGHT == d) {
|
||||
if (currentFrame >= getNumFrames()) {
|
||||
//Got to the end of the animation:
|
||||
resetFrameNumber();
|
||||
endAnimation = true;
|
||||
}
|
||||
} else if (Direction.LEFT == d) {
|
||||
if (currentFrame >= getNumFrames() * 2) {
|
||||
//Got to the end of animation.
|
||||
resetFrameNumber();
|
||||
endAnimation = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Terminate looping if necessary:
|
||||
if (endAnimation && Looping.ONCE == l) {
|
||||
setLoopingMode(Looping.NONE);
|
||||
}
|
||||
|
||||
//Return new frame number:
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the sprite at the specified coordinates.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @param coordinates a <code>Point</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public synchronized boolean renderSprite(Graphics g, Point coordinates) {
|
||||
if (!isInitialized()) {
|
||||
//Sprite not initialized. Cannot draw.
|
||||
return false;
|
||||
}
|
||||
|
||||
//Draw stuff:
|
||||
getAnimation().drawTile(g, coordinates, getCurrentFrame());
|
||||
|
||||
//Get next frame number:
|
||||
//nextFrameNumber();
|
||||
|
||||
//Done:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import javax.print.attribute.EnumSyntax;
|
||||
|
||||
/**
|
||||
* Class Direction: an enumeration for the directions a sprite could
|
||||
* be facing.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 12, 2004) - Created the Direction class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 12, 2004
|
||||
*/
|
||||
public class Direction extends EnumSyntax {
|
||||
|
||||
/**
|
||||
* Represents the direction of heading nowhere. Neither left nor
|
||||
* right. This one will be used by the immobile lemmings, like the
|
||||
* blocker.
|
||||
*/
|
||||
public static final Direction NO_DIRECTION = new Direction(0);
|
||||
|
||||
/**
|
||||
* Represents the right-to-left motion direction.
|
||||
*/
|
||||
public static final Direction LEFT = new Direction(1);
|
||||
|
||||
/**
|
||||
* Represents the left-to-right motion direction.
|
||||
*/
|
||||
public static final Direction RIGHT = new Direction(2);
|
||||
|
||||
// /**
|
||||
// * Part of the EnumSyntax implementation.
|
||||
// */
|
||||
// private static final String[] stringTable = {
|
||||
// "No Direction",
|
||||
// "Left",
|
||||
// "Right"};
|
||||
|
||||
// /**
|
||||
// * Part of the EnumSyntax implementation.
|
||||
// */
|
||||
// private static final Direction[] enumValueTable = {
|
||||
// NO_DIRECTION,
|
||||
// LEFT,
|
||||
// RIGHT
|
||||
// };
|
||||
|
||||
/**
|
||||
* Creates a new <code>Direction</code> instance.
|
||||
*
|
||||
* @param value an <code>int</code> value
|
||||
*/
|
||||
private Direction(int value) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
|
||||
/**
|
||||
* Class ImageLoader: The image loader class provides the
|
||||
* functionality for loading images from the hard drive or the web
|
||||
* into BufferedImages.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Feb. 06, 2004) - Created the ImageLoader class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Feb. 06, 2004
|
||||
*/
|
||||
public final class ImageLoader {
|
||||
|
||||
/**
|
||||
* Contains the location for all of the system images.
|
||||
*/
|
||||
public static final String IMAGE_LOCATION = "images/";
|
||||
|
||||
/**
|
||||
* Implement this as a singleton.
|
||||
*/
|
||||
private static ImageLoader instance;
|
||||
|
||||
/**
|
||||
* The default graphics configuration for the current client.
|
||||
*/
|
||||
private GraphicsConfiguration config;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImageLoader</code> instance.
|
||||
*/
|
||||
private ImageLoader() {
|
||||
config = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*
|
||||
* @return an <code>ImageLoader</code> value
|
||||
*/
|
||||
public static ImageLoader getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ImageLoader();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the graphics configuration used.
|
||||
*
|
||||
* @return a <code>GraphicsConfiguration</code> value
|
||||
*/
|
||||
public GraphicsConfiguration getImageConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the image from the specified URL. Returns an accelerated
|
||||
* version of the image, ready to be rendered.
|
||||
*
|
||||
* @param path an <code>URL</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage loadImage(final URL path) {
|
||||
if (path == null) {
|
||||
System.err.println("ImageLoader.loadImage - received NULL path... "
|
||||
+ "Loading aborted");
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedImage result = javax.imageio.ImageIO.read(path);
|
||||
|
||||
if (result == null) {
|
||||
System.err.println("ImageLoader.loadImage - could not read image \""
|
||||
+ path.getPath() + "\"...");
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
return accelerateImage(result);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("ImageLoader.loadImage - Could not load image \""
|
||||
+ path.getPath() + "\"...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the image from the file specified.
|
||||
*
|
||||
* @param src a <code>File</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage loadImage(final File src) {
|
||||
if (src == null) {
|
||||
System.err.println("ImageLoader.loadImage - received NULL file... "
|
||||
+ "Loading aborted.");
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!src.exists()) {
|
||||
System.err.println("ImageLoader.loadImage - Could not find the file "
|
||||
+ "specified... Loading aborted.");
|
||||
System.err.println(src.getAbsolutePath());
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedImage result = javax.imageio.ImageIO.read(src);
|
||||
|
||||
if (result == null) {
|
||||
System.err.println("ImageLoader.loadImage - could not read image \""
|
||||
+ src.getAbsolutePath() + "\"...");
|
||||
System.err.flush();
|
||||
return null;
|
||||
}
|
||||
|
||||
return accelerateImage(result);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("ImageLoader.loadImage - Could not load image \""
|
||||
+ src.getAbsolutePath() + "\"...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a local image for instance, for insertion into the graphics
|
||||
* pane.
|
||||
*
|
||||
* @param imagePath a <code>String</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage loadLocalImage(final String imagePath) {
|
||||
// return loadImage(this.getClass().getResource(imagePath));
|
||||
return loadImage(new File(imagePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a system image from the standard location.
|
||||
*
|
||||
* @param imageName a <code>String</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage loadSystemImage(final String imageName) {
|
||||
return loadLocalImage(IMAGE_LOCATION + imageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a hardware-accelerated image if possible.
|
||||
*
|
||||
* @param src a <code>BufferedImage</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
private BufferedImage accelerateImage(final BufferedImage src) {
|
||||
BufferedImage result
|
||||
= config.createCompatibleImage(src.getWidth(),
|
||||
src.getHeight(),
|
||||
src.getColorModel().getTransparency());
|
||||
|
||||
Graphics2D g2d = result.createGraphics();
|
||||
g2d.setComposite(AlphaComposite.Src);
|
||||
g2d.drawImage(src, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hardware-accelerated blank image of the specified size.
|
||||
*
|
||||
* @param width an <code>int</code> value
|
||||
* @param height an <code>int</code> value
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage createBlankImage(int width, int height) {
|
||||
BufferedImage result
|
||||
= config.createCompatibleImage(width, height,
|
||||
java.awt.Transparency.BITMASK);
|
||||
|
||||
Graphics2D g2D = (Graphics2D) result.createGraphics();
|
||||
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
|
||||
Rectangle rect = new Rectangle(0, 0, width, height);
|
||||
g2D.fill(rect);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Image;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Toolkit;
|
||||
//import java.awt.image.Raster;
|
||||
//import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.MemoryImageSource;
|
||||
|
||||
/**
|
||||
* Class ImageUtilities: contains certain utility functions that can
|
||||
* be useful for various image manipulating classes.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 12, 2004) - Created the ImageUtilities class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 12, 2004
|
||||
*/
|
||||
public class ImageUtilities {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
//private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Singleton Implementation.
|
||||
*/
|
||||
private static ImageUtilities instance;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImageUtilities</code> instance.
|
||||
*/
|
||||
private ImageUtilities() { }
|
||||
|
||||
/**
|
||||
* Singleton Implementation.
|
||||
*
|
||||
* @return an <code>ImageUtilities</code> value
|
||||
*/
|
||||
public static ImageUtilities getInstance() {
|
||||
if (instance == null) { instance = new ImageUtilities(); }
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color of the pixel at the specified coordinates of the image.
|
||||
*
|
||||
* @param image a <code>BufferedImage</code> value
|
||||
* @param x an <code>int</code> value
|
||||
* @param y an <code>int</code> value
|
||||
* @return a <code>Color</code> value
|
||||
*/
|
||||
public Color getPixel(final BufferedImage image, int x, int y) {
|
||||
/*
|
||||
Raster imageRaster = image.getRaster();
|
||||
ColorSpace imageSpace = image.getColorModel().getColorSpace();
|
||||
float[] components = new float[imageSpace.getNumComponents() + 1];
|
||||
Color result = null;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("ImageUtilities.getPixel - getting @ (" + x + ", "
|
||||
+ y + ")");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
components = imageRaster.getPixel(x, y, components);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("Color components:");
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
System.out.println("\tc[" + i + "] = " + components[i]);
|
||||
}
|
||||
}
|
||||
|
||||
result = new Color((int) components[0],
|
||||
(int) components[1],
|
||||
(int) components[2]);
|
||||
|
||||
return result;
|
||||
*/
|
||||
|
||||
return new Color(image.getRGB(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an invisible cursor.
|
||||
*
|
||||
* @return a <code>Cursor</code> value
|
||||
*/
|
||||
public Cursor createBlankCursor() {
|
||||
int[] pixels = new int[16 * 16];
|
||||
Image img = Toolkit.getDefaultToolkit().createImage(
|
||||
new MemoryImageSource(16, 16, pixels, 0, 16));
|
||||
|
||||
Cursor result = Toolkit.getDefaultToolkit()
|
||||
.createCustomCursor(img, new Point(0, 0), "invisible_cursor");
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
//import java.net.URL;
|
||||
|
||||
import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.awt.image.Raster;
|
||||
//import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Class ImprovedTileSet: This tileset is essentially an improved
|
||||
* version of the regular tileset.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 01, 2004) - Created the ImprovedTileSet class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 01, 2004
|
||||
*/
|
||||
public class ImprovedTileSet extends TileSet {
|
||||
|
||||
/**
|
||||
* The list of tiles in this tileset, accelerated and ready to
|
||||
* render.
|
||||
*/
|
||||
private BufferedImage[] tiles;
|
||||
|
||||
/**
|
||||
* Describe constant <code>VERBOSE</code> here.
|
||||
*
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImprovedTileSet</code> instance.
|
||||
*/
|
||||
public ImprovedTileSet() {
|
||||
tiles = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>specialLoad</code> method here.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean specialLoad() {
|
||||
if (VERBOSE) {
|
||||
System.out.println("How can we NOT use Verbose? ");
|
||||
}
|
||||
|
||||
//Now, create the images and stuff:
|
||||
tiles = new BufferedImage[getFrameList().length];
|
||||
|
||||
for (int k = 0; k < tiles.length; k++) {
|
||||
//Fetch raster:
|
||||
Rectangle src = getFrameList()[k].getSource();
|
||||
Raster data = getFramesetImage().getData(src);
|
||||
tiles[k] = new BufferedImage(data.getWidth(),
|
||||
data.getHeight(),
|
||||
getFramesetImage().getType());
|
||||
tiles[k].setData(data.createRaster(data.getSampleModel(),
|
||||
data.getDataBuffer(), null));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all the necessary clean-up operations.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public synchronized boolean unloadTileset() {
|
||||
//Clean up the tile list if necessary:
|
||||
if (tiles != null) {
|
||||
tiles = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the tileset.
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public synchronized int getTileCount() {
|
||||
return tiles.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the largest tile in the tileset.
|
||||
*
|
||||
* @return a <code>Dimension</code> value
|
||||
*/
|
||||
public synchronized Dimension getLargestDimension() {
|
||||
Dimension result = new Dimension();
|
||||
|
||||
for (int i = 0; i < tiles.length; i++) {
|
||||
int width = tiles[i].getWidth();
|
||||
int height = tiles[i].getHeight();
|
||||
|
||||
if (width > result.width) {
|
||||
result.width = width;
|
||||
}
|
||||
|
||||
if (height > result.height) {
|
||||
result.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the tile with the specified id.
|
||||
*
|
||||
* @param tileNum an <code>int</code> value
|
||||
* @return a <code>Dimension</code> value
|
||||
*/
|
||||
public synchronized Dimension getDimension(int tileNum) {
|
||||
Dimension result = new Dimension();
|
||||
|
||||
result.width = tiles[tileNum].getWidth();
|
||||
result.height = tiles[tileNum].getHeight();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the tile with the specified number onto the graphics context
|
||||
* passed in at the specified coordinates. Note that the position of
|
||||
* the tile will depend on its anchor point, which will be put
|
||||
* exactly at the coordinates passed in.
|
||||
*
|
||||
* @param destination the context to which we want to draw the tile.
|
||||
* @param coordinates the coordinates at which we want to draw the tile.
|
||||
* @param tileNum the number of the tile we want to draw. The tiles
|
||||
* will be numbered automatically, from left to right, from top to
|
||||
* bottom, when the image file is parsed.
|
||||
*/
|
||||
public synchronized void drawTile(Graphics destination,
|
||||
Point coordinates,
|
||||
int tileNum) {
|
||||
if (DEBUG) {
|
||||
System.out.println("TileSet.drawTile - Drawing tile " + tileNum + " at ("
|
||||
+ coordinates.x + ", " + coordinates.y + ")");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
coordinates.translate(getFrameList()[tileNum].getExtent().x,
|
||||
getFrameList()[tileNum].getExtent().y);
|
||||
|
||||
//Render tile:
|
||||
destination.drawImage(tiles[tileNum],
|
||||
coordinates.x,
|
||||
coordinates.y,
|
||||
null);
|
||||
|
||||
coordinates.translate(-getFrameList()[tileNum].getExtent().x,
|
||||
-getFrameList()[tileNum].getExtent().y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import javax.print.attribute.EnumSyntax;
|
||||
|
||||
/**
|
||||
* Class Looping: an enumeration for the looping mode an animated
|
||||
* sprite could use.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 12, 2004) - Created the Looping class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 12, 2004
|
||||
*/
|
||||
public class Looping extends EnumSyntax {
|
||||
|
||||
/**
|
||||
* Represents the animation that is "stuck" in the current frame. No
|
||||
* looping takes place.
|
||||
*/
|
||||
public static final Looping NONE = new Looping(0);
|
||||
|
||||
/**
|
||||
* Represents the animation that only loops once, after which it
|
||||
* reverts to the NONE looping mode in the first frame.
|
||||
*/
|
||||
public static final Looping ONCE = new Looping(1);
|
||||
|
||||
/**
|
||||
* Represents the animation which repeats infinitely.
|
||||
*/
|
||||
public static final Looping INFINITE = new Looping(2);
|
||||
|
||||
// /**
|
||||
// * Part of the EnumSyntax implementation.
|
||||
// */
|
||||
// private static final String[] stringTable = {
|
||||
// "None",
|
||||
// "Once",
|
||||
// "Infinite"};
|
||||
|
||||
// /**
|
||||
// * Part of the EnumSyntax implementation.
|
||||
// */
|
||||
// private static final Looping[] enumValueTable = {
|
||||
// NONE,
|
||||
// ONCE,
|
||||
// INFINITE
|
||||
// };
|
||||
|
||||
/**
|
||||
* Creates a new <code>Looping</code> instance.
|
||||
*
|
||||
* @param value an <code>int</code> value
|
||||
*/
|
||||
private Looping(int value) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,996 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
import edu.gatech.cs2335.lemmings.engine.Portal;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.PrettySprite;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.ExploderJob;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.gui.LFancyLabel;
|
||||
|
||||
///////////// Zooming test Stuff
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
/**
|
||||
* The Lemmings Renderer
|
||||
*
|
||||
* Takes care of drawing stuff to screen
|
||||
*/
|
||||
public final class Renderer {
|
||||
|
||||
|
||||
////////////////////////////// Zooming Test Stuff ///////////////////////////
|
||||
|
||||
/**
|
||||
* The global Do-Zoom switch. With this turned off, everything will
|
||||
* be a bit faster, and won't use any of the affine transformation
|
||||
* crap.
|
||||
*/
|
||||
private static final boolean DO_ZOOM = true;
|
||||
|
||||
/**
|
||||
* The list of possible zoom levels.
|
||||
*/
|
||||
private static final double[] ZOOMLEVELS = {
|
||||
4.0, // Zoomed In [0]
|
||||
2.0,
|
||||
1.0, // Normal Zoom [2]
|
||||
0.5,
|
||||
0.25 // Zoomed Out [4]
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a temporary variable to save the "normal" transformation
|
||||
* matrix.
|
||||
*/
|
||||
private AffineTransform saveAT;
|
||||
|
||||
/**
|
||||
* This is where the zoom transformation will be stored.
|
||||
*/
|
||||
private AffineTransform myTransform;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Display debug information?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Display a lot of debug information?
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* Temporary Buffer to store stuff.
|
||||
*/
|
||||
private BufferedImage buffer;
|
||||
|
||||
/**
|
||||
* The bounds of the display on the frame that we will be rendering to.
|
||||
*/
|
||||
private Rectangle display;
|
||||
|
||||
/**
|
||||
* Stores the map area.
|
||||
*/
|
||||
private Dimension mapSize;
|
||||
|
||||
/**
|
||||
* Stores the current User View area.
|
||||
*/
|
||||
private Rectangle mapViewport;
|
||||
|
||||
/**
|
||||
* Stores the current Background View Area
|
||||
*/
|
||||
private Rectangle backgroundViewport;
|
||||
|
||||
/**
|
||||
* Stores the current Scaling (for use in various Resolutions/Zooms)
|
||||
*/
|
||||
//private Point scaleFactor;
|
||||
|
||||
/**
|
||||
* The rate at which we are scrolling.
|
||||
*/
|
||||
private Point scrollRate;
|
||||
|
||||
/**
|
||||
* Stores the current zoom
|
||||
*/
|
||||
private int zoomFactor;
|
||||
|
||||
/**
|
||||
* Stores the current game level
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Just a temporary point.
|
||||
*/
|
||||
private Point coords = new Point();
|
||||
|
||||
|
||||
/**
|
||||
* Just a temporary point.
|
||||
*/
|
||||
private Point coords2 = new Point();
|
||||
/**
|
||||
* The coordinates of the mouse.
|
||||
*/
|
||||
private Point mouseCoordinates = new Point();
|
||||
|
||||
/**
|
||||
* The cursor to denote the currently selected lemming.
|
||||
*/
|
||||
private AnimatedSprite cursor;
|
||||
|
||||
/**
|
||||
* Contains a pointer to the lemming currently selected.
|
||||
*/
|
||||
private Lemming selectedLemming;
|
||||
|
||||
/**
|
||||
* Now that's something new - a temporary rectangle.
|
||||
*/
|
||||
private Rectangle rcTemp = new Rectangle();
|
||||
|
||||
/**
|
||||
* Should we render water?
|
||||
*/
|
||||
private boolean renderWater = false;
|
||||
|
||||
/**
|
||||
* Position of water.
|
||||
*/
|
||||
private int waterPosition = -1;
|
||||
|
||||
/**
|
||||
* The height of water.
|
||||
*/
|
||||
private int waterHeight = -1;
|
||||
|
||||
/**
|
||||
* The width of water.
|
||||
*/
|
||||
private int waterWidth = -1;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Renderer</code> instance.
|
||||
*
|
||||
* @param l The level that we will be rendering.
|
||||
* @param disp The display bounds.
|
||||
*/
|
||||
public Renderer(Level l, Rectangle disp) {
|
||||
//////////////////////////// Zoom Stuff ///////////////////////////////////
|
||||
if (DO_ZOOM) {
|
||||
myTransform = new AffineTransform();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setLevel(l);
|
||||
setDisplay(disp);
|
||||
setMapSize(l.getMap().getSize());
|
||||
|
||||
//Set up the view anchor:
|
||||
mapViewport = new Rectangle(0, 0, display.width, display.height);
|
||||
|
||||
//Set up the background viewport:
|
||||
backgroundViewport = new Rectangle(mapViewport);
|
||||
|
||||
//Set up scaleFactor:
|
||||
/*
|
||||
scaleFactor = new Point(mapViewport.width / backgroundViewport.width,
|
||||
mapViewport.height / backgroundViewport.height);
|
||||
*/
|
||||
|
||||
setZoomFactor(ZOOMLEVELS.length / 2);
|
||||
|
||||
//Center viewport on the entrance point:
|
||||
mapViewport.translate(l.getData().getEntrancePoint().x,
|
||||
l.getData().getEntrancePoint().y);
|
||||
mapViewport.translate(-disp.width / 2, -disp.height / 2);
|
||||
clipAnchor();
|
||||
|
||||
scrollRate = new Point();
|
||||
|
||||
selectedLemming = null;
|
||||
|
||||
cursor = new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("cursor"),
|
||||
Direction.NO_DIRECTION, Looping.INFINITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the cursor.
|
||||
*/
|
||||
public void updateCursor() {
|
||||
cursor.nextFrameNumber();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the buffer to a blank image of the specified size.
|
||||
*
|
||||
* @param width an <code>int</code> value
|
||||
* @param height an <code>int</code> value
|
||||
*/
|
||||
//private void createBuffer(int width, int height) {
|
||||
// buffer = ImageLoader.getInstance().createBlankImage(width, height);
|
||||
//}
|
||||
/**
|
||||
*accessor for renderer
|
||||
*
|
||||
*@return Rectangle
|
||||
*/
|
||||
public Rectangle getMapViewPort() {
|
||||
|
||||
return mapViewport;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the view anchor is such that it goes outside the dimensions of
|
||||
* the map, clips it so it doesn't.
|
||||
*/
|
||||
private void clipAnchor() {
|
||||
//Clip right side:
|
||||
if (mapViewport.x + mapViewport.width > mapSize.width) {
|
||||
mapViewport.x = mapSize.width - mapViewport.width;
|
||||
}
|
||||
|
||||
//Clip bottom side:
|
||||
if (mapViewport.y + mapViewport.height > mapSize.height) {
|
||||
mapViewport.y = mapSize.height - mapViewport.height;
|
||||
}
|
||||
|
||||
//Clip left side:
|
||||
if (mapViewport.x < 0) {
|
||||
mapViewport.x = 0;
|
||||
}
|
||||
|
||||
//Clip top side:
|
||||
if (mapViewport.y < 0) {
|
||||
mapViewport.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of level.
|
||||
* @return value of level.
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of level.
|
||||
* @param v Value to assign to level.
|
||||
*/
|
||||
public void setLevel(Level v) {
|
||||
this.level = v;
|
||||
|
||||
buffer = level.getMap().createGameMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of display.
|
||||
* @return value of display.
|
||||
*/
|
||||
public Rectangle getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of display.
|
||||
* @param v Value to assign to display.
|
||||
*/
|
||||
public void setDisplay(Rectangle v) {
|
||||
this.display = v;
|
||||
|
||||
//Initialize the back buffer:
|
||||
// createBuffer(display.width, display.height);
|
||||
// rerenderTerrain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of mapSize.
|
||||
* @return value of mapSize.
|
||||
*/
|
||||
public Dimension getMapSize() {
|
||||
return mapSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of mapSize.
|
||||
* @param v Value to assign to mapSize.
|
||||
*/
|
||||
protected void setMapSize(Dimension v) {
|
||||
this.mapSize = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of zoomFactor.
|
||||
* @return value of zoomFactor.
|
||||
*/
|
||||
public int getZoomFactor() {
|
||||
return zoomFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of zoomFactor.
|
||||
* @param v Value to assign to zoomFactor.
|
||||
*/
|
||||
public void setZoomFactor(int v) {
|
||||
this.zoomFactor = v;
|
||||
|
||||
if (DO_ZOOM) {
|
||||
double z = ZOOMLEVELS[v];
|
||||
|
||||
//Set up affine:
|
||||
myTransform.setToScale(z, z);
|
||||
|
||||
//Update the viewports:
|
||||
zoomRectangle(mapViewport, display);
|
||||
|
||||
//Clippie:
|
||||
clipAnchor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies zooming to the rectangle.
|
||||
*
|
||||
* @param r a <code>Rectangle</code> value
|
||||
* @param ref a <code>Rectangle</code> value
|
||||
*/
|
||||
private void zoomRectangle(Rectangle r, Rectangle ref) {
|
||||
double z = ZOOMLEVELS[zoomFactor];
|
||||
|
||||
//Calculate center point of the rectangle:
|
||||
int x = r.x + (r.width / 2);
|
||||
int y = r.y + (r.height / 2);
|
||||
|
||||
//Resize rectangle:
|
||||
r.width = (int) (ref.width / z);
|
||||
r.height = (int) (ref.height / z);
|
||||
|
||||
//Recenter viewport:
|
||||
r.x = x - (r.width / 2);
|
||||
r.y = y - (r.height / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies unzooming to the rectangle.
|
||||
*
|
||||
* @param r a <code>Rectangle</code> value
|
||||
* @param ref a <code>Rectangle</code> value
|
||||
*/
|
||||
private void unzoomRectangle(Rectangle r, Rectangle ref) {
|
||||
double z = ZOOMLEVELS[zoomFactor];
|
||||
|
||||
//Calculate center point of the rectangle:
|
||||
int x = r.x + (r.width / 2);
|
||||
int y = r.y + (r.height / 2);
|
||||
|
||||
//Resize rectangle:
|
||||
r.width = (int) (ref.width * z);
|
||||
r.height = (int) (ref.height * z);
|
||||
|
||||
//Recenter viewport:
|
||||
r.x = x - (r.width / 2);
|
||||
r.y = y - (r.height / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms in.
|
||||
*/
|
||||
public void zoomIn() {
|
||||
int z = getZoomFactor() - 1;
|
||||
|
||||
if (z >= 0) {
|
||||
setZoomFactor(z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms out.
|
||||
*/
|
||||
public void zoomOut() {
|
||||
int z = getZoomFactor() + 1;
|
||||
|
||||
if (z < ZOOMLEVELS.length) {
|
||||
setZoomFactor(z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll the map by offset in the x-y directions.
|
||||
* @param offset the amount to offset
|
||||
*/
|
||||
public void scroll(Point offset) {
|
||||
scrollRate.x = offset.x;
|
||||
scrollRate.y = offset.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getScrollRate</code> method here.
|
||||
*
|
||||
* @return a <code>Point</code> value
|
||||
*/
|
||||
public Point getScrollRate() {
|
||||
return new Point(scrollRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getMouseCoordinates</code> method here.
|
||||
*
|
||||
* @return a <code>Point</code> value
|
||||
*/
|
||||
public Point getMouseCoordinates() {
|
||||
return new Point(mouseCoordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setMouseCoordinates</code> method here.
|
||||
*
|
||||
* @param coord a <code>Point</code> value
|
||||
*/
|
||||
public synchronized void setMouseCoordinates(Point coord) {
|
||||
mouseCoordinates.x = coord.x;
|
||||
mouseCoordinates.y = coord.y;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("Renderer: New Mouse Coordinates: ( " + coord.x
|
||||
+ ", " + coord.y + ")");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//mouseToWorld(mouseCoordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts mouse coordinates to world coordinates.
|
||||
*
|
||||
* @param c a <code>Point</code> value
|
||||
* @return a <code>Point</code> value
|
||||
*/
|
||||
public Point mouseToWorld(Point c) {
|
||||
//Find offset from viewport:
|
||||
c.translate(-display.x, -display.y);
|
||||
|
||||
if (DO_ZOOM) {
|
||||
//Scale coordinates:
|
||||
c.x = (int) (c.x / ZOOMLEVELS[zoomFactor]);
|
||||
c.y = (int) (c.y / ZOOMLEVELS[zoomFactor]);
|
||||
}
|
||||
|
||||
//Find offset from world:
|
||||
c.translate(mapViewport.x, mapViewport.y);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts world coordinates to mouse coordinates.
|
||||
*
|
||||
* @param c a <code>Point</code> value
|
||||
* @return a <code>Point</code> value
|
||||
*/
|
||||
public Point worldToMouse(Point c) {
|
||||
//Find offset from viewport:
|
||||
c.translate(-mapViewport.x, -mapViewport.y);
|
||||
|
||||
if (DO_ZOOM) {
|
||||
//Scale coordinates:
|
||||
c.x = (int) (c.x * ZOOMLEVELS[zoomFactor]);
|
||||
c.y = (int) (c.y * ZOOMLEVELS[zoomFactor]);
|
||||
}
|
||||
|
||||
//Find offset from screen:
|
||||
c.translate(display.x, display.y);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the mouse click point to a gameWorld point
|
||||
*
|
||||
* @param c the coordinates to translate
|
||||
* @return translated coordinates
|
||||
*/
|
||||
//private Point screenToWorld(Point c) {
|
||||
// //Find offset from viewport:
|
||||
// c.translate(-display.x, -display.y);
|
||||
//
|
||||
// //Find offset from world:
|
||||
// c.translate(mapViewport.x, mapViewport.y);
|
||||
//
|
||||
// return c;
|
||||
//}
|
||||
|
||||
/**
|
||||
* Convert the world coordinates to world point
|
||||
*
|
||||
* @param c the coordinates to translate
|
||||
* @return translated coordinates
|
||||
*/
|
||||
private Point worldToScreen(Point c) {
|
||||
//Find offset from viewport:
|
||||
c.translate(-mapViewport.x, -mapViewport.y);
|
||||
|
||||
//Find offset from screen:
|
||||
c.translate(display.x, display.y);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>renderExploder</code> method here.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
* @param target a <code>Graphics2D</code> value
|
||||
*/
|
||||
private synchronized void renderExploder(Lemming l, Graphics2D target) {
|
||||
//Render the exploder's numbers here.
|
||||
coords.x = l.getPosition().getX();
|
||||
coords.y = l.getPosition().getY();
|
||||
|
||||
coords.x -= 5;
|
||||
coords.y -= 40;
|
||||
|
||||
worldToScreen(coords);
|
||||
|
||||
String str = Integer
|
||||
.toString(((ExploderJob) l.getOccupation()).getTimeLeftOnEarth() / 5);
|
||||
|
||||
target.setColor(Color.red);
|
||||
target.setFont(LFancyLabel.DEFAULT_FONT);
|
||||
|
||||
target.drawString(str, coords.x, coords.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a given Graphics Frame
|
||||
*
|
||||
* @param target the frame to update
|
||||
* @return success
|
||||
*/
|
||||
public synchronized boolean updateFrame(Graphics target) {
|
||||
Graphics2D g = (Graphics2D) target;
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Renderer: Rendering ...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Do scrolling:
|
||||
if (scrollRate.x != 0 || scrollRate.y != 0) {
|
||||
if (DO_ZOOM) {
|
||||
mapViewport.translate((int) (scrollRate.x / ZOOMLEVELS[zoomFactor]),
|
||||
(int) (scrollRate.y / ZOOMLEVELS[zoomFactor]));
|
||||
} else {
|
||||
mapViewport.translate(scrollRate.x, scrollRate.y);
|
||||
}
|
||||
|
||||
//Make sure we don't scroll out of the map:
|
||||
clipAnchor();
|
||||
}
|
||||
|
||||
//Set up clipping:
|
||||
g.setClip(display);
|
||||
|
||||
//Find coordinates:
|
||||
coords.x = 0;
|
||||
coords.y = 0;
|
||||
worldToScreen(coords);
|
||||
|
||||
//Render background:
|
||||
g.drawImage(level.getMap().getBackground(), null, display.x, display.y);
|
||||
|
||||
////////////////////////// Zoom ///////////////////////////////////////////
|
||||
saveAT = g.getTransform();
|
||||
g.setTransform(myTransform);
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Blit Terrain:
|
||||
g.drawImage(buffer, null, coords.x, coords.y);
|
||||
|
||||
//Render portals:
|
||||
List ports = level.getLevelPortals();
|
||||
for (int i = 0; i < ports.size(); i++) {
|
||||
Portal p = (Portal) ports.get(i);
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Renderer: Rendering portal...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Render portal:
|
||||
coords.x = p.getPhysics().getPosition().getX();
|
||||
coords.y = p.getPhysics().getPosition().getY();
|
||||
|
||||
//Get screen coordinates of portal:
|
||||
worldToScreen(coords);
|
||||
|
||||
p.getAnimation().renderSprite(g, coords);
|
||||
}
|
||||
|
||||
//Render Lemmings:
|
||||
List lems = level.getActiveLemmings();
|
||||
selectedLemming = null;
|
||||
for (int i = 0; i < lems.size(); i++) {
|
||||
Lemming l = (Lemming) lems.get(i);
|
||||
|
||||
//Get world coordinates of lemming:
|
||||
coords.x = l.getPosition().getX();
|
||||
coords.y = l.getPosition().getY();
|
||||
|
||||
if (!mapViewport.contains(coords)) {
|
||||
//Lemming is outside the screen. Don't bother.
|
||||
continue;
|
||||
}
|
||||
|
||||
//Get screen coordinates of lemming:
|
||||
worldToScreen(coords);
|
||||
|
||||
if (selectedLemming == null) {
|
||||
checkLemmingSelected(l, g);
|
||||
|
||||
if (selectedLemming != null) {
|
||||
cursor.renderSprite(g, coords);
|
||||
}
|
||||
}
|
||||
|
||||
//Render lemming:
|
||||
l.getOccupation().getAnimation().renderSprite(g, coords);
|
||||
|
||||
if (l.getOccupation() instanceof ExploderJob) {
|
||||
renderExploder(l, g);
|
||||
}
|
||||
}
|
||||
|
||||
//Render pretty sprites:
|
||||
List pl = level.getPrettySprites();
|
||||
for (int i = 0; i < pl.size(); i++) {
|
||||
PrettySprite ps = (PrettySprite) pl.get(i);
|
||||
|
||||
//Get world coordinates of sprite:
|
||||
coords.x = ps.getPosition().getX();
|
||||
coords.y = ps.getPosition().getY();
|
||||
|
||||
if (!mapViewport.contains(coords)) {
|
||||
//Sprite is outside the screen. Don't bother.
|
||||
continue;
|
||||
}
|
||||
|
||||
//Get screen coordinates of sprite:
|
||||
worldToScreen(coords);
|
||||
|
||||
//Render sprite:
|
||||
ps.getAnimation().renderSprite(g, coords);
|
||||
}
|
||||
|
||||
//Render water if necessary:
|
||||
if (renderWater) {
|
||||
renderWater(g);
|
||||
}
|
||||
////////////////////////// Zoom ///////////////////////////////////////////
|
||||
g.setTransform(saveAT);
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Unclip:
|
||||
g.setClip(null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>renderWater</code> method here.
|
||||
*
|
||||
* @param g a <code>Graphics2D</code> value
|
||||
*/
|
||||
private void renderWater(Graphics2D g) {
|
||||
coords.x = 0;
|
||||
coords.y = waterPosition;
|
||||
|
||||
if (coords.y <= mapViewport.y + mapViewport.height) {
|
||||
//Some water's on screen:
|
||||
int x = mapViewport.x + mapViewport.width;
|
||||
int y = mapViewport.y + mapViewport.height;
|
||||
int yInc = 2 * waterHeight / 3;
|
||||
int xInit = -waterWidth / 2;
|
||||
int counter = 0;
|
||||
int mapWidth = level.getMap().getMap().getWidth();
|
||||
int mapHeight = level.getMap().getMap().getHeight();
|
||||
|
||||
AnimatedSprite was = level.getMap().getWaterAnimation();
|
||||
|
||||
//The y coordinate now contains where we should put top layer of water.
|
||||
for (coords.y = waterPosition;
|
||||
coords.y <= y && coords.y <= mapHeight;
|
||||
coords.y += yInc) {
|
||||
//The above is iterating through rows of water.
|
||||
coords.x = mapViewport.x;
|
||||
|
||||
if (counter % 2 == 1) {
|
||||
coords.x += xInit;
|
||||
}
|
||||
|
||||
for (; coords.x <= x && coords.x <= mapWidth; coords.x += waterWidth) {
|
||||
//This is iterating through columns of water.
|
||||
coords2.x = coords.x;
|
||||
coords2.y = coords.y;
|
||||
|
||||
worldToScreen(coords2);
|
||||
|
||||
was.renderSprite(g, coords2);
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Once the level has been set, calculates how water needs to be drawn.
|
||||
*/
|
||||
public void calculateWaterLevel() {
|
||||
if (VERBOSE) {
|
||||
System.out.println("Renderer: Calculating Water Level...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
int wl = level.getData().getWaterLevel();
|
||||
|
||||
if (wl < 0) {
|
||||
renderWater = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\tGot water height - " + wl);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
renderWater = true;
|
||||
|
||||
//Calculate top-most world position of water.
|
||||
waterPosition = level.getMap().getMap().getHeight() - wl;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\tGot water position - " + waterPosition);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Calculate water dimensions:
|
||||
waterHeight
|
||||
= level.getMap().getWaterAnimation().getAnimation().getExtent(0).height
|
||||
+ level.getMap().getWaterAnimation().getAnimation().getExtent(0).y;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\tGot unit height - " + waterHeight);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
waterWidth
|
||||
= level.getMap().getWaterAnimation().getAnimation().getExtent(0).width
|
||||
+ level.getMap().getWaterAnimation().getAnimation().getExtent(0).x;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\tGot unit width - " + waterWidth);
|
||||
System.out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the lemming is selected.
|
||||
*
|
||||
* @param l a <code>Lemming</code> value
|
||||
* @param g a <code>Point</code> value
|
||||
*/
|
||||
private void checkLemmingSelected(Lemming l, Graphics2D g) {
|
||||
Rectangle r = null;
|
||||
|
||||
r = l.getOccupation().getAnimation().getAnimation()
|
||||
.getExtent(l.getOccupation().getAnimation().getCurrentFrame());
|
||||
|
||||
rcTemp.x = r.x;
|
||||
rcTemp.y = r.y;
|
||||
rcTemp.width = r.width;
|
||||
rcTemp.height = r.height;
|
||||
|
||||
coords2.x = l.getPosition().getX();
|
||||
coords2.y = l.getPosition().getY();
|
||||
|
||||
worldToMouse(coords2);
|
||||
|
||||
rcTemp.translate(coords2.x, coords2.y);
|
||||
|
||||
unzoomRectangle(rcTemp, rcTemp);
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Lemming:");
|
||||
System.out.println("\tWorld: " + l.getPosition());
|
||||
System.out.println("\tScreen: " + coords2);
|
||||
System.out.println("\tUnzoomed: " + rcTemp);
|
||||
System.out.println("");
|
||||
System.out.flush();
|
||||
|
||||
g.setColor(Color.red);
|
||||
g.setTransform(saveAT);
|
||||
|
||||
g.fill(rcTemp);
|
||||
|
||||
g.setTransform(myTransform);
|
||||
}
|
||||
|
||||
if (rcTemp.contains(mouseCoordinates)) {
|
||||
selectedLemming = l;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getSelectedLemming</code> method here.
|
||||
*
|
||||
* @return a <code>Lemming</code> value
|
||||
*/
|
||||
public Lemming getSelectedLemming() {
|
||||
return selectedLemming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rerenders the terrain.
|
||||
*/
|
||||
public synchronized void rerenderTerrain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the renderer.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
sb.append("Renderer:").append("\n");
|
||||
sb.append(level.getData().toString());
|
||||
sb.append("Map Size: ").append(mapSize).append("\n");
|
||||
sb.append("Rendering to: ").append(display).append("\n");
|
||||
sb.append("Map view Anchor: ").append(mapViewport).append("\n");
|
||||
sb.append("Zoom: ").append(zoomFactor).append("\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the GUI and show it. For thread safety,
|
||||
* this method should be invoked from the
|
||||
* event-dispatching thread.
|
||||
*/
|
||||
private static void createAndShowGUI() {
|
||||
//Make sure we have nice window decorations.
|
||||
//javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
|
||||
|
||||
//Create and set up the window.
|
||||
final javax.swing.JFrame frame
|
||||
= new javax.swing
|
||||
.JFrame("Renderer Test",
|
||||
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration());
|
||||
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
//Display the window.
|
||||
frame.setSize(800, 600);
|
||||
frame.setVisible(true);
|
||||
|
||||
//Initialize double buffering:
|
||||
//frame.createBufferStrategy(2);
|
||||
|
||||
//Create and set up the content pane.
|
||||
Level l = edu.gatech.cs2335.lemmings.file.LevelReader.getInstance()
|
||||
.loadLevel("test_level");
|
||||
final Renderer r = new Renderer(l, new Rectangle(0, 20, 400, 400));
|
||||
|
||||
javax.swing.JPanel newContentPane
|
||||
= new javax.swing.JPanel(new java.awt.BorderLayout());
|
||||
//newContentPane.add(tst, java.awt.BorderLayout.CENTER);
|
||||
newContentPane.setOpaque(true); //content panes must be opaque
|
||||
frame.setContentPane(newContentPane);
|
||||
|
||||
//Initialize double buffering:
|
||||
frame.createBufferStrategy(2);
|
||||
final java.awt.image.BufferStrategy strategy = frame.getBufferStrategy();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
long lastFrame = System.currentTimeMillis();
|
||||
|
||||
while (true) {
|
||||
int width = frame.getWidth();
|
||||
int height = frame.getHeight();
|
||||
|
||||
//Get the graphics context from buffer strategy:
|
||||
Graphics g = strategy.getDrawGraphics();
|
||||
|
||||
//Do the drawing:
|
||||
g.setColor(java.awt.Color.gray);
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
|
||||
r.updateFrame(g);
|
||||
|
||||
//Flip buffer:
|
||||
strategy.show();
|
||||
|
||||
//Cap the frame rate:
|
||||
lastFrame += 20; //Frame rate
|
||||
try {
|
||||
Thread.sleep(Math.max(0,
|
||||
lastFrame - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
).start();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*@param args args
|
||||
*/
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
//Schedule a job for the event-dispatching thread:
|
||||
//creating and showing this application's GUI.
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
createAndShowGUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,645 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
//import java.net.URL;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* The tileset class simplifies loading bitmap files that contain
|
||||
* several tiles. It is a fairly flexible class, but it does impose
|
||||
* certain restrictions on the way the file is organized. First of
|
||||
* all, there needs to be a set of control pixels in the upper-right
|
||||
* corner of the image. The control pixels start at the coordinate
|
||||
* (width-1, 0) and go down from there in the following order:
|
||||
* transparency pixel, empty-region pixel, outside anchor pixel,
|
||||
* used-region pixel, inside anchor pixel; five in all. The
|
||||
* transparency pixel is used for color-keying, and all the pixels of
|
||||
* that color in the image will be made transparent. The outside and
|
||||
* inside anchor pixels do the same thing currently, and are used to
|
||||
* denote the image anchor. When the tile is blitted using the
|
||||
* putTile method, the anchor has the coordinates passed in to the
|
||||
* method, and the rest of the image is drawn relatively to it. In
|
||||
* other words, suppose we blit to rectangular tiles using the same
|
||||
* target coordinates. One of the tiles has its anchor in the
|
||||
* top-left corner, and the other - in the center. Then the center of
|
||||
* the latter tile will coincide with the top-left corner of the
|
||||
* former tile. The empty-region and used-region pixels are used to
|
||||
* denote where the useful areas of the tile are, and which ones can
|
||||
* be discarded. The reason for that is that the tiles in the tileset
|
||||
* file have to be arranged in a table. In other words, all tiles in
|
||||
* one column have to be the same width, and all the tiles in one row
|
||||
* have to be the same height. That is not to say, however, that the
|
||||
* width and the height have to be the equal, or that the tiles in
|
||||
* different rows have to have the same height, and in different
|
||||
* columns - the same width. Suppose a game has only two tiles. We
|
||||
* can arrange them in a column. One of the tiles is square, and the
|
||||
* other - a very thin rectangle. Then, we could mark the whole first
|
||||
* tile as used, and for the second tile - only the space that is
|
||||
* actually used up. Since we arranged the tiles in a column, the
|
||||
* widths of the tiles have to be the same. However, we can mark the
|
||||
* unused areas of the thin tile with the unused-area pixel color,
|
||||
* and they will be discarded when blitting.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 11, 2004) - Created the TileSet class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 11, 2004
|
||||
*/
|
||||
public class TileSet {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
protected static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* Show lots of debug output?
|
||||
*/
|
||||
protected static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The list of informations pertaining to the frames in this set.
|
||||
*/
|
||||
private FrameInformation[] frameList;
|
||||
|
||||
/**
|
||||
* The name of the file we want to load the image from, in case it
|
||||
* needs to be reloaded somehow.
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* The image, where the whole tileset is stored.
|
||||
*/
|
||||
private BufferedImage framesetImage;
|
||||
|
||||
/**
|
||||
* Creates a new <code>TileSet</code> instance.
|
||||
*/
|
||||
public TileSet() {
|
||||
frameList = null;
|
||||
fileName = null;
|
||||
framesetImage = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the tileset from a file. Returns true upon success or false
|
||||
* upon failure.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean loadTileset(String name) {
|
||||
//Dimensions of the image
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
//Number of tiles horizontally and vertically
|
||||
// int xCount = 0;
|
||||
// int yCount = 0;
|
||||
//Lists of coordinates for the tile bounds
|
||||
List horizontalTileBounds = new Vector();
|
||||
List verticalTileBounds = new Vector();
|
||||
//Color control
|
||||
Color transparentColor = null;
|
||||
Color boundColor = null;
|
||||
Color anchorColor = null;
|
||||
Color insideColor = null;
|
||||
Color insideAnchorColor = null;
|
||||
Color testColor = null;
|
||||
//Image info
|
||||
Raster tilesetRaster = null;
|
||||
ColorSpace tilesetSpace = null;
|
||||
//Miscellaneous temporaries
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
int currentTile = 0;
|
||||
// boolean found = false;
|
||||
//First, clean up if we already have something loaded:
|
||||
if (!unloadTileset()) {
|
||||
//Could not clean up...
|
||||
return false;
|
||||
}
|
||||
//Save the name of the file:
|
||||
fileName = name;
|
||||
//Load the image from the file:
|
||||
framesetImage = ImageLoader.getInstance().loadLocalImage(name);
|
||||
if (framesetImage == null) {
|
||||
System.err.println("TileSet.loadTileset - could not load image.");
|
||||
System.err.flush();
|
||||
return false;
|
||||
}
|
||||
//Get image info:
|
||||
tilesetRaster = framesetImage.getRaster();
|
||||
tilesetSpace = framesetImage.getColorModel().getColorSpace();
|
||||
//Get image dimensions:
|
||||
width = tilesetRaster.getWidth();
|
||||
height = tilesetRaster.getHeight();
|
||||
//Define color control variables:
|
||||
transparentColor = ImageUtilities.getInstance()
|
||||
.getPixel(framesetImage, width - 1, 0);
|
||||
boundColor = ImageUtilities.getInstance()
|
||||
.getPixel(framesetImage, width - 1, 1);
|
||||
anchorColor = ImageUtilities.getInstance()
|
||||
.getPixel(framesetImage, width - 1, 2);
|
||||
insideColor = ImageUtilities.getInstance()
|
||||
.getPixel(framesetImage, width - 1, 3);
|
||||
insideAnchorColor = ImageUtilities.getInstance()
|
||||
.getPixel(framesetImage, width - 1, 4);
|
||||
testColor = Color.black;
|
||||
//Find the coordinates of the vertical tile bounds:
|
||||
for (x = 0; x < width; x++) {
|
||||
testColor = ImageUtilities.getInstance().getPixel(framesetImage, x, 0);
|
||||
|
||||
if (testColor.equals(transparentColor)) {
|
||||
//Add the coordinate to the list:
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSet: Adding x coordinate - " + x);
|
||||
System.out.flush();
|
||||
}
|
||||
verticalTileBounds.add(new Integer(x));
|
||||
}
|
||||
}
|
||||
//Find the coordinates of the horizontal tile bounds:
|
||||
for (y = 0; y < height; y++) {
|
||||
testColor = ImageUtilities.getInstance().getPixel(framesetImage, 0, y);
|
||||
if (testColor.equals(transparentColor)) {
|
||||
//Add the coordinate to the list:
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSet: Adding y coordinate - " + y);
|
||||
System.out.flush();
|
||||
}
|
||||
horizontalTileBounds.add(new Integer(y));
|
||||
}
|
||||
}
|
||||
//Allocate the list of frame infos:
|
||||
frameList = new FrameInformation[(verticalTileBounds.size() - 1)
|
||||
* (horizontalTileBounds.size() - 1)];
|
||||
//Scan the tiles in:
|
||||
for (row = 0; row < horizontalTileBounds.size() - 1; row++) {
|
||||
for (col = 0; col < verticalTileBounds.size() - 1; col++) {
|
||||
currentTile = col + row * (verticalTileBounds.size() - 1);
|
||||
if (DEBUG) {
|
||||
System.out.println("TileSet: Processing tile (" + col + ", "
|
||||
+ row + ") - #" + currentTile);
|
||||
System.out.flush();
|
||||
}
|
||||
frameList[currentTile] = new FrameInformation();
|
||||
//Determine the anchor point:
|
||||
frameList[currentTile].getAnchor().x
|
||||
= findFirstOccurrence(((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col + 1))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
anchorColor, insideAnchorColor, false);
|
||||
|
||||
frameList[currentTile].getAnchor().y
|
||||
= findFirstOccurrence(((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row + 1))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
anchorColor, insideAnchorColor, true);
|
||||
//Find the first tile pixel:
|
||||
frameList[currentTile].getSource().x
|
||||
= findFirstOccurrence(((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col + 1))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
insideColor, insideAnchorColor, false);
|
||||
|
||||
frameList[currentTile].getSource().y
|
||||
= findFirstOccurrence(((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row + 1))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
insideColor, insideAnchorColor, true);
|
||||
if (frameList[currentTile].getSource().x == 0) {
|
||||
//Could not find. Use default:
|
||||
frameList[currentTile].getSource().x
|
||||
= ((Integer) verticalTileBounds.get(col)).intValue() + 1;
|
||||
}
|
||||
if (frameList[currentTile].getSource().y == 0) {
|
||||
//Could not find. Use default:
|
||||
frameList[currentTile].getSource().y
|
||||
= ((Integer) horizontalTileBounds.get(row)).intValue() + 1;
|
||||
}
|
||||
|
||||
//Find the last tile pixel:
|
||||
frameList[currentTile].getSource().width
|
||||
= findLastOccurrence(((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col + 1))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
insideColor, insideAnchorColor, false)
|
||||
- frameList[currentTile].getSource().x + 1;
|
||||
|
||||
frameList[currentTile].getSource().height
|
||||
= findLastOccurrence(((Integer) horizontalTileBounds.get(row))
|
||||
.intValue(),
|
||||
((Integer) horizontalTileBounds.get(row + 1))
|
||||
.intValue(),
|
||||
((Integer) verticalTileBounds.get(col))
|
||||
.intValue(),
|
||||
insideColor, insideAnchorColor, true)
|
||||
- frameList[currentTile].getSource().y + 1;
|
||||
|
||||
if (frameList[currentTile].getSource().width <= 0) {
|
||||
//Could not find. Use default:
|
||||
frameList[currentTile].getSource().width
|
||||
= ((Integer) verticalTileBounds.get(col + 1)).intValue()
|
||||
- frameList[currentTile].getSource().x;
|
||||
}
|
||||
if (frameList[currentTile].getSource().height <= 0) {
|
||||
//Could not find. Use default:
|
||||
frameList[currentTile].getSource().height
|
||||
= ((Integer) horizontalTileBounds.get(row + 1)).intValue()
|
||||
- frameList[currentTile].getSource().y;
|
||||
}
|
||||
|
||||
//Calculate tile extent:
|
||||
frameList[currentTile]
|
||||
.setExtent(new Rectangle(frameList[currentTile].getSource()));
|
||||
frameList[currentTile].getExtent()
|
||||
.translate(-frameList[currentTile].getAnchor().x,
|
||||
-frameList[currentTile].getAnchor().y);
|
||||
}
|
||||
}
|
||||
|
||||
specialLoad();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>specialLoad</code> method here.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean specialLoad() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getFrameList</code> method here.
|
||||
*
|
||||
* @return a <code>FrameInformation[]</code> value
|
||||
*/
|
||||
protected FrameInformation[] getFrameList() {
|
||||
return frameList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getFramesetImage</code> method here.
|
||||
*
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
protected BufferedImage getFramesetImage() {
|
||||
return framesetImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the coordinate of the first occurrence of one of the test colors.
|
||||
*
|
||||
* @param lowBound an <code>int</code> value
|
||||
* @param highBound an <code>int</code> value
|
||||
* @param coordinate an <code>int</code> value
|
||||
* @param c1 a <code>Color</code> value
|
||||
* @param c2 a <code>Color</code> value
|
||||
* @param vertical a <code>boolean</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int findFirstOccurrence(int lowBound, int highBound,
|
||||
int coordinate,
|
||||
Color c1, Color c2, boolean vertical) {
|
||||
Color testColor = null;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
for (int i = lowBound + 1; i < highBound; i++) {
|
||||
if (vertical) {
|
||||
x = coordinate;
|
||||
y = i;
|
||||
} else {
|
||||
x = i;
|
||||
y = coordinate;
|
||||
}
|
||||
|
||||
testColor = ImageUtilities.getInstance().getPixel(framesetImage, x, y);
|
||||
if (testColor.equals(c1) || testColor.equals(c2)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the coordinate of the last occurrence of one of the test colors.
|
||||
*
|
||||
* @param lowBound an <code>int</code> value
|
||||
* @param highBound an <code>int</code> value
|
||||
* @param coordinate an <code>int</code> value
|
||||
* @param c1 a <code>Color</code> value
|
||||
* @param c2 a <code>Color</code> value
|
||||
* @param vertical a <code>boolean</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int findLastOccurrence(int lowBound, int highBound,
|
||||
int coordinate,
|
||||
Color c1, Color c2, boolean vertical) {
|
||||
Color testColor = null;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
for (int i = highBound - 1; i > lowBound; i--) {
|
||||
if (vertical) {
|
||||
x = coordinate;
|
||||
y = i;
|
||||
} else {
|
||||
x = i;
|
||||
y = coordinate;
|
||||
}
|
||||
|
||||
testColor = ImageUtilities.getInstance().getPixel(framesetImage, x, y);
|
||||
if (testColor.equals(c1) || testColor.equals(c2)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the surface was lost, reloads it, but does not reparse the file.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean reloadTileset() {
|
||||
//Load the image from the file:
|
||||
framesetImage = ImageLoader.getInstance().loadLocalImage(getFileName());
|
||||
if (framesetImage == null) {
|
||||
System.err.println("TileSet.reloadTileset - could not load image");
|
||||
System.err.flush();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all the necessary clean-up operations.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean unloadTileset() {
|
||||
//Clean up the tile list if necessary:
|
||||
if (frameList != null) {
|
||||
frameList = null;
|
||||
fileName = null;
|
||||
framesetImage = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the tileset.
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public int getTileCount() {
|
||||
return frameList.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image on which the tileset resides.
|
||||
* @return a <code>BufferedImage</code> value
|
||||
*/
|
||||
public BufferedImage getImage() {
|
||||
return framesetImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the file containing the tileset in a string.
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the largest tile in the tileset.
|
||||
*
|
||||
* @return a <code>Dimension</code> value
|
||||
*/
|
||||
public Dimension getLargestDimension() {
|
||||
Dimension result = new Dimension();
|
||||
|
||||
for (int i = 0; i < frameList.length; i++) {
|
||||
int width = frameList[i].getSource().width;
|
||||
int height = frameList[i].getSource().height;
|
||||
|
||||
if (width > result.width) {
|
||||
result.width = width;
|
||||
}
|
||||
|
||||
if (height > result.height) {
|
||||
result.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the tile with the specified id.
|
||||
*
|
||||
* @param tileNum an <code>int</code> value
|
||||
* @return a <code>Dimension</code> value
|
||||
*/
|
||||
public Dimension getDimension(int tileNum) {
|
||||
Dimension result = new Dimension();
|
||||
|
||||
result.width = frameList[tileNum].getSource().width;
|
||||
result.height = frameList[tileNum].getSource().height;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extent of the tile with the specified id.
|
||||
*
|
||||
* @param tileNum an <code>int</code> value
|
||||
* @return a <code>Rectangle</code> value
|
||||
*/
|
||||
public Rectangle getExtent(int tileNum) {
|
||||
Rectangle result = new Rectangle(frameList[tileNum].getExtent());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the tile with the specified number onto the graphics context
|
||||
* passed in at the specified coordinates. Note that the position of
|
||||
* the tile will depend on its anchor point, which will be put
|
||||
* exactly at the coordinates passed in.
|
||||
*
|
||||
* @param destination the context to which we want to draw the tile.
|
||||
* @param coordinates the coordinates at which we want to draw the tile.
|
||||
* @param tileNum the number of the tile we want to draw. The tiles
|
||||
* will be numbered automatically, from left to right, from top to
|
||||
* bottom, when the image file is parsed.
|
||||
*/
|
||||
public void drawTile(Graphics destination, Point coordinates, int tileNum) {
|
||||
if (DEBUG) {
|
||||
System.out.println("TileSet.drawTile - Drawing tile " + tileNum + " at ("
|
||||
+ coordinates.x + ", " + coordinates.y + ")");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
frameList[tileNum].getExtent().translate(coordinates.x, coordinates.y);
|
||||
|
||||
//Fetch raster:
|
||||
Rectangle src = frameList[tileNum].getSource();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSet.drawTile: src rectangle - " + src);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
Raster data = framesetImage.getData(src);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSet.drawTile: data - " + data);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
BufferedImage temp = new BufferedImage(data.getWidth(),
|
||||
data.getHeight(),
|
||||
framesetImage.getType());
|
||||
|
||||
temp.setData(data.createRaster(data.getSampleModel(),
|
||||
data.getDataBuffer(), null));
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSet.drawTile: temp - " + temp);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Render tile:
|
||||
destination.drawImage(temp,
|
||||
frameList[tileNum].getExtent().x,
|
||||
frameList[tileNum].getExtent().y,
|
||||
null);
|
||||
frameList[tileNum].getExtent().translate(-coordinates.x, -coordinates.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information structure for one tile in the tileset.
|
||||
*/
|
||||
protected class FrameInformation {
|
||||
|
||||
/**
|
||||
* This rectangle represents the location of the frame in the
|
||||
* master frame set.
|
||||
*/
|
||||
private Rectangle source;
|
||||
|
||||
/**
|
||||
* The extent of the frame.
|
||||
*/
|
||||
private Rectangle extent;
|
||||
|
||||
/**
|
||||
* The anchor point of the frame. That is, when we say that we
|
||||
* want to render the frame at certain coordinates, the point with
|
||||
* the coordinates stored here, relative to the top-left corner of
|
||||
* the frame, will be drawn at the specified coordinates.
|
||||
*/
|
||||
private Point anchor;
|
||||
|
||||
/**
|
||||
* Creates a new <code>FrameInformation</code>
|
||||
* instance. Initializes all of the data members to contain all
|
||||
* default values (zeros).
|
||||
*/
|
||||
public FrameInformation() {
|
||||
source = new Rectangle();
|
||||
extent = new Rectangle();
|
||||
anchor = new Point();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of source.
|
||||
* @return value of source.
|
||||
*/
|
||||
public Rectangle getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of source.
|
||||
* @param v Value to assign to source.
|
||||
*/
|
||||
public void setSource(Rectangle v) {
|
||||
this.source = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of extent.
|
||||
* @return value of extent.
|
||||
*/
|
||||
public Rectangle getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of extent.
|
||||
* @param v Value to assign to extent.
|
||||
*/
|
||||
public void setExtent(Rectangle v) {
|
||||
this.extent = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of anchor.
|
||||
* @return value of anchor.
|
||||
*/
|
||||
public Point getAnchor() {
|
||||
return anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of anchor.
|
||||
* @param v Value to assign to anchor.
|
||||
*/
|
||||
public void setAnchor(Point v) {
|
||||
this.anchor = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package edu.gatech.cs2335.lemmings.graphics;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Class TileSetManager: This guy will allow us to manage tilesets in
|
||||
* such a fashion that every tileset is only loaded once.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 12, 2004) - Created the TileSetManager class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 12, 2004
|
||||
*/
|
||||
public class TileSetManager {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The name of the file, where the mappings between the resource
|
||||
* names and their paths reside.
|
||||
*/
|
||||
public static final String RESOURCE_MAP_FILE = "resources.txt";
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*/
|
||||
private static TileSetManager instance;
|
||||
|
||||
/**
|
||||
* This map will contain the tilesets currently loaded.
|
||||
*/
|
||||
private Map tileSets;
|
||||
|
||||
/**
|
||||
* This contains the mappings between the paths and the ids of the
|
||||
* resources.
|
||||
*/
|
||||
private Map paths;
|
||||
|
||||
/**
|
||||
* Creates a new <code>TileSetManager</code> instance. Since this
|
||||
* class is a songleton, there is no need for the constructor to be
|
||||
* public.
|
||||
*/
|
||||
private TileSetManager() {
|
||||
tileSets = new HashMap();
|
||||
paths = new HashMap();
|
||||
|
||||
loadPaths();
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton Implementation.
|
||||
*
|
||||
* @return a <code>TileSetManager</code> value
|
||||
*/
|
||||
public static synchronized TileSetManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new TileSetManager();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will load the mapping between the paths and ids of
|
||||
* the resources.
|
||||
*/
|
||||
private void loadPaths() {
|
||||
FileInputStream fis = null;
|
||||
Properties props = null;
|
||||
|
||||
paths.clear();
|
||||
|
||||
//Open up the resource properties file:
|
||||
try {
|
||||
fis = new FileInputStream(RESOURCE_MAP_FILE);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("TileSetManager: Could not open settings file...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
props = new Properties();
|
||||
props.load(fis);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("TileSetManager: Could not "
|
||||
+ "read the properties file...");
|
||||
System.err.println("\tIOException: " + ioe.getMessage());
|
||||
System.err.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("TileSetManager: Loaded the following properties");
|
||||
System.out.println(props);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
paths.putAll(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the resource if needed.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @param path a <code>String</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean loadResource(String name, String path) {
|
||||
String newName = name;
|
||||
String p = path;
|
||||
if (newName == null) {
|
||||
|
||||
//Check if the path is valid:
|
||||
if (p == null) { return false; }
|
||||
|
||||
File f = new File(p);
|
||||
if (!f.exists()) { return false; }
|
||||
|
||||
newName = f.getName();
|
||||
|
||||
//Check if a resource with the same name already exists:
|
||||
if (this.paths.containsKey(newName)) { return false; }
|
||||
|
||||
//If we are still here, need to add the new entry to the paths:
|
||||
this.paths.put(newName, f.getPath());
|
||||
|
||||
p = (String) this.paths.get(newName);
|
||||
|
||||
} else {
|
||||
if (this.paths.containsKey(newName)) {
|
||||
if (p != null) {
|
||||
//Need to update the entry in the table:
|
||||
File f = new File(p);
|
||||
if (!f.exists()) { return false; }
|
||||
|
||||
this.paths.remove(newName);
|
||||
this.paths.put(newName, f.getPath());
|
||||
|
||||
//Need to also check if we have already loaded the item into
|
||||
//the table:
|
||||
if (this.tileSets.containsKey(newName)) {
|
||||
this.tileSets.remove(newName);
|
||||
}
|
||||
|
||||
p = (String) this.paths.get(newName);
|
||||
|
||||
} else {
|
||||
p = "images/" + (String) this.paths.get(newName);
|
||||
this.paths.put(name, p);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (p == null) {
|
||||
return false;
|
||||
} else {
|
||||
File f = new File(p);
|
||||
if (!f.exists()) { return false; }
|
||||
|
||||
this.paths.put(newName, f.getPath());
|
||||
|
||||
p = (String) this.paths.get(newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If we are still here, the paths and everything are good. Time to
|
||||
//actually load the resource:
|
||||
TileSet set = new ImprovedTileSet();
|
||||
if (!set.loadTileset(p)) { return false; }
|
||||
|
||||
this.tileSets.put(newName, set);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the tileset is loaded and false if it is not.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean tileSetLoaded(String name) {
|
||||
return this.tileSets.containsKey(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset with the specified name. Loads it if necessary.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* @return a <code>TileSet</code> value
|
||||
*/
|
||||
public TileSet getTileSet(String name) {
|
||||
if (!tileSetLoaded(name)) {
|
||||
if (!loadResource(name, null)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return (TileSet) this.tileSets.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class GamePlayPanel: This class will display the game itself.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 28, 2004) - Created the GamePlayPanel class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 28, 2004
|
||||
*/
|
||||
public class GamePlayPanel extends LLeafComponent
|
||||
implements IMouseMotionable, IMouseWheelable, IClickable {
|
||||
|
||||
/**
|
||||
* If the cursor is within this many pixels of the edge of the map,
|
||||
* we will scroll.
|
||||
*/
|
||||
public static final int SCROLL_OFFSET = 25;
|
||||
|
||||
/**
|
||||
* The renderer used to draw stuff.
|
||||
*/
|
||||
private Renderer renderer;
|
||||
|
||||
/**
|
||||
* Just a temporary point.
|
||||
*/
|
||||
private Point coords = new Point();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>GamePlayPanel</code> instance.
|
||||
*@param r r
|
||||
*/
|
||||
public GamePlayPanel(Renderer r) {
|
||||
renderer = r;
|
||||
setBounds(r.getDisplay());
|
||||
renderer.calculateWaterLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
*Returns a renderer
|
||||
*@return renderer
|
||||
*/
|
||||
|
||||
public Renderer getRenderer() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
GamePlayPanel gpp = (GamePlayPanel) component;
|
||||
|
||||
gpp.renderer = this.renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected synchronized boolean paint(Graphics g) {
|
||||
boolean result = true;
|
||||
|
||||
//Render field:
|
||||
result = result && renderer.updateFrame(g);
|
||||
|
||||
//Render scroll fields:
|
||||
if (LApplication.VERBOSE) {
|
||||
java.awt.Rectangle t = new java.awt.Rectangle(getBounds().x,
|
||||
getBounds().y,
|
||||
getBounds().width,
|
||||
SCROLL_OFFSET);
|
||||
java.awt.Rectangle l = new java.awt.Rectangle(getBounds().x,
|
||||
getBounds().y,
|
||||
SCROLL_OFFSET,
|
||||
getBounds().height);
|
||||
java.awt.Rectangle b
|
||||
= new java.awt
|
||||
.Rectangle(getBounds().x,
|
||||
getBounds().y + getBounds().height - SCROLL_OFFSET,
|
||||
getBounds().width, SCROLL_OFFSET);
|
||||
java.awt.Rectangle r
|
||||
= new java.awt
|
||||
.Rectangle(getBounds().x + getBounds().width - SCROLL_OFFSET,
|
||||
getBounds().y, SCROLL_OFFSET, getBounds().height);
|
||||
java.awt.Graphics2D gr = (java.awt.Graphics2D) g;
|
||||
|
||||
gr.setColor(new java.awt.Color(1.0f, 0.0f, 0.0f, 0.5f));
|
||||
gr.fill(t);
|
||||
gr.fill(l);
|
||||
gr.fill(b);
|
||||
gr.fill(r);
|
||||
}
|
||||
|
||||
//Render cursor over selected lemming:
|
||||
/*
|
||||
if (selectedLemming != null) {
|
||||
coords.x = selectedLemming.getPosition().getX();
|
||||
coords.y = selectedLemming.getPosition().getY();
|
||||
renderer.worldToScreen(coords);
|
||||
|
||||
result = result && cursor.renderSprite(g, coords);
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the implementing class to be told when the mouse has moved.
|
||||
*
|
||||
* @param oldX an <code>int</code> value
|
||||
* @param oldY an <code>int</code> value
|
||||
* @param newX an <code>int</code> value
|
||||
* @param newY an <code>int</code> value
|
||||
*/
|
||||
public synchronized void processMouseMotion(int oldX, int oldY,
|
||||
int newX, int newY) {
|
||||
//PMD FIX
|
||||
int nX = newX;
|
||||
int nY = newY;
|
||||
//See if we are selecting any lemmings:
|
||||
coords.x = nX;
|
||||
coords.y = nY;
|
||||
|
||||
renderer.setMouseCoordinates(coords);
|
||||
|
||||
//selectedLemming = renderer.getLevel().findLemmingAt(coords);
|
||||
|
||||
//Process scrolling:
|
||||
coords.x = 0;
|
||||
coords.y = 0;
|
||||
nX -= getBounds().x;
|
||||
nY -= getBounds().y;
|
||||
|
||||
//Check horizontal:
|
||||
if (nX < SCROLL_OFFSET) {
|
||||
//Scroll left:
|
||||
coords.x = nX - SCROLL_OFFSET;
|
||||
//The fact that coords.x is negative here means we will be
|
||||
//scrolling left, not right.
|
||||
} else {
|
||||
int rdiff = getBounds().width - nX;
|
||||
|
||||
if (rdiff < SCROLL_OFFSET) {
|
||||
//Scroll right:
|
||||
coords.x = SCROLL_OFFSET - rdiff;
|
||||
}
|
||||
}
|
||||
|
||||
//Check vertical:
|
||||
if (nY < SCROLL_OFFSET) {
|
||||
//Scroll up:
|
||||
coords.y = nY - SCROLL_OFFSET;
|
||||
} else {
|
||||
int bdiff = getBounds().height - nY;
|
||||
|
||||
if (bdiff < SCROLL_OFFSET) {
|
||||
//Scroll down:
|
||||
coords.y = SCROLL_OFFSET - bdiff;
|
||||
}
|
||||
}
|
||||
|
||||
if (LApplication.VERBOSE) {
|
||||
System.out.println("Scrolling: (" + coords.x + ", " + coords.y + ")");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Apply scrolling:
|
||||
renderer.scroll(coords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the click of a mouse button at the specified coordinates.
|
||||
*
|
||||
* @param button an <code>int</code> value
|
||||
* @param coord a <code>Point</code> value
|
||||
*/
|
||||
public void registerMouseClick(int button, Point coord) {
|
||||
Lemming s = renderer.getSelectedLemming();
|
||||
|
||||
if (s != null) {
|
||||
renderer.getLevel().assignJobToLemming(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the mouse wheel rotation.
|
||||
*
|
||||
* @param numClicks The number of clicks the wheel was rotated. A
|
||||
* negative value means the wheel was rotated away from the user,
|
||||
* and positive means it was rotated towards the user.
|
||||
*/
|
||||
public void processMouseWheel(int numClicks) {
|
||||
if (numClicks < 0) {
|
||||
renderer.zoomIn();
|
||||
} else if (numClicks > 0) {
|
||||
renderer.zoomOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* Interface IClickable: This interface allows us to say that a certain
|
||||
* component is clickable by the mouse.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 14, 2004) - Created the IClickable interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 14, 2004
|
||||
*/
|
||||
public interface IClickable {
|
||||
|
||||
/**
|
||||
* Registers the click of a mouse button at the specified coordinates.
|
||||
*
|
||||
* @param button an <code>int</code> value
|
||||
* @param coords a <code>Point</code> value
|
||||
*/
|
||||
public void registerMouseClick(int button, Point coords);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.awt.Point;
|
||||
|
||||
/**
|
||||
* Interface IMouseMotionable: Allows the implementing classes to know
|
||||
* where the mouse is.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 10, 2004) - Created the IMouseMotionable interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 10, 2004
|
||||
*/
|
||||
public interface IMouseMotionable {
|
||||
|
||||
/**
|
||||
* Allows the implementing class to be told when the mouse has moved.
|
||||
*
|
||||
* @param oldX an <code>int</code> value
|
||||
* @param oldY an <code>int</code> value
|
||||
* @param newX an <code>int</code> value
|
||||
* @param newY an <code>int</code> value
|
||||
*/
|
||||
public void processMouseMotion(int oldX, int oldY, int newX, int newY);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
/**
|
||||
* Interface IMouseWheelable: Should be implemented by all components that
|
||||
* want to listen to mouse wheel rotations.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the IMouseWheelable interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public interface IMouseWheelable {
|
||||
|
||||
/**
|
||||
* Processes the mouse wheel rotation.
|
||||
*
|
||||
* @param numClicks The number of clicks the wheel was rotated. A
|
||||
* negative value means the wheel was rotated away from the user,
|
||||
* and positive means it was rotated towards the user.
|
||||
*/
|
||||
public void processMouseWheel(int numClicks);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
/**
|
||||
* Interface ITypable: This interface should be implemented by all
|
||||
* components that would like to be notified of the keyboard events.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the ITypable interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public interface ITypable {
|
||||
|
||||
/**
|
||||
* Processes the key type event.
|
||||
*
|
||||
* @param key The key that was typed.
|
||||
* @param modifiers The modifiers that accompanied the
|
||||
* key-type. This is a collection of ORed flags, like SHIFT, ALT,
|
||||
* etc.
|
||||
*/
|
||||
public void processKeyTyped(char key, int modifiers);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
//import java.awt.event.ActionEvent;
|
||||
//import java.awt.event.ActionListener;
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJob;
|
||||
import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobFactory;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
|
||||
/**
|
||||
* Class JobButton: This button will display the animation for the job
|
||||
* specified, and the number of that type of job available.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 07, 2004) - Created the JobButton class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 07, 2004
|
||||
*/
|
||||
public final class JobButton extends LAbstractButton {
|
||||
|
||||
/**
|
||||
* The color to use for unselected buttons.
|
||||
*/
|
||||
public static final Color UNSELECTED_COLOR
|
||||
= new Color(0.5f, 0.5f, 0.5f, 0.9f);
|
||||
|
||||
/**
|
||||
* The color to use for selected buttons.
|
||||
*/
|
||||
public static final Color SELECTED_COLOR
|
||||
= new Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
|
||||
/**
|
||||
* The level associated with this button.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* The job associated with this button.
|
||||
*/
|
||||
private LemmingJob job;
|
||||
|
||||
/**
|
||||
* The label that will contain the text for the number of jobs.
|
||||
*/
|
||||
private LLabel lblNumJobs;
|
||||
|
||||
/**
|
||||
* Set to true if this button is selected, or false if it is not.
|
||||
*/
|
||||
private boolean selected;
|
||||
|
||||
/**
|
||||
* A temporary point for the purposes of fast rendering.
|
||||
*/
|
||||
private Point ptTemp = new Point();
|
||||
|
||||
/**
|
||||
* Creates a new <code>JobButton</code> instance.
|
||||
*
|
||||
* @param l a <code>Level</code> value
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public JobButton(Level l, String id) {
|
||||
lblNumJobs = new LLabel();
|
||||
lblNumJobs.setText("");
|
||||
lblNumJobs.setShown(true);
|
||||
|
||||
setLevel(l);
|
||||
setLemmingJob(id);
|
||||
setSelected(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level associated with this button.
|
||||
*
|
||||
* @return a <code>Level</code> value
|
||||
*/
|
||||
public synchronized Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new level for this button.
|
||||
*
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public synchronized void setLevel(Level l) {
|
||||
level = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the job associated with this button.
|
||||
*
|
||||
* @return a <code>LemmingJob</code> value
|
||||
*/
|
||||
public synchronized LemmingJob getLemmingJob() {
|
||||
return job;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new job for this button.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public synchronized void setLemmingJob(String id) {
|
||||
if (id == null || id.equals("")) { return; }
|
||||
|
||||
//Set up animation
|
||||
job = LemmingJobFactory.getInstance().makeJob(id);
|
||||
|
||||
if (job == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
job.setOwner(new Lemming());
|
||||
|
||||
//Set up the new action command
|
||||
setActionCommand(id);
|
||||
|
||||
//Set up number of jobs available
|
||||
lblNumJobs.setText(Integer.toString(((GamePlayState) GameEngine
|
||||
.getInstance()
|
||||
.getCurrentState())
|
||||
.getLevel().getJobsRemaining(id)));
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the button is currently selected.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setSelected</code> method here.
|
||||
*
|
||||
* @param v a <code>boolean</code> value
|
||||
*/
|
||||
public void setSelected(boolean v) {
|
||||
selected = v;
|
||||
|
||||
if (v) {
|
||||
//We should animate the button:
|
||||
job.getAnimation().setLoopingMode(Looping.INFINITE);
|
||||
} else {
|
||||
//We should not animate the button:
|
||||
job.getAnimation().setLoopingMode(Looping.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the selection on the button.
|
||||
*/
|
||||
public void toggleSelected() {
|
||||
if (isSelected()) {
|
||||
setSelected(false);
|
||||
} else {
|
||||
setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the button.
|
||||
*/
|
||||
protected void updateButton() {
|
||||
job.getAnimation().nextFrameNumber();
|
||||
|
||||
//Set up number of jobs available
|
||||
lblNumJobs.setText(Integer.toString(((GamePlayState) GameEngine
|
||||
.getInstance()
|
||||
.getCurrentState())
|
||||
.getLevel()
|
||||
.getJobsRemaining(job.getId())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
int x = getBounds().x;
|
||||
int y = getBounds().y;
|
||||
Rectangle e = job.getAnimation().getAnimation()
|
||||
.getExtent(job.getAnimation().getCurrentFrame());
|
||||
|
||||
e = new Rectangle(e);
|
||||
lblNumJobs.setPosition(new Point(x + e.width,
|
||||
y - lblNumJobs.getBounds().height - 5));
|
||||
|
||||
e.width += 30;
|
||||
e.height += 5;
|
||||
|
||||
setBounds(e);
|
||||
getBounds().translate(x, y);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
//Render background thingie:
|
||||
if (isSelected()) {
|
||||
g.setColor(UNSELECTED_COLOR);
|
||||
} else {
|
||||
g.setColor(SELECTED_COLOR);
|
||||
}
|
||||
((java.awt.Graphics2D) g).fill(getBounds());
|
||||
|
||||
//Render the image:
|
||||
Rectangle e = job.getAnimation().getAnimation()
|
||||
.getExtent(job.getAnimation().getCurrentFrame());
|
||||
ptTemp.x = getBounds().x - e.x;
|
||||
ptTemp.y = getBounds().y - e.y;
|
||||
job.getAnimation().renderSprite(g, ptTemp);
|
||||
|
||||
//Render text:
|
||||
lblNumJobs.makeDirty();
|
||||
lblNumJobs.renderAll(g);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>toString</code> method here.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
sb.append("Job Button: \"").append(job.getId()).append("\" - {")
|
||||
.append(" numJobs: ").append(level.getJobsRemaining(job.getId()))
|
||||
.append(" bounds: ").append(getBounds());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
//import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
//import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
//import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
//import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJob;
|
||||
//import edu.gatech.cs2335.lemmings.engine.lemmingjob.LemmingJobFactory;
|
||||
//import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
|
||||
/**
|
||||
* Class JobContainer: The container for lemming job buttons. It will
|
||||
* display them and align them nicely and stuff.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 10, 2004) - Created the JobContainer class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 10, 2004
|
||||
*/
|
||||
public final class JobContainer extends LContainer implements ActionListener {
|
||||
|
||||
/**
|
||||
* Tells the container that the buttons should be arranged on the
|
||||
* x-axis.
|
||||
*/
|
||||
public static final int X_AXIS = 0;
|
||||
|
||||
/**
|
||||
* Tells the container that the buttons should be arranged on the
|
||||
* y-axis.
|
||||
*/
|
||||
public static final int Y_AXIS = 1;
|
||||
|
||||
/**
|
||||
* The number of pixels to put between the buttons.
|
||||
*/
|
||||
public static final int SPACING = 5;
|
||||
|
||||
/**
|
||||
* The level that the container is associated with.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* How should the buttons be arranged?
|
||||
*/
|
||||
private int arrangement;
|
||||
|
||||
/**
|
||||
* The event.
|
||||
*/
|
||||
private JobSelectionEvent event;
|
||||
|
||||
/**
|
||||
* The components to notify of job selection.
|
||||
*/
|
||||
private List listeners;
|
||||
|
||||
/**
|
||||
* Creates a new <code>JobContainer</code> instance.
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public JobContainer(Level l) {
|
||||
setLevel(l);
|
||||
setArrangement(Y_AXIS);
|
||||
|
||||
event = new JobSelectionEvent("");
|
||||
listeners = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an JobSelectionListener to the button.
|
||||
*
|
||||
* @param l the JobSelectionListener to be added.
|
||||
*/
|
||||
public void addJobSelectionListener(JobSelectionListener l) {
|
||||
if (!listeners.contains(l)) {
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an JobSelectionListener from the button. If the listener is the
|
||||
* currently set JobSelection for the button, then the JobSelection is set to
|
||||
* null.
|
||||
*
|
||||
* @param l the listener to be removed.
|
||||
*/
|
||||
public void removeJobSelectionListener(JobSelectionListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the listeners for this button.
|
||||
*
|
||||
* @return a <code>List</code> value
|
||||
*/
|
||||
protected List getJobSelectionListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the list of action listeners.
|
||||
*
|
||||
* @param ll a <code>List</code> value
|
||||
*/
|
||||
protected void setJobSelectionListeners(List ll) {
|
||||
listeners = new Vector(ll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all listeners that have registered interest for
|
||||
* notification on this event type. The event instance is lazily
|
||||
* created using the event parameter.
|
||||
*
|
||||
* @param e the JobSelectionEvent object.
|
||||
*/
|
||||
protected void fireJobSelected(JobSelectionEvent e) {
|
||||
Iterator i = listeners.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
((JobSelectionListener) i.next()).jobSelected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getLevel</code> method here.
|
||||
*
|
||||
* @return a <code>Level</code> value
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setLevel</code> method here.
|
||||
*
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public void setLevel(Level l) {
|
||||
level = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getArrangement</code> method here.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public int getArrangement() {
|
||||
return arrangement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setArrangment</code> method here.
|
||||
*
|
||||
* @param a an <code>int</code> value
|
||||
*/
|
||||
public void setArrangement(int a) {
|
||||
if (a == X_AXIS || a == Y_AXIS) {
|
||||
arrangement = a;
|
||||
rearrangeButtons();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Bad value for button arrangement");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a job button for the job with the specified ID.
|
||||
*
|
||||
* @param jobId a <code>String</code> value
|
||||
*/
|
||||
public void addJobButton(String jobId) {
|
||||
//Create the new job button:
|
||||
JobButton butt = new JobButton(level, jobId);
|
||||
butt.setShown(true);
|
||||
butt.addActionListener(this);
|
||||
|
||||
List children = getChildren();
|
||||
|
||||
if (children.size() == 0) {
|
||||
//This is the first button:
|
||||
butt.setPosition(new Point(getBounds().x, getBounds().y));
|
||||
} else {
|
||||
//This is not the first button:
|
||||
Point newPos = new Point();
|
||||
Rectangle e = butt.getLemmingJob().getAnimation().getAnimation()
|
||||
.getExtent(butt.getLemmingJob().getAnimation().getCurrentFrame());
|
||||
LComponent prevChild = ((LComponent) children.get(children.size() - 1));
|
||||
newPos.x = prevChild.getBounds().x - e.x;
|
||||
newPos.y = prevChild.getBounds().y - e.y;
|
||||
|
||||
if (arrangement == X_AXIS) {
|
||||
//Move to the right:
|
||||
newPos.x += prevChild.getBounds().width + SPACING;
|
||||
} else {
|
||||
//Move down:
|
||||
newPos.y += prevChild.getBounds().height + SPACING;
|
||||
}
|
||||
|
||||
butt.setPosition(newPos);
|
||||
}
|
||||
|
||||
addChild(butt);
|
||||
|
||||
if (children.size() == 1) {
|
||||
setSelectedButton(jobId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rearranges all buttons.
|
||||
*/
|
||||
protected void rearrangeButtons() {
|
||||
List children = new Vector(getChildren());
|
||||
|
||||
clear();
|
||||
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
addJobButton(((JobButton) children.get(i)).getLemmingJob().getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the buttons.
|
||||
*/
|
||||
public void updateButtons() {
|
||||
List children = getChildren();
|
||||
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
JobButton butt = (JobButton) children.get(i);
|
||||
|
||||
butt.updateButton();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the button with the spercified id.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public void setSelectedButton(String id) {
|
||||
List children = getChildren();
|
||||
|
||||
//Check if we need to do job selection any way:
|
||||
if (level.getJobsRemaining(id) <= 0) { return; }
|
||||
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
JobButton butt = (JobButton) children.get(i);
|
||||
|
||||
if (!id.equals(butt.getActionCommand())) {
|
||||
if (butt.isSelected()) {
|
||||
butt.setSelected(false);
|
||||
}
|
||||
} else {
|
||||
if (!butt.isSelected()) {
|
||||
butt.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Tell the level a new job has been selected:
|
||||
level.setActiveJobId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>actionPerformed</code> method here.
|
||||
*
|
||||
* @param e an <code>ActionEvent</code> value
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//Update the selection.
|
||||
setSelectedButton(e.getActionCommand());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
//Nothing (?) to paint here.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* Class JobSelectionEvent: Fired whenever a new job has been selected.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 10, 2004) - Created the JobSelectionEvent class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 10, 2004
|
||||
*/
|
||||
public final class JobSelectionEvent extends EventObject {
|
||||
|
||||
/**
|
||||
* The id of the newly selected job.
|
||||
*/
|
||||
private String jobId;
|
||||
|
||||
/**
|
||||
* Creates a new <code>JobSelectionEvent</code> instance.
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
public JobSelectionEvent(String id) {
|
||||
super(id);
|
||||
|
||||
setJobId(id);
|
||||
}
|
||||
/**
|
||||
*
|
||||
*@param r r
|
||||
*/
|
||||
public void setJobId(String r) {
|
||||
jobId = r;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*@return String
|
||||
*/
|
||||
public String getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* Interface JobSelectionListener: The interface that should be
|
||||
* implemented by all classes that want to listen to job selection
|
||||
* events.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 10, 2004) - Created the JobSelectionListener interface
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 10, 2004
|
||||
*/
|
||||
public interface JobSelectionListener extends EventListener {
|
||||
|
||||
/**
|
||||
* Invoked when a job has been selected.
|
||||
*
|
||||
* @param e The event associated with this invokation.
|
||||
*/
|
||||
public void jobSelected(JobSelectionEvent e);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Class LAbstractButton: The abstract button class.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 29, 2004) - Created the LAbstractButton class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 29, 2004
|
||||
*/
|
||||
public abstract class LAbstractButton extends LLeafComponent
|
||||
implements IClickable {
|
||||
|
||||
/**
|
||||
* The list of listeners that are listening to this button.
|
||||
*/
|
||||
private List listeners;
|
||||
|
||||
/**
|
||||
* The action command associated with this button.
|
||||
*/
|
||||
private String actionCommand;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LAbstractButton</code> instance.
|
||||
*/
|
||||
public LAbstractButton() {
|
||||
super();
|
||||
|
||||
listeners = new Vector();
|
||||
actionCommand = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ActionListener to the button.
|
||||
*
|
||||
* @param l the ActionListener to be added.
|
||||
*/
|
||||
public void addActionListener(ActionListener l) {
|
||||
if (!listeners.contains(l)) {
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ActionListener from the button. If the listener is the
|
||||
* currently set Action for the button, then the Action is set to
|
||||
* null.
|
||||
*
|
||||
* @param l the listener to be removed.
|
||||
*/
|
||||
public void removeActionListener(ActionListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the listeners for this button.
|
||||
*
|
||||
* @return a <code>List</code> value
|
||||
*/
|
||||
protected List getActionListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the list of action listeners.
|
||||
*
|
||||
* @param ll a <code>List</code> value
|
||||
*/
|
||||
protected void setActionListeners(List ll) {
|
||||
listeners = new Vector(ll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all listeners that have registered interest for
|
||||
* notification on this event type. The event instance is lazily
|
||||
* created using the event parameter.
|
||||
*
|
||||
* @param e the ActionEvent object.
|
||||
*/
|
||||
protected void fireActionPerformed(ActionEvent e) {
|
||||
Iterator i = listeners.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
((ActionListener) i.next()).actionPerformed(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action command for this button.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String getActionCommand() {
|
||||
return (this.actionCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new action command for this button.
|
||||
*
|
||||
* @param v a <code>String</code> value
|
||||
*/
|
||||
public void setActionCommand(String v) {
|
||||
this.actionCommand = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the click of a mouse button at the specified coordinates.
|
||||
*
|
||||
* @param button an <code>int</code> value
|
||||
* @param coords a <code>Point</code> value
|
||||
*/
|
||||
public void registerMouseClick(int button, Point coords) {
|
||||
ActionEvent event = new ActionEvent(this, ((int) new Date().getTime()),
|
||||
getActionCommand());
|
||||
|
||||
if (LApplication.VERBOSE) {
|
||||
System.out.println("Button " + getClass().getName() + " clicked.");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
this.fireActionPerformed(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.util.Timer;
|
||||
//import java.util.TimerTask;
|
||||
|
||||
//import java.awt.Canvas;
|
||||
import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
//import java.awt.Cursor;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.Graphics2D;
|
||||
//import java.awt.AlphaComposite;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
|
||||
import java.awt.image.BufferStrategy;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
//import java.awt.event.MouseMotionListener;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
* Class LApplication: This is the main application class. When
|
||||
* instantiated, it will create a new window with nothing in it. The
|
||||
* window's content pane is what we will be drawing in and every
|
||||
* frame, we will call our own components' renderall method to render
|
||||
* the stuff on screen.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LApplication class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public class LApplication {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Show lots of debug output?
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The default title of the application window.
|
||||
*/
|
||||
public static final String DEFAULT_TITLE = "LApplication";
|
||||
|
||||
/**
|
||||
* The default location of the top-left corner of the application.
|
||||
*/
|
||||
public static final Point DEFAULT_LOCATION = new Point(50, 50);
|
||||
|
||||
/**
|
||||
* The default size of the application window.
|
||||
*/
|
||||
public static final Dimension DEFAULT_SIZE = new Dimension(800, 600);
|
||||
|
||||
/**
|
||||
* The frame rate cap.
|
||||
*/
|
||||
public static final float MAXIMUM_FRAME_RATE = 60;
|
||||
|
||||
/**
|
||||
* This is the delay between frames.
|
||||
*/
|
||||
public static final long FRAME_DELAY = (long) (1000.0f / MAXIMUM_FRAME_RATE);
|
||||
|
||||
/**
|
||||
* If we are not rendering, then check this many millis if we should go.
|
||||
*/
|
||||
public static final long NO_GO_DELAY = 1000;
|
||||
|
||||
/**
|
||||
* If we are lagging by this much, skip a frame.
|
||||
*/
|
||||
public static final int MAX_TARDINESS = 1000;
|
||||
|
||||
/**
|
||||
* The buffer strategy associated with this application.
|
||||
*/
|
||||
private BufferStrategy strategy;
|
||||
|
||||
/**
|
||||
* The graphics configuration used by this application.
|
||||
*/
|
||||
private GraphicsConfiguration gConfig;
|
||||
|
||||
/**
|
||||
* The root pane associated with this application.
|
||||
*/
|
||||
private LRootPane rootPane;
|
||||
|
||||
/**
|
||||
* Specifies whether we are currently rendering or not.
|
||||
*/
|
||||
private boolean rendererGoing;
|
||||
|
||||
/**
|
||||
* The frame that everything happens in.
|
||||
*/
|
||||
private JFrame frame;
|
||||
|
||||
/*
|
||||
* The task that will be used for rendering.
|
||||
*/
|
||||
//private TimerTask timerTask;
|
||||
|
||||
/**
|
||||
* The obligatory temporary point to avoid dynamic allocation during
|
||||
* runtime.
|
||||
*/
|
||||
private Point ptTemp = new Point();
|
||||
|
||||
/*
|
||||
* The obligatory temporary point to avoid dynamic allocation during
|
||||
* runtime.
|
||||
*/
|
||||
//private Point ptTemp2 = new Point();
|
||||
|
||||
/**
|
||||
* The cursor to be used in this application. If null, a default
|
||||
* cursor is used.
|
||||
*/
|
||||
//private LCursor cursor;
|
||||
|
||||
/**
|
||||
* Determines whether or not we should render the cursor.
|
||||
*/
|
||||
//private boolean renderCursor;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LApplication</code> instance.
|
||||
*
|
||||
* @param title The title to give to the window. If null is passed
|
||||
* in, a default vaue will be provided.
|
||||
* @param location The location of the application window. If null
|
||||
* is passed in, a default vaue will be provided.
|
||||
* @param size The size of the application window. If null is passed
|
||||
* in, a default vaue will be provided.
|
||||
*/
|
||||
public LApplication(String title, Point location, Dimension size) {
|
||||
rendererGoing = false;
|
||||
//renderCursor = false;
|
||||
|
||||
if (title == null) {
|
||||
title = DEFAULT_TITLE;
|
||||
}
|
||||
|
||||
if (location == null) {
|
||||
location = DEFAULT_LOCATION;
|
||||
}
|
||||
|
||||
if (size == null) {
|
||||
size = DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
//Use default graphics configuration:
|
||||
gConfig = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
|
||||
//Create frame:
|
||||
frame = new JFrame(title, gConfig);
|
||||
// canvas = new Canvas(gConfig);
|
||||
// frame.setUndecorated(true);
|
||||
/*
|
||||
{
|
||||
public void paint(Graphics g) {
|
||||
//Java is saying we should redraw the frame... Okay.
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
*/
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
ptTemp.x = e.getX();
|
||||
ptTemp.y = e.getY();
|
||||
|
||||
getRootPane().dispatchMouseMotionEvent(ptTemp, ptTemp);
|
||||
}
|
||||
});
|
||||
frame.addMouseWheelListener(new MouseWheelListener() {
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
ptTemp.x = e.getX();
|
||||
ptTemp.y = e.getY();
|
||||
|
||||
getRootPane().dispatchMouseWheelEvent(ptTemp, e.getWheelRotation());
|
||||
}
|
||||
});
|
||||
frame.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
ptTemp.x = e.getX();
|
||||
ptTemp.y = e.getY();
|
||||
|
||||
getRootPane().dispatchMouseClickEvent(e.getButton(), ptTemp);
|
||||
}
|
||||
});
|
||||
frame.addKeyListener(new KeyAdapter() {
|
||||
public void keyTyped(KeyEvent e) {
|
||||
getRootPane().dispatchKeyboardEvent(e.getKeyChar(),
|
||||
e.getModifiers());
|
||||
}
|
||||
});
|
||||
|
||||
//Display the window:
|
||||
frame.setLocation(location);
|
||||
frame.setSize(size);
|
||||
frame.setResizable(false);
|
||||
frame.setVisible(true);
|
||||
|
||||
//Initialize double buffering:
|
||||
frame.createBufferStrategy(2);
|
||||
strategy = frame.getBufferStrategy();
|
||||
|
||||
//Initialize the root pane:
|
||||
rootPane = new LRootPane();
|
||||
rootPane.setShown(true);
|
||||
|
||||
//Set up the renderer thread:
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
long lastFrame = System.currentTimeMillis();
|
||||
// boolean render = true;
|
||||
|
||||
while (true) {
|
||||
if (!rendererGoing || !frame.isVisible()) {
|
||||
//Sleep a bit, then continue:
|
||||
try {
|
||||
lastFrame += NO_GO_DELAY;
|
||||
|
||||
Thread.sleep(Math.max(0,
|
||||
lastFrame - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
} finally {
|
||||
lastFrame = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
//Do the rendering:
|
||||
repaint();
|
||||
// render = false;
|
||||
|
||||
//Cap frame rate:
|
||||
lastFrame += FRAME_DELAY;
|
||||
try {
|
||||
if (DEBUG) {
|
||||
System.out.println("Want to sleep "
|
||||
+ (lastFrame - System.currentTimeMillis())
|
||||
+ " millis");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
Thread.sleep(Math.max(0,
|
||||
lastFrame - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
} finally {
|
||||
lastFrame = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
// cursor = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the graphics configuration used by the application.
|
||||
* @return a <code>GraphicsConfiguration</code> value
|
||||
*/
|
||||
public GraphicsConfiguration getConfiguration() {
|
||||
return gConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root pane used for this application.
|
||||
* @return a <code>LRootPane</code> value
|
||||
*/
|
||||
public LRootPane getRootPane() {
|
||||
return rootPane;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the new root pane:
|
||||
*
|
||||
* @param pane a <code>LRootPane</code> value
|
||||
*/
|
||||
public synchronized void setRootPane(LRootPane pane) {
|
||||
// rootPane.clear();
|
||||
pane.copy(rootPane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaints everything that needs repainting.
|
||||
*/
|
||||
public synchronized void repaint() {
|
||||
if (DEBUG) {
|
||||
System.out.println("LApplication: Rendering...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Get the graphics context from buffer strategy:
|
||||
Graphics g = strategy.getDrawGraphics();
|
||||
|
||||
//Clear all:
|
||||
//FIXME: Hack. Need to make it so only things that need
|
||||
// rerendering are rerendered.
|
||||
//g.setColor(java.awt.Color.gray);
|
||||
//g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
|
||||
|
||||
//Do the drawing:
|
||||
rootPane.renderAll(g);
|
||||
|
||||
/*
|
||||
if (renderCursor) {
|
||||
//Render the cursor:
|
||||
cursor.renderCursor(g);
|
||||
}
|
||||
*/
|
||||
|
||||
//Flip the buffer:
|
||||
strategy.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the renderer loop.
|
||||
*/
|
||||
public synchronized void startRenderer() {
|
||||
if (rendererGoing) {
|
||||
return;
|
||||
}
|
||||
|
||||
rendererGoing = true;
|
||||
|
||||
/*
|
||||
if (timerTask != null) {
|
||||
//Already started task
|
||||
return;
|
||||
}
|
||||
|
||||
//Set up renderer timer:
|
||||
timerTask = new TimerTask() {
|
||||
public void run() {
|
||||
if (System.currentTimeMillis() - scheduledExecutionTime()
|
||||
>= MAX_TARDINESS) {
|
||||
return; // Too late; skip this execution.
|
||||
}
|
||||
|
||||
if (!rendererGoing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frame.isVisible()) {
|
||||
//No need to redraw:
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform the task
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
|
||||
new Timer().scheduleAtFixedRate(timerTask,
|
||||
0,
|
||||
(int) (1000.0f / MAXIMUM_FRAME_RATE));
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the renderer.
|
||||
*/
|
||||
public synchronized void stopRenderer() {
|
||||
rendererGoing = false;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Fades screen to black in the specified time.
|
||||
// *
|
||||
// * @param time The number of millis to fade.
|
||||
// */
|
||||
// public synchronized void fade(long time) {
|
||||
// stopRenderer();
|
||||
// getRootPane().clear();
|
||||
|
||||
// //We want 60 steps a second. So:
|
||||
// long numSteps = (time * 6) / 100;
|
||||
// long delay = time / numSteps;
|
||||
// float increment = 1.0f / numSteps;
|
||||
// float current = 0.0f;
|
||||
// Graphics2D g2D = (Graphics2D) strategy.getDrawGraphics();
|
||||
// Rectangle rect = new Rectangle(0,0,frame.getWidth(),frame.getHeight());
|
||||
// long last = System.currentTimeMillis();
|
||||
|
||||
// if (VERBOSE) {
|
||||
// System.out.println("LApplication: Set up fading... ");
|
||||
// System.out.println("\tTime: " + time);
|
||||
// System.out.println("\tSteps: " + numSteps);
|
||||
// System.out.println("\tDelay: " + delay);
|
||||
// System.out.println("\tIncrement: " + increment);
|
||||
// System.out.flush();
|
||||
// }
|
||||
|
||||
// g2D.setColor(Color.black);
|
||||
|
||||
// for (int i = 0; i < numSteps; i++) {
|
||||
// g2D.setComposite(AlphaComposite
|
||||
// .getInstance(AlphaComposite.XOR, current));
|
||||
// g2D.fill(rect);
|
||||
// current += increment;
|
||||
|
||||
// last += delay;
|
||||
// try {
|
||||
// Thread.sleep(Math.max(0, last - System.currentTimeMillis()));
|
||||
// } catch (Exception e) {
|
||||
// System.out.println("");
|
||||
// } finally {
|
||||
// last = System.currentTimeMillis();
|
||||
// }
|
||||
|
||||
// //Flip the buffer:
|
||||
// strategy.show();
|
||||
// }
|
||||
|
||||
// startRenderer();
|
||||
// getRootPane().makeDirty();
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Returns the cursor currently used, or null if no cursor is used.
|
||||
// *
|
||||
// * @return a <code>LCursor</code> value
|
||||
// */
|
||||
// public LCursor getCursor() {
|
||||
// return cursor;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Sets the new cursor up.
|
||||
// *
|
||||
// * @param c a <code>LCursor</code> value
|
||||
// */
|
||||
// public synchronized void setCursor(LCursor c) {
|
||||
// if (c == null) {
|
||||
// cursor = null;
|
||||
// renderCursor = false;
|
||||
|
||||
// //Use default cursor:
|
||||
// frame.setCursor(Cursor.getDefaultCursor());
|
||||
// } else {
|
||||
// cursor = c;
|
||||
// renderCursor = true;
|
||||
|
||||
// //Use custom cursor:
|
||||
// frame.setCursor(ImageUtilities.getInstance().createBlankCursor());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
//import java.awt.FontMetrics;
|
||||
//import java.awt.GraphicsEnvironment;
|
||||
|
||||
//import java.awt.event.ActionEvent;
|
||||
//import java.awt.event.ActionListener;
|
||||
|
||||
//import java.util.Date;
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
//import java.util.Iterator;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
|
||||
/**
|
||||
* Class LButton: This is the basic class for a button.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 14, 2004) - Created the LButton class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 14, 2004
|
||||
*/
|
||||
public class LButton extends LAbstractButton {
|
||||
|
||||
/**
|
||||
* The text to display on this button.
|
||||
*/
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* The image to display on this button.
|
||||
*/
|
||||
private AnimatedSprite image;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LButton</code> instance.
|
||||
*/
|
||||
public LButton() {
|
||||
super();
|
||||
|
||||
text = "LButton";
|
||||
image = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text displayed on this button.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String getText() {
|
||||
return (this.text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new value of the text on this button.
|
||||
*
|
||||
* @param v a <code>String</code> value
|
||||
*/
|
||||
public void setText(String v) {
|
||||
this.text = v;
|
||||
setActionCommand(text);
|
||||
image = null;
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image displayed on this button.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new value for the image of this button.
|
||||
*
|
||||
* @param newImage an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public void setImage(AnimatedSprite newImage) {
|
||||
image = newImage;
|
||||
setActionCommand(newImage.getAnimation().getFileName());
|
||||
text = null;
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>updateDimensions</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
if (text != null) {
|
||||
/*
|
||||
//We are updating due to changes in text:
|
||||
FontMetrics metrics = new FontMetrics(LFancyLabel.DEFAULT_FONT);
|
||||
|
||||
setSize(metrics.charsWidth(text.toCharArray(), 0,
|
||||
text.length()), metrics.getHeight());
|
||||
*/
|
||||
|
||||
//Hack. Must make the size be actually dependent on text...
|
||||
setSize(100, 100);
|
||||
|
||||
} else if (image != null) {
|
||||
//We are updating due to image:
|
||||
int x = getBounds().x;
|
||||
int y = getBounds().y;
|
||||
Rectangle e = image.getAnimation().getExtent(image.getCurrentFrame());
|
||||
|
||||
if (LApplication.VERBOSE) {
|
||||
System.out.println("LButton: Coords - (" + x + ", " + y + ")");
|
||||
System.out.println(" Extent - " + e);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
setBounds(e);
|
||||
getBounds().translate(x, y);
|
||||
} else {
|
||||
//Both text and image are null... Bad.
|
||||
throw new NullPointerException("Both text and image are null.");
|
||||
}
|
||||
|
||||
makeDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
LButton target = (LButton) component;
|
||||
|
||||
target.setActionListeners(getActionListeners());
|
||||
target.setActionCommand(this.getActionCommand());
|
||||
target.text = this.getText();
|
||||
target.image = this.getImage();
|
||||
target.updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
Rectangle bounds = this.getBounds();
|
||||
|
||||
if (text != null) {
|
||||
//Render text button...
|
||||
g.setColor(Color.black);
|
||||
g.setFont(LFancyLabel.DEFAULT_FONT);
|
||||
|
||||
//Render border first:
|
||||
g.draw3DRect(bounds.x - 5, bounds.y - 5,
|
||||
bounds.width + 5, bounds.height + 5, true);
|
||||
|
||||
//Render text:
|
||||
g.drawString(getText(), bounds.x, bounds.y);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (image != null) {
|
||||
//Render image button...
|
||||
Rectangle e = image.getAnimation().getExtent(image.getCurrentFrame());
|
||||
|
||||
return image.renderSprite(g, new Point(bounds.x - e.x, bounds.y - e.y));
|
||||
|
||||
} else {
|
||||
//No text, no image... :/
|
||||
throw new NullPointerException("Both text and image are null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* Class LColoredComponent: An abstract parent for the colored components.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LColoredComponent class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public abstract class LColoredComponent extends LLeafComponent {
|
||||
|
||||
/**
|
||||
* The default foreground color.
|
||||
*/
|
||||
public static final Color DEFAULT_FOREGROUND_COLOR = Color.black;
|
||||
|
||||
/**
|
||||
* The default background color.
|
||||
*/
|
||||
public static final Color DEFAULT_BACKGROUND_COLOR = Color.white;
|
||||
|
||||
/**
|
||||
* The foreground color associated with this component.
|
||||
*/
|
||||
private Color foreground;
|
||||
|
||||
/**
|
||||
* The background color associated with this component.
|
||||
*/
|
||||
private Color background;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LColoredComponent</code> instance.
|
||||
*/
|
||||
public LColoredComponent() {
|
||||
super();
|
||||
|
||||
setBackground(DEFAULT_BACKGROUND_COLOR);
|
||||
setForeground(DEFAULT_FOREGROUND_COLOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the foreground associated with this component.
|
||||
*
|
||||
* @return a <code>Color</code> value
|
||||
*/
|
||||
public final Color getForeground() {
|
||||
return foreground; //new Color(foreground.getRGB());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the new foreground with this colored component.
|
||||
*
|
||||
* @param c a <code>Color</code> value
|
||||
*/
|
||||
public final void setForeground(Color c) {
|
||||
setForeground(c.getRGB());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the new foreground with this colored component.
|
||||
*
|
||||
* @param rgb an <code>int</code> value
|
||||
*/
|
||||
public final void setForeground(int rgb) {
|
||||
this.foreground = new Color(rgb, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the background associated with this component.
|
||||
*
|
||||
* @return a <code>Color</code> value
|
||||
*/
|
||||
public final Color getBackground() {
|
||||
return background; // new Color(background.getRGB());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the new background with this colored component.
|
||||
*
|
||||
* @param c a <code>Color</code> value
|
||||
*/
|
||||
public final void setBackground(Color c) {
|
||||
setBackground(c.getRGB());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the new background with this colored component.
|
||||
*
|
||||
* @param rgb an <code>int</code> value
|
||||
*/
|
||||
public final void setBackground(int rgb) {
|
||||
this.background = new Color(rgb, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* The base component class, from which all of the more specific
|
||||
* components, such as buttons, will be derived.
|
||||
*
|
||||
* @author <a href="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class LComponent {
|
||||
|
||||
/**
|
||||
* The parent component of this component. If this is the root
|
||||
* panel, then it will have no parent.
|
||||
*/
|
||||
private LContainer parent;
|
||||
|
||||
/**
|
||||
* The rectangle defining the position and the dimensions of the
|
||||
* window in virtual GUI coordinates
|
||||
*/
|
||||
private Rectangle position;
|
||||
|
||||
/**
|
||||
* Determines whether the component is hidden or visible.
|
||||
*/
|
||||
private boolean isVisible;
|
||||
|
||||
/**
|
||||
* Indicates that the component is dirty.
|
||||
*/
|
||||
private boolean isDirty;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LComponent</code> instance.
|
||||
*
|
||||
*/
|
||||
public LComponent() {
|
||||
parent = null;
|
||||
position = new Rectangle();
|
||||
isVisible = false;
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the initialization necessary for the
|
||||
* component. Returns true if the initialization went through
|
||||
* successfully and false if something went wrong.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all the necessary operations to clean up after the
|
||||
* component. Does *not* destroy the children of the component,
|
||||
* however.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean cleanUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the parent component of this one if there is
|
||||
* one, or NULL if this component has no parent or is the root
|
||||
* window.
|
||||
*
|
||||
* @return a <code>LComponent</code> value
|
||||
*/
|
||||
public final LContainer getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new parent for this component.
|
||||
*
|
||||
* @param c a <code>LContainer</code> value
|
||||
*/
|
||||
public final void setParent(LContainer c) {
|
||||
parent = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component is visible, and false if it is not.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean isShown() {
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visibility of the component to the value passed in.
|
||||
*
|
||||
* @param value a <code>boolean</code> value
|
||||
*/
|
||||
public final void setShown(boolean value) {
|
||||
isVisible = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component is to be rerendered during the next frame.
|
||||
*@return boolean
|
||||
*/
|
||||
public final boolean isComponentDirty() {
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component's dirty value to the one passed in.
|
||||
*@param value v
|
||||
*/
|
||||
protected final void setDirty(boolean value) {
|
||||
isDirty = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component has input focus, and false if it does not.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean isActive() {
|
||||
if (getParent() == null) {
|
||||
//I am the root and therefore active by defult.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isShown()) {
|
||||
//I am hidden. Could not be active.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getParent().isActive()) {
|
||||
//The parent is inactive, therefore neither am I:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this == getParent().getChildren()
|
||||
.get(getParent().getChildren().size() - 1)) {
|
||||
//I am the last child in the parent's list, and therefore the top-most:
|
||||
return true;
|
||||
}
|
||||
|
||||
//If all else fails...
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Brings the current component to the top of the z-order. (It's
|
||||
* children will still remain on top of it, however.)
|
||||
*
|
||||
*/
|
||||
public final void bringToTop() {
|
||||
//Gotta save the parent pointer because when we call Remove, it
|
||||
//will set my parent to NULL.
|
||||
LContainer p = getParent();
|
||||
|
||||
if (p == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Bring parent to top in case it is not on top already:
|
||||
p.bringToTop();
|
||||
|
||||
//This basically moves the element to the end of the list of
|
||||
//children of the parent. That means that it will be rendered
|
||||
//last, and thus will be on top of all other children of its
|
||||
//parent.
|
||||
p.removeChild(this);
|
||||
p.addChild(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rectangle denoting the bounds of the component.
|
||||
*
|
||||
* @return a <code>Rectangle</code> value
|
||||
*/
|
||||
public final Rectangle getBounds() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new bounds of the component. No error checking is
|
||||
* performed beyond that the size of the rectangle should be
|
||||
* meaningful.
|
||||
*@param newBounds n
|
||||
*/
|
||||
public final void setBounds(Rectangle newBounds) {
|
||||
this.position = newBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of the top-left corner of the component to the
|
||||
* desired coordinates.
|
||||
*
|
||||
* @param p a <code>Point</code> value
|
||||
*/
|
||||
public final void setPosition(Point p) {
|
||||
p.translate(-position.x, -position.y);
|
||||
|
||||
move(p);
|
||||
|
||||
p.translate(position.x, position.y);
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the component.
|
||||
*
|
||||
* @param d a <code>Dimension</code> value
|
||||
*/
|
||||
public final void setSize(Dimension d) {
|
||||
if (d.width < 0 || d.height < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSize(d.width, d.height);
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setSize</code> method here.
|
||||
*
|
||||
* @param width an <code>int</code> value
|
||||
* @param height an <code>int</code> value
|
||||
*/
|
||||
protected final void setSize(int width, int height) {
|
||||
this.position.width = width;
|
||||
this.position.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the dimensions of the component. This must *NOT* under
|
||||
* any circumstances call the method setPosition() or setSize()!!!
|
||||
*/
|
||||
protected void updateDimensions() { }
|
||||
|
||||
/**
|
||||
* Marks the component dirty.
|
||||
*/
|
||||
public abstract void makeDirty();
|
||||
|
||||
/**
|
||||
* Moves the component by the offsets specified by the components of
|
||||
* the point.
|
||||
*
|
||||
* @param offset a <code>Point</code> value
|
||||
*/
|
||||
public abstract void move(Point offset);
|
||||
|
||||
/**
|
||||
* Calls paint on self and then all the children in z order.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public abstract boolean renderAll(Graphics g);
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected abstract void copy(LComponent component);
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected abstract boolean paint(Graphics g);
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Class LContainer: The parent for all components that can contain
|
||||
* other components.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LContainer class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public abstract class LContainer extends LComponent {
|
||||
|
||||
/**
|
||||
* The list of children of the component.
|
||||
*/
|
||||
private List children;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LContainer</code> instance.
|
||||
*/
|
||||
public LContainer() {
|
||||
super();
|
||||
|
||||
children = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the component by the offsets specified by the components of
|
||||
* the point.
|
||||
*
|
||||
* @param offset a <code>Point</code> value
|
||||
*/
|
||||
public final void move(Point offset) {
|
||||
Rectangle r = getBounds();
|
||||
|
||||
r.x += offset.x;
|
||||
r.y += offset.y;
|
||||
|
||||
/*
|
||||
Point p = new Point(getBounds().x, getBounds().y);
|
||||
|
||||
p.x += offset.x;
|
||||
p.y += offset.y;
|
||||
|
||||
this.setPosition(p);
|
||||
*/
|
||||
|
||||
//Now that we've moved self, we need to also move all the children:
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
((LComponent) children.get(i)).move(offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the component dirty.
|
||||
*/
|
||||
public final void makeDirty() {
|
||||
setDirty(true);
|
||||
|
||||
//Set all children dirty as well:
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
((LComponent) children.get(i)).makeDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls paint on self and then all the children in z order.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean renderAll(Graphics g) {
|
||||
if (!isShown()) {
|
||||
//I am invisible. No go.
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!this.isComponentDirty()) {
|
||||
//Not dirtty. No need to rerender:
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//Paint self:
|
||||
if (!this.paint(g)) {
|
||||
//Could not paint self:
|
||||
return false;
|
||||
}
|
||||
|
||||
this.setDirty(false);
|
||||
|
||||
//Now, render the children:
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
((LComponent) children.get(i)).renderAll(g);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to add the component passed in as a child of this
|
||||
* component. Returns true if the addition was successful, and false
|
||||
* if it was not.
|
||||
*
|
||||
* @param child a <code>LComponent</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean addChild(LComponent child) {
|
||||
if (child == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!children.contains(child)) {
|
||||
//The list does not yet contain the child. Add it:
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
child.setParent(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to remove the component passed in from the list of
|
||||
* children of the current component. Returns true if the removal is
|
||||
* successful, or false if the child could not be found in the
|
||||
* list. The child is not deleted after removal.
|
||||
*
|
||||
* @param child a <code>LComponent</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean removeChild(LComponent child) {
|
||||
if (child == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!children.contains(child)) { return false; }
|
||||
|
||||
child.setParent(null);
|
||||
children.remove(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of children.
|
||||
* @return a <code>List</code> value
|
||||
*/
|
||||
protected final List getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all children.
|
||||
*/
|
||||
public final void clear() {
|
||||
while (children.size() > 0) {
|
||||
removeChild((LComponent) children.get(0));
|
||||
}
|
||||
|
||||
children.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the child of this component that the
|
||||
* specified coordinates are inside of, if there is one, or NULL if
|
||||
* there is no such child.
|
||||
*
|
||||
* @param coords a <code>Point</code> value
|
||||
* @return a <code>LComponent</code> value
|
||||
*/
|
||||
public final LComponent findChildAtCoordinates(Point coords) {
|
||||
int childCount = children.size() - 1;
|
||||
LComponent currentComponent = null;
|
||||
LComponent childComponent = null;
|
||||
|
||||
//If I am invisible, so are my children. No need to continue:
|
||||
if (!this.isShown()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Start with the top-most child:
|
||||
for (int i = childCount; i >= 0; i--) {
|
||||
currentComponent = (LComponent) children.get(i);
|
||||
|
||||
if (currentComponent instanceof LContainer) {
|
||||
childComponent = ((LContainer) currentComponent)
|
||||
.findChildAtCoordinates(coords);
|
||||
if (childComponent != null) {
|
||||
//Found one:
|
||||
return childComponent;
|
||||
}
|
||||
} else if (currentComponent.getBounds().contains(coords)
|
||||
&& currentComponent.isShown()) {
|
||||
return currentComponent;
|
||||
}
|
||||
}
|
||||
|
||||
//I have no children at the specified coordinates... Am I there?
|
||||
if (this.getBounds().contains(coords)) {
|
||||
//So I am!
|
||||
return this;
|
||||
}
|
||||
|
||||
//Nothing fit...
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top-most active child of this component.
|
||||
*@return bcomponent
|
||||
*/
|
||||
public final LComponent findActiveChild() {
|
||||
if (!isActive()) {
|
||||
//I'm not active, so neither could be my children:
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get last child:
|
||||
LComponent temp = (LComponent) children.get(children.size() - 1);
|
||||
|
||||
//Get last child's active child:
|
||||
if (temp instanceof LContainer) {
|
||||
temp = ((LContainer) temp).findActiveChild();
|
||||
}
|
||||
|
||||
if (temp == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
//import java.awt.AlphaComposite;
|
||||
|
||||
/**
|
||||
* Class LFader: This little widget allows one to fade the screen to a
|
||||
* certain color in different kinds of cool ways.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 15, 2004) - Created the LFader class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 15, 2004
|
||||
*/
|
||||
public class LFader extends LColoredComponent {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Just a little flag so we know when we have started fading.
|
||||
*/
|
||||
private boolean startedFading;
|
||||
|
||||
/**
|
||||
* The amount of time remaining in the fading.
|
||||
*/
|
||||
private long timeRemaining;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LFader</code> instance.
|
||||
*/
|
||||
public LFader() {
|
||||
startedFading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new thread that will update the fading of the thing
|
||||
* specially timed to complete in the specified number of millis.
|
||||
*
|
||||
* @param time a <code>long</code> value
|
||||
* @return a <code>Thread</code> value
|
||||
*/
|
||||
private Thread createThread(final long time) {
|
||||
Thread defThread = new Thread(new Runnable() {
|
||||
public void run() { }
|
||||
});
|
||||
|
||||
//First, make sure we have a valid time:
|
||||
if (time < 0) {
|
||||
return defThread;
|
||||
}
|
||||
|
||||
if ((time * 6) / 100 == 0) {
|
||||
//The time period provided is much too short.
|
||||
return defThread;
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
//We would like to have 60 steps per second, so calculate
|
||||
//the number of steps.
|
||||
long numSteps = (time * 6) / 100;
|
||||
|
||||
//Calculate the delay between each step:
|
||||
long delay = time / numSteps;
|
||||
|
||||
//Calculate the percent of the fade to do at each step:
|
||||
float incrementPercent = 1.0f / numSteps;
|
||||
|
||||
//A variable to store the progress to the completion of the fade:
|
||||
float currentPercentComplete = 0.0f;
|
||||
|
||||
//The time of the last update:
|
||||
long lastTime = System.currentTimeMillis();
|
||||
|
||||
//The targetted end fade time:
|
||||
long finalTime = time + lastTime;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LFader: Set up fading... ");
|
||||
System.out.println(" Time: " + time);
|
||||
System.out.println(" Steps: " + numSteps);
|
||||
System.out.println(" Delay: " + delay);
|
||||
System.out.println(" Increment: " + incrementPercent);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
resetFade();
|
||||
|
||||
startedFading = true;
|
||||
|
||||
for (int i = 0; i < numSteps; i++) {
|
||||
//Update the fading:
|
||||
update(currentPercentComplete);
|
||||
|
||||
//Increment percent to completion:
|
||||
currentPercentComplete += incrementPercent;
|
||||
|
||||
//Sleep some:
|
||||
lastTime += delay;
|
||||
try {
|
||||
Thread.sleep(Math.max(0, lastTime - System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
//Sleep interrupted...
|
||||
System.out.println("");
|
||||
} finally {
|
||||
lastTime = System.currentTimeMillis();
|
||||
timeRemaining = finalTime - lastTime;
|
||||
}
|
||||
}
|
||||
|
||||
// startedFading = false;
|
||||
}
|
||||
};
|
||||
|
||||
return new Thread(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fades to foreground in the time specified.
|
||||
*
|
||||
* @param time a <code>long</code> value
|
||||
*/
|
||||
public void fadeToForeground(long time) {
|
||||
createThread(time).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are currently fading.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isFading() {
|
||||
return startedFading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getTimeRemaining</code> method here.
|
||||
*
|
||||
* @return a <code>long</code> value
|
||||
*/
|
||||
public long getTimeRemaining() {
|
||||
return timeRemaining;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the fading.
|
||||
* @param progress the percent to completion.
|
||||
*/
|
||||
protected void update(float progress) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("Updating - " + (progress * 100) + "%");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Do a simple fade to black for now:
|
||||
Color f = getForeground();
|
||||
setForeground(new Color(f.getRed() / 255.0f,
|
||||
f.getGreen() / 255.0f,
|
||||
f.getBlue() / 255.0f,
|
||||
progress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the fading to the original configuration.
|
||||
*/
|
||||
protected void resetFade() {
|
||||
Color f = getForeground();
|
||||
setForeground(new Color(f.getRed() / 255.0f,
|
||||
f.getGreen() / 255.0f,
|
||||
f.getBlue() / 255.0f,
|
||||
0.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
if (!startedFading) {
|
||||
return true;
|
||||
}
|
||||
if (VERBOSE) {
|
||||
System.out.println("Fading - " + getForeground());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setColor(getForeground());
|
||||
g2d.fill(getBounds());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
/**
|
||||
* Class LFancyLabel: In addition to the regular label functionality,
|
||||
* this guy allows you to specify different fonts for the label.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LFancyLabel class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public final class LFancyLabel extends LLabel {
|
||||
|
||||
/**
|
||||
* Show lots of debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The default font.
|
||||
*/
|
||||
public static final Font DEFAULT_FONT;
|
||||
|
||||
static {
|
||||
//Initialize default font to the first font available
|
||||
Font temp = GraphicsEnvironment
|
||||
.getLocalGraphicsEnvironment().getAllFonts()[0];
|
||||
DEFAULT_FONT = temp.deriveFont(Font.PLAIN, 16.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* The font used to render this fancy label.
|
||||
*/
|
||||
private Font currentFont;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LFancyLabel</code> instance.
|
||||
*/
|
||||
public LFancyLabel() {
|
||||
this(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LFancyLabel</code> instance.
|
||||
*
|
||||
* @param text a <code>String</code> value
|
||||
*/
|
||||
public LFancyLabel(String text) {
|
||||
this(text, DEFAULT_FONT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LFancyLabel</code> instance.
|
||||
*
|
||||
* @param text a <code>String</code> value
|
||||
* @param font a <code>Font</code> value
|
||||
*/
|
||||
public LFancyLabel(String text, Font font) {
|
||||
super(text);
|
||||
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fint associated with this label.
|
||||
*
|
||||
* @return a <code>Font</code> value
|
||||
*/
|
||||
public Font getFont() {
|
||||
return currentFont;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new font value.
|
||||
*
|
||||
* @param newFont a <code>Font</code> value
|
||||
*/
|
||||
public void setFont(Font newFont) {
|
||||
if (newFont == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
currentFont = newFont;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
super.copy(component);
|
||||
|
||||
LFancyLabel target = (LFancyLabel) component;
|
||||
|
||||
target.setFont(new Font(getFont().getName(), getFont().getStyle(),
|
||||
getFont().getSize()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("LFancyLabel: Rendering with:");
|
||||
System.out.println("\t" + getFont());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
g.setColor(this.getForeground());
|
||||
g.setFont(this.getFont());
|
||||
g.drawString(this.getText(), this.getBounds().x, this.getBounds().y);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSet;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
|
||||
/**
|
||||
* Class LIcon: This class will display an image.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 14, 2004) - Created the LIcon class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 14, 2004
|
||||
*/
|
||||
public final class LIcon extends LLeafComponent {
|
||||
|
||||
/**
|
||||
* The sprite containing the image to be displayed.
|
||||
*/
|
||||
private AnimatedSprite image;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LIcon</code> instance.
|
||||
*
|
||||
*/
|
||||
public LIcon() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LIcon</code> instance.
|
||||
*@param set set
|
||||
*/
|
||||
public LIcon(TileSet set) {
|
||||
setAnimation(new AnimatedSprite(set,
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the animation associated with this icon.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public synchronized AnimatedSprite getAnimation() {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new icon image.
|
||||
*
|
||||
* @param newSprite an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public synchronized void setAnimation(AnimatedSprite newSprite) {
|
||||
//Save the sprite:
|
||||
image = newSprite;
|
||||
|
||||
//Update dimensions:
|
||||
Dimension newSize = image.getAnimation().getLargestDimension();
|
||||
setSize(newSize.width, newSize.height);
|
||||
|
||||
//Updated:
|
||||
this.makeDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the looping mode used by this animation.
|
||||
*
|
||||
* @return a <code>Looping</code> value
|
||||
*/
|
||||
public Looping getLoopingMode() {
|
||||
return getAnimation().getLoopingMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new looping mode for this icon.
|
||||
*
|
||||
* @param mode a <code>Looping</code> value
|
||||
*/
|
||||
public void setLoopingMode(Looping mode) {
|
||||
getAnimation().setLoopingMode(mode);
|
||||
|
||||
this.makeDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
LIcon target = (LIcon) component;
|
||||
|
||||
target.setAnimation(this.getAnimation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
return image.renderSprite(g, new Point(getBounds().x, getBounds().y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Class LLabel: Your regular old label.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LLabel class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public class LLabel extends LColoredComponent {
|
||||
|
||||
/**
|
||||
* Show lots of debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The text to display.
|
||||
*/
|
||||
private String labelText;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LLabel</code> instance.
|
||||
*/
|
||||
public LLabel() {
|
||||
this(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LLabel</code> instance.
|
||||
*
|
||||
* @param text a <code>String</code> value
|
||||
*/
|
||||
public LLabel(String text) {
|
||||
setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text of this label.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String getText() {
|
||||
return labelText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives this label new text.
|
||||
*
|
||||
* @param text a <code>String</code> value
|
||||
*/
|
||||
public final void setText(String text) {
|
||||
String t = text;
|
||||
if (t == null) {
|
||||
t = " ";
|
||||
}
|
||||
|
||||
labelText = t;
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected final void updateDimensions() {
|
||||
//We should now know the number of columns...
|
||||
//Make the margin of 6:
|
||||
int width = labelText.length() * LTextField.CHARACTER_DIMENSION.width;
|
||||
int height = LTextField.CHARACTER_DIMENSION.height;
|
||||
|
||||
getBounds().width = width;
|
||||
getBounds().height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
LLabel target = (LLabel) component;
|
||||
|
||||
target.setText(new String(this.getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("LLabel: Painting...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
g.setColor(getForeground());
|
||||
g.setFont(LFancyLabel.DEFAULT_FONT);
|
||||
g.drawString(getText(), getBounds().x, getBounds().y + getBounds().height);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Class LLeafComponent: This is the opposite of a container. That is,
|
||||
* there can be no children for this component.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LLeafComponent class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public abstract class LLeafComponent extends LComponent {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LLeafComponent</code> instance.
|
||||
*/
|
||||
public LLeafComponent() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the component by the offsets specified by the components of
|
||||
* the point.
|
||||
*
|
||||
* @param offset a <code>Point</code> value
|
||||
*/
|
||||
public final void move(Point offset) {
|
||||
Rectangle r = getBounds();
|
||||
|
||||
r.x += offset.x;
|
||||
r.y += offset.y;
|
||||
|
||||
/*
|
||||
Point p = new Point(getBounds().x, getBounds().y);
|
||||
|
||||
p.x += offset.x;
|
||||
p.y += offset.y;
|
||||
|
||||
this.setPosition(p);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the component dirty.
|
||||
*/
|
||||
public final void makeDirty() {
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls paint on self and then all the children in z order.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public final boolean renderAll(Graphics g) {
|
||||
if (!isShown()) {
|
||||
//I am invisible. No go.
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!this.isComponentDirty()) {
|
||||
//Not dirtty. No need to rerender:
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
this.setDirty(false);
|
||||
|
||||
//Paint self:
|
||||
if (!this.paint(g)) {
|
||||
//Could not paint self:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//import java.awt.event.MouseEvent;
|
||||
//import java.awt.event.KeyEvent;
|
||||
|
||||
/**
|
||||
* Class LRootPane: This is the class for the root pane. It will be
|
||||
* the root of everything else. It will be immovable, and will
|
||||
* distribute the events to whichever children get them.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 13, 2004) - Created the LRootPane class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 13, 2004
|
||||
*/
|
||||
public class LRootPane extends LContainer {
|
||||
|
||||
/**
|
||||
* Creates a new <code>LRootPane</code> instance.
|
||||
*/
|
||||
public LRootPane() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LRootPane target = (LRootPane) component;
|
||||
target.clear();
|
||||
|
||||
//Copy the children pointers over.
|
||||
List c = getChildren();
|
||||
for (int i = 0; i < c.size(); i++) {
|
||||
target.addChild((LComponent) c.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
//Root pane is invisible:
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the mouse event to the appropriate child.
|
||||
*@param button b
|
||||
*@param coords c
|
||||
*/
|
||||
public void dispatchMouseClickEvent(int button, Point coords) {
|
||||
LComponent comp = findChildAtCoordinates(coords);
|
||||
|
||||
if (comp == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (comp instanceof IClickable) {
|
||||
//Translate to coords relative to the clickable:
|
||||
coords.translate(-comp.getBounds().x, -comp.getBounds().y);
|
||||
|
||||
//Register:
|
||||
((IClickable) comp).registerMouseClick(button, coords);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the mouse event to the appropriate child.
|
||||
*@param oldCoords o
|
||||
*@param newCoords n
|
||||
*/
|
||||
public void dispatchMouseMotionEvent(Point oldCoords, Point newCoords) {
|
||||
LComponent comp = findChildAtCoordinates(newCoords);
|
||||
|
||||
if (comp == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (comp instanceof IMouseMotionable) {
|
||||
//Translate to coords relative to the mousable:
|
||||
// oldCoords.translate(-comp.getBounds().x, -comp.getBounds().y);
|
||||
// newCoords.translate(-comp.getBounds().x, -comp.getBounds().y);
|
||||
|
||||
//Register:
|
||||
((IMouseMotionable) comp).processMouseMotion(oldCoords.x, oldCoords.y,
|
||||
newCoords.x, newCoords.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>dispatchMouseWheelEvent</code> method here.
|
||||
*
|
||||
* @param coordinates a <code>Point</code> value
|
||||
* @param numClicks an <code>int</code> value
|
||||
*/
|
||||
public void dispatchMouseWheelEvent(Point coordinates, int numClicks) {
|
||||
LComponent comp = findChildAtCoordinates(coordinates);
|
||||
|
||||
if (comp instanceof IMouseWheelable) {
|
||||
((IMouseWheelable) comp).processMouseWheel(numClicks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the mouse event to the appropriate child.
|
||||
*@param button b
|
||||
*@param coords c
|
||||
*@param offset o
|
||||
*/
|
||||
public void dispatchMouseDragEvent(int button, Point coords, Point offset) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the keyboard event to the appropriate child.
|
||||
*@param keyCode k
|
||||
*@param modifiers m
|
||||
*/
|
||||
public void dispatchKeyboardEvent(char keyCode, int modifiers) {
|
||||
LComponent child = findActiveChild();
|
||||
|
||||
if (child instanceof ITypable) {
|
||||
((ITypable) child).processKeyTyped(keyCode, modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Dimension;
|
||||
//import java.awt.Rectangle;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
//Font metrics stuff:
|
||||
//import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
//import java.awt.GraphicsConfiguration;
|
||||
|
||||
/**
|
||||
* Class LTextField: This guy basically allows one to type in some text.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the LTextField class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public final class LTextField extends LColoredComponent
|
||||
implements ITypable, IClickable {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The dimensions of one character.
|
||||
*/
|
||||
public static final Dimension CHARACTER_DIMENSION;
|
||||
static {
|
||||
//Get the default configuration for the default device.
|
||||
Graphics2D defaultGraphics
|
||||
= (Graphics2D) GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration()
|
||||
.createCompatibleImage(1, 1).getGraphics();
|
||||
|
||||
//These are the bounds of the widest character.
|
||||
Rectangle2D bounds
|
||||
= LFancyLabel.DEFAULT_FONT
|
||||
.getMaxCharBounds(defaultGraphics.getFontRenderContext());
|
||||
|
||||
CHARACTER_DIMENSION = new Dimension((int) bounds.getWidth(),
|
||||
(int) bounds.getHeight());
|
||||
};
|
||||
|
||||
/**
|
||||
* The stroke to use for the border of the textbox.
|
||||
*/
|
||||
private Stroke borderStroke = new BasicStroke(2.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_ROUND);
|
||||
|
||||
/**
|
||||
* The color of the border of the textbox.
|
||||
*/
|
||||
private Color borderColor = Color.black;
|
||||
|
||||
/**
|
||||
* The text currently set in the text field.
|
||||
*/
|
||||
private StringBuffer textBuffer;
|
||||
|
||||
/**
|
||||
* The position of the caret.
|
||||
*/
|
||||
private int caretPosition;
|
||||
|
||||
/**
|
||||
* The number of columns in this textbox.
|
||||
*/
|
||||
private int numColumns;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LTextField</code> instance.
|
||||
*/
|
||||
public LTextField() {
|
||||
this(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>LTextLabel</code> instance.
|
||||
*
|
||||
* @param initialText a <code>String</code> value
|
||||
*/
|
||||
public LTextField(String initialText) {
|
||||
setText(initialText);
|
||||
setNumColumns(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text of this label.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String getText() {
|
||||
return textBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives this label new text.
|
||||
*
|
||||
* @param t a <code>String</code> value
|
||||
*/
|
||||
public void setText(String t) {
|
||||
String text = t;
|
||||
|
||||
if (text == null) {
|
||||
text = " ";
|
||||
}
|
||||
|
||||
textBuffer = new StringBuffer(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of numColumns.
|
||||
* @return value of numColumns.
|
||||
*/
|
||||
public int getNumColumns() {
|
||||
return numColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of numColumns.
|
||||
* @param v Value to assign to numColumns.
|
||||
*/
|
||||
public void setNumColumns(int v) {
|
||||
//PMD FIX
|
||||
int tv = v;
|
||||
if (tv <= 0) {
|
||||
tv = 1;
|
||||
}
|
||||
|
||||
this.numColumns = tv;
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
//We should now know the number of columns...
|
||||
//Make the margin of 6:
|
||||
int width = numColumns * CHARACTER_DIMENSION.width + 6;
|
||||
int height = CHARACTER_DIMENSION.height + 6;
|
||||
|
||||
getBounds().width = width;
|
||||
getBounds().height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new caret position if possible.
|
||||
*
|
||||
* @param newPosition an <code>int</code> value
|
||||
*/
|
||||
public final void setCaretPosition(final int newPosition) {
|
||||
int length = textBuffer.length();
|
||||
|
||||
if (newPosition < 0) {
|
||||
this.caretPosition = 0;
|
||||
}
|
||||
|
||||
if (newPosition > length) {
|
||||
this.caretPosition = length;
|
||||
}
|
||||
|
||||
end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the caret position.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public final int getCaretPosition() {
|
||||
return caretPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the caret one to the left if possible.
|
||||
*/
|
||||
public final void moveCaretLeft() {
|
||||
if (caretPosition > 0) {
|
||||
caretPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the caret one to the right is possible.
|
||||
*/
|
||||
public final void moveCaretRight() {
|
||||
int length = textBuffer.length();
|
||||
|
||||
if (caretPosition < length) {
|
||||
caretPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a HOME.
|
||||
*/
|
||||
public final void home() {
|
||||
caretPosition = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an END.
|
||||
*/
|
||||
public final void end() {
|
||||
caretPosition = textBuffer.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a backspace.
|
||||
*/
|
||||
public final void backSpace() {
|
||||
int oldPosition = getCaretPosition();
|
||||
|
||||
moveCaretLeft();
|
||||
|
||||
if (getCaretPosition() != oldPosition) {
|
||||
delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a delete.
|
||||
*/
|
||||
public final void delete() {
|
||||
int length = textBuffer.length();
|
||||
|
||||
if (caretPosition < length) {
|
||||
//Delete the char:
|
||||
textBuffer.deleteCharAt(caretPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the click of a mouse button at the specified coordinates.
|
||||
*
|
||||
* @param button an <code>int</code> value
|
||||
* @param coords a <code>Point</code> value
|
||||
*/
|
||||
public void registerMouseClick(int button, Point coords) {
|
||||
bringToTop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the key type event.
|
||||
*
|
||||
* @param key The key that was typed.
|
||||
* @param modifiers The modifiers that accompanied the
|
||||
* key-type. This is a collection of ORed flags, like SHIFT, ALT,
|
||||
* etc.
|
||||
*/
|
||||
public void processKeyTyped(char key, int modifiers) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("LTextField - Got key code " + (int) key);
|
||||
System.out.println(" The ASCII is " + key);
|
||||
System.out.println(" And the text "
|
||||
+ KeyEvent.getKeyText(key));
|
||||
System.out.println("");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case KeyEvent.VK_BACK_SPACE:
|
||||
backSpace();
|
||||
break;
|
||||
|
||||
case KeyEvent.VK_DELETE:
|
||||
delete();
|
||||
break;
|
||||
|
||||
/***** This stuff doesn't work with the char key. Have to find a
|
||||
* way to get around it and use the key code instead.
|
||||
|
||||
|
||||
case KeyEvent.VK_LEFT: case KeyEvent.VK_UP:
|
||||
moveCaretLeft();
|
||||
break;
|
||||
|
||||
case KeyEvent.VK_RIGHT: case KeyEvent.VK_DOWN:
|
||||
moveCaretRight();
|
||||
break;
|
||||
|
||||
case KeyEvent.VK_HOME: case KeyEvent.VK_PAGE_UP:
|
||||
home();
|
||||
break;
|
||||
|
||||
case KeyEvent.VK_END: case KeyEvent.VK_PAGE_DOWN:
|
||||
end();
|
||||
break;
|
||||
|
||||
*/
|
||||
|
||||
default:
|
||||
//Insert character:
|
||||
// textBuffer.insert(caretPosition, KeyEvent.getKeyText(key));
|
||||
textBuffer.insert(caretPosition, key);
|
||||
moveCaretRight();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
LTextField target = (LTextField) component;
|
||||
|
||||
target.setText(new String(this.getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
//Render background:
|
||||
g2d.setColor(getBackground());
|
||||
g2d.fill(getBounds());
|
||||
|
||||
//Render border around the textbox:
|
||||
g2d.setStroke(borderStroke);
|
||||
g2d.setColor(borderColor);
|
||||
g2d.draw(getBounds());
|
||||
|
||||
//Render text in the textbox:
|
||||
//Set up clipping 'cause I'm lazy:
|
||||
Shape oldClippie = g2d.getClip();
|
||||
g2d.setClip(getBounds());
|
||||
|
||||
//XXX: I render the caret as a pipe ('|') here...
|
||||
if (isActive()) {
|
||||
textBuffer.insert(caretPosition, '|');
|
||||
}
|
||||
g.setColor(getForeground());
|
||||
g.setFont(LFancyLabel.DEFAULT_FONT);
|
||||
g.drawString(getText(),
|
||||
getBounds().x + 3,
|
||||
getBounds().y + getBounds().height - 5);
|
||||
|
||||
//XXX: Continued:
|
||||
if (isActive()) {
|
||||
textBuffer.deleteCharAt(caretPosition);
|
||||
}
|
||||
|
||||
//Reset clipping. Again 'cause I'm lazy and don't want to compute
|
||||
//which parts of the string to render myself:
|
||||
g2d.setClip(oldClippie);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
//import java.awt.FontMetrics;
|
||||
//import java.awt.GraphicsEnvironment;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
//import java.util.Date;
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
//import java.util.Iterator;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
|
||||
/**
|
||||
* Class LToggleButton: this is the ltogglebutton class.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 14, 2004) - Created the LToggleButton class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 14, 2004
|
||||
*/
|
||||
public final class LToggleButton extends LAbstractButton
|
||||
implements ActionListener {
|
||||
|
||||
/**
|
||||
* The text to display on this button.
|
||||
*/
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* The image to display on this button.
|
||||
*/
|
||||
private AnimatedSprite image;
|
||||
|
||||
/**
|
||||
* Set to true if this button is selected, or false if it is not.
|
||||
*/
|
||||
private boolean selected;
|
||||
|
||||
/**
|
||||
* The color of the button when it is unselected.
|
||||
*/
|
||||
private Color unselectedColor = new Color(1.0f, 1.0f, 1.0f, 0.1f);
|
||||
|
||||
/**
|
||||
* The color of the button when it is selected.
|
||||
*/
|
||||
private Color selectedColor = new Color(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
|
||||
/**
|
||||
* Describe variable <code>coord</code> here.
|
||||
*
|
||||
*/
|
||||
private Point coord = new Point();
|
||||
|
||||
/**
|
||||
* Creates a new <code>LToggleButton</code> instance.
|
||||
*/
|
||||
public LToggleButton() {
|
||||
super();
|
||||
|
||||
text = "LToggleButton";
|
||||
image = null;
|
||||
|
||||
setSelected(false);
|
||||
addActionListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text displayed on this button.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public String getText() {
|
||||
return (this.text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new value of the text on this button.
|
||||
*
|
||||
* @param v a <code>String</code> value
|
||||
*/
|
||||
public void setText(String v) {
|
||||
this.text = v;
|
||||
setActionCommand(text);
|
||||
image = null;
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image displayed on this button.
|
||||
*
|
||||
* @return an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public AnimatedSprite getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new value for the image of this button.
|
||||
*
|
||||
* @param newImage an <code>AnimatedSprite</code> value
|
||||
*/
|
||||
public void setImage(AnimatedSprite newImage) {
|
||||
image = newImage;
|
||||
setActionCommand(newImage.getAnimation().getFileName());
|
||||
text = null;
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>updateDimensions</code> method here.
|
||||
*
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
if (text != null) {
|
||||
/*
|
||||
//We are updating due to changes in text:
|
||||
FontMetrics metrics = new FontMetrics(LFancyLabel.DEFAULT_FONT);
|
||||
|
||||
setSize(metrics.charsWidth(text.toCharArray(), 0,
|
||||
text.length()), metrics.getHeight());
|
||||
*/
|
||||
|
||||
//Hack. Must make the size be actually dependent on text...
|
||||
setSize(100, 100);
|
||||
|
||||
} else if (image != null) {
|
||||
//We are updating due to image:
|
||||
int x = getBounds().x;
|
||||
int y = getBounds().y;
|
||||
Rectangle e = image.getAnimation().getExtent(image.getCurrentFrame());
|
||||
|
||||
if (LApplication.VERBOSE) {
|
||||
System.out.println("LButton: Coords - (" + x + ", " + y + ")");
|
||||
System.out.println(" Extent - " + e);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
setBounds(e);
|
||||
getBounds().translate(x, y);
|
||||
} else {
|
||||
//Both text and image are null... Bad.
|
||||
throw new NullPointerException("Both text and image are null.");
|
||||
}
|
||||
|
||||
makeDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the button is currently selected.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setSelected</code> method here.
|
||||
*
|
||||
* @param v a <code>boolean</code> value
|
||||
*/
|
||||
public void setSelected(boolean v) {
|
||||
selected = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the selection on the button.
|
||||
*/
|
||||
public void toggleSelected() {
|
||||
if (isSelected()) {
|
||||
setSelected(false);
|
||||
} else {
|
||||
setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
LToggleButton target = (LToggleButton) component;
|
||||
|
||||
target.setActionListeners(getActionListeners());
|
||||
target.setActionCommand(this.getActionCommand());
|
||||
target.text = this.getText();
|
||||
target.image = this.getImage();
|
||||
target.updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
java.awt.Graphics2D gr = (java.awt.Graphics2D) g;
|
||||
Rectangle bounds = this.getBounds();
|
||||
|
||||
//Render background:
|
||||
if (selected) {
|
||||
gr.setColor(selectedColor);
|
||||
} else {
|
||||
gr.setColor(unselectedColor);
|
||||
}
|
||||
gr.fill(bounds);
|
||||
|
||||
if (text != null) {
|
||||
//Render text button...
|
||||
g.setColor(Color.black);
|
||||
g.setFont(LFancyLabel.DEFAULT_FONT);
|
||||
|
||||
//Render border first:
|
||||
g.draw3DRect(bounds.x - 5, bounds.y - 5,
|
||||
bounds.width + 5, bounds.height + 5, true);
|
||||
|
||||
//Render text:
|
||||
g.drawString(getText(), bounds.x, bounds.y);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (image != null) {
|
||||
//Render image button...
|
||||
Rectangle e = image.getAnimation().getExtent(image.getCurrentFrame());
|
||||
|
||||
coord.x = bounds.x - e.x;
|
||||
coord.y = bounds.y - e.y;
|
||||
|
||||
return image.renderSprite(g, coord);
|
||||
|
||||
} else {
|
||||
//No text, no image... :/
|
||||
throw new NullPointerException("Both text and image are null.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>actionPerformed</code> method here.
|
||||
*
|
||||
* @param e an <code>ActionEvent</code> value
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
toggleSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.BasicStroke;
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.LevelData;
|
||||
import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
/**
|
||||
* Class LevelButton: This is essentially the button that shows the
|
||||
* name of the level, it's thumbnail, and some statistics.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Mar. 29, 2004) - Created the LevelButton class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Mar. 29, 2004
|
||||
*/
|
||||
public class LevelButton extends LAbstractButton {
|
||||
|
||||
/**
|
||||
* The data associated with this level button.
|
||||
*/
|
||||
private LevelData data;
|
||||
|
||||
/**
|
||||
* The preview of the level.
|
||||
*/
|
||||
//private LIcon preview; //Make this the minimap, eventually.
|
||||
|
||||
/**
|
||||
* The label containing the level name.
|
||||
*/
|
||||
private LFancyLabel lblLevelName;
|
||||
|
||||
/**
|
||||
* The label that will show the number of lemmings to be released.
|
||||
*/
|
||||
private LLabel lblNumLemmings;
|
||||
|
||||
/**
|
||||
* The label that will show the percentage of lemmings to be saved.
|
||||
*/
|
||||
private LLabel lblSavePercent;
|
||||
|
||||
/**
|
||||
* The label that will show the time limit on the level.
|
||||
*/
|
||||
private LLabel lblTimeLimit;
|
||||
|
||||
/**
|
||||
* Set to true if this button is selected, or false if it is not.
|
||||
*/
|
||||
private boolean selected;
|
||||
|
||||
/**
|
||||
* The stroke to use for the border of the button.
|
||||
*/
|
||||
private Stroke borderStroke = new BasicStroke(3.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_ROUND);
|
||||
|
||||
/**
|
||||
* The color of the border of the button.
|
||||
*/
|
||||
private Color borderColor = Color.black;
|
||||
|
||||
/**
|
||||
* The color of the button when it is unselected.
|
||||
*/
|
||||
private Color unselectedColor = new Color(1.0f, 1.0f, 1.0f, 0.1f);
|
||||
|
||||
/**
|
||||
* The color of the button when it is selected.
|
||||
*/
|
||||
private Color selectedColor = new Color(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelButton</code> instance.
|
||||
*
|
||||
* @param levelName The id associated with the level we would like
|
||||
* to display in this button.
|
||||
*/
|
||||
public LevelButton(String levelName) {
|
||||
//Initialize the preview here:
|
||||
//preview = new LIcon();
|
||||
setActionCommand(levelName);
|
||||
|
||||
//Initialize the labels:
|
||||
lblLevelName = new LFancyLabel();
|
||||
lblLevelName.setFont(LFancyLabel.DEFAULT_FONT
|
||||
.deriveFont(Font.BOLD, 20.0f));
|
||||
lblLevelName.setShown(true);
|
||||
|
||||
lblNumLemmings = new LLabel();
|
||||
lblNumLemmings.setShown(true);
|
||||
|
||||
lblSavePercent = new LLabel();
|
||||
lblSavePercent.setShown(true);
|
||||
|
||||
lblTimeLimit = new LLabel();
|
||||
lblTimeLimit.setShown(true);
|
||||
|
||||
setLevel(levelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the button is currently selected.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>setSelected</code> method here.
|
||||
*
|
||||
* @param v a <code>boolean</code> value
|
||||
*/
|
||||
public void setSelected(boolean v) {
|
||||
selected = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the selection on the button.
|
||||
*/
|
||||
public void toggleSelected() {
|
||||
if (isSelected()) {
|
||||
setSelected(false);
|
||||
} else {
|
||||
setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the data when need be.
|
||||
*/
|
||||
private void updateData() {
|
||||
lblLevelName.setText(data.getName());
|
||||
|
||||
lblNumLemmings.setText("Lemmings: " + data.getNumLemmings());
|
||||
lblSavePercent.setText("Save: " + data.getPercentToSave() + "%");
|
||||
lblTimeLimit.setText("Time: " + data.getTimeLimit() + " seconds");
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
int x = getBounds().x;
|
||||
int y = getBounds().y;
|
||||
|
||||
x += 120;
|
||||
y += 25;
|
||||
|
||||
lblLevelName.setPosition(new Point(x, y));
|
||||
y += 5;
|
||||
|
||||
lblNumLemmings.setPosition(new Point(x, y));
|
||||
y += lblNumLemmings.getBounds().height + 5;
|
||||
|
||||
lblSavePercent.setPosition(new Point(x, y));
|
||||
y += lblSavePercent.getBounds().height + 5;
|
||||
|
||||
lblTimeLimit.setPosition(new Point(x, y));
|
||||
|
||||
getBounds().width = 350;
|
||||
getBounds().height = 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up to display the level with the specified id.
|
||||
*
|
||||
* @param name a <code>String</code> value
|
||||
* name cannot be found.
|
||||
*/
|
||||
public final void setLevel(String name) {
|
||||
data = LevelReader.getInstance().loadLevelData(name);
|
||||
setActionCommand(name);
|
||||
|
||||
if (data == null) {
|
||||
throw new NullPointerException("No data for level \"" + name
|
||||
+ "\" found...");
|
||||
}
|
||||
|
||||
updateData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
//Bah, we won't be doing any *copying*, shall we?
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
java.awt.Graphics2D gr = (java.awt.Graphics2D) g;
|
||||
Rectangle r = getBounds();
|
||||
|
||||
//Render button background:
|
||||
if (selected) {
|
||||
gr.setColor(selectedColor);
|
||||
} else {
|
||||
gr.setColor(unselectedColor);
|
||||
}
|
||||
gr.fill(r);
|
||||
|
||||
//Render border around the button:
|
||||
gr.setStroke(borderStroke);
|
||||
gr.setColor(borderColor);
|
||||
gr.draw(r);
|
||||
|
||||
//Render labels 'n things:
|
||||
lblLevelName.makeDirty();
|
||||
lblLevelName.renderAll(g);
|
||||
|
||||
lblNumLemmings.makeDirty();
|
||||
lblNumLemmings.renderAll(g);
|
||||
|
||||
lblSavePercent.makeDirty();
|
||||
lblSavePercent.renderAll(g);
|
||||
|
||||
lblTimeLimit.makeDirty();
|
||||
lblTimeLimit.renderAll(g);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
//import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
//import java.awt.Stroke;
|
||||
import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
//import java.awt.BasicStroke;
|
||||
|
||||
//import java.util.List;
|
||||
//import java.util.Vector;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.engine.LevelData;
|
||||
//import edu.gatech.cs2335.lemmings.file.LevelReader;
|
||||
|
||||
//import java.awt.Point;
|
||||
//import java.awt.Color;
|
||||
//import java.awt.Rectangle;
|
||||
//import java.awt.Graphics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import java.util.List;
|
||||
//import java.util.Vector;
|
||||
//import java.util.Iterator;
|
||||
|
||||
//import java.awt.Point;
|
||||
|
||||
//import java.awt.event.ActionEvent;
|
||||
|
||||
//import edu.gatech.cs2335.lemmings.gui.LIcon;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LButton;
|
||||
//import edu.gatech.cs2335.lemmings.gui.LRootPane;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Looping;
|
||||
import edu.gatech.cs2335.lemmings.graphics.Direction;
|
||||
import edu.gatech.cs2335.lemmings.graphics.AnimatedSprite;
|
||||
import edu.gatech.cs2335.lemmings.graphics.TileSetManager;
|
||||
|
||||
/**
|
||||
* Class LevelContainer: Basically a panel that contains level buttons.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 11, 2004) - Created the LevelContainer class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 11, 2004
|
||||
*/
|
||||
public final class LevelContainer extends LContainer
|
||||
implements ActionListener, IMouseWheelable {
|
||||
|
||||
/**
|
||||
* Show debug output?
|
||||
*/
|
||||
public static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* The number of pixels to put between the buttons.
|
||||
*/
|
||||
public static final int SPACING = 15;
|
||||
|
||||
/**
|
||||
* How many levels shall we display at once?
|
||||
*/
|
||||
private static final int ENTRIES_PER_PAGE = 8;
|
||||
|
||||
/**
|
||||
* Contains the id of the currently selected level.
|
||||
*/
|
||||
private String selectedLevel;
|
||||
|
||||
/**
|
||||
* Describe variable <code>up</code> here.
|
||||
*
|
||||
*/
|
||||
private LButton up;
|
||||
|
||||
/**
|
||||
* Describe variable <code>down</code> here.
|
||||
*
|
||||
*/
|
||||
private LButton down;
|
||||
|
||||
/**
|
||||
* The index of the currently displayed item.
|
||||
*/
|
||||
private int currentIndex;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LevelContainer</code> instance.
|
||||
*/
|
||||
public LevelContainer() {
|
||||
//Add the scroller buttons:
|
||||
up = new LButton();
|
||||
up.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("scroll_up"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
up.setPosition(new Point(0, 0));
|
||||
up.setShown(true);
|
||||
up.setActionCommand("scroll_btn_up");
|
||||
up.addActionListener(this);
|
||||
|
||||
down = new LButton();
|
||||
down.setImage(new AnimatedSprite(TileSetManager.getInstance()
|
||||
.getTileSet("scroll_down"),
|
||||
Direction.NO_DIRECTION,
|
||||
Looping.NONE));
|
||||
down.setPosition(new Point(0, 0));
|
||||
down.setShown(true);
|
||||
down.setActionCommand("scroll_btn_down");
|
||||
down.addActionListener(this);
|
||||
|
||||
addChild(up);
|
||||
addChild(down);
|
||||
|
||||
currentIndex = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected synchronized void updateDimensions() {
|
||||
Rectangle r = getBounds();
|
||||
|
||||
up.setPosition(new Point(r.x + r.width, r.y));
|
||||
down.setPosition(new Point(r.x + r.width, r.y + r.height));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a level button for the specified level id.
|
||||
*
|
||||
* @param levelId a <code>String</code> value
|
||||
*/
|
||||
public synchronized void addLevelButton(String levelId) {
|
||||
List children = getChildren();
|
||||
int numButtons = children.size();
|
||||
// boolean left = ((numButtons % 2) == 0);
|
||||
|
||||
//Create new Level Button:
|
||||
LevelButton butt = new LevelButton(levelId);
|
||||
// butt.setShown(true);
|
||||
butt.addActionListener(this);
|
||||
|
||||
/*
|
||||
Point coords = new Point();
|
||||
if (numButtons == 0) {
|
||||
//This is the first button:
|
||||
coords.x = getBounds().x;
|
||||
coords.y = getBounds().y;
|
||||
} else if (left) {
|
||||
//This is not the first button, but it will be in the left column:
|
||||
LComponent pc = (LComponent) children.get(children.size() - 2);
|
||||
coords.x = getBounds().x;
|
||||
coords.y = pc.getBounds().y + pc.getBounds().height + SPACING;
|
||||
} else {
|
||||
//This is not the first button, and it will be in the right column:
|
||||
LComponent pc = (LComponent) children.get(children.size() - 1);
|
||||
coords.x = pc.getBounds().x + pc.getBounds().width + SPACING;
|
||||
coords.y = pc.getBounds().y;
|
||||
}
|
||||
|
||||
butt.setPosition(coords);
|
||||
*/
|
||||
|
||||
addChild(butt);
|
||||
updateShownLevels();
|
||||
|
||||
if (numButtons == 0) {
|
||||
setSelectedButton(levelId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the selected button.
|
||||
*
|
||||
* @param id a <code>String</code> value
|
||||
*/
|
||||
protected synchronized void setSelectedButton(String id) {
|
||||
List children = getChildren();
|
||||
|
||||
for (int i = 2; i < children.size(); i++) {
|
||||
LevelButton butt = (LevelButton) children.get(i);
|
||||
|
||||
if (!id.equals(butt.getActionCommand())) {
|
||||
if (butt.isSelected()) {
|
||||
butt.setSelected(false);
|
||||
}
|
||||
} else {
|
||||
if (!butt.isSelected()) {
|
||||
butt.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remember Selected Level:
|
||||
selectedLevel = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getSelectedLevel</code> method here.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public synchronized String getSelectedLevel() {
|
||||
return selectedLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>actionPerformed</code> method here.
|
||||
*
|
||||
* @param e an <code>ActionEvent</code> value
|
||||
*/
|
||||
public synchronized void actionPerformed(ActionEvent e) {
|
||||
//Is it up or down button?
|
||||
String c = e.getActionCommand();
|
||||
|
||||
if ("scroll_btn_up".equals(c)) {
|
||||
scrollUp();
|
||||
|
||||
} else if ("scroll_btn_down".equals(c)) {
|
||||
scrollDown();
|
||||
|
||||
} else {
|
||||
//Update the selection.
|
||||
setSelectedButton(e.getActionCommand());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls up.
|
||||
*/
|
||||
private synchronized void scrollUp() {
|
||||
if (currentIndex <= 2) {
|
||||
currentIndex = 2;
|
||||
|
||||
} else {
|
||||
currentIndex -= 2;
|
||||
|
||||
}
|
||||
|
||||
updateShownLevels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls down.
|
||||
*/
|
||||
private synchronized void scrollDown() {
|
||||
if (getChildren().size() - 2 < ENTRIES_PER_PAGE) {
|
||||
return;
|
||||
}
|
||||
if (currentIndex >= getChildren().size() - ENTRIES_PER_PAGE) {
|
||||
currentIndex = getChildren().size() - ENTRIES_PER_PAGE;
|
||||
if ((currentIndex % 2) == 1) {
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
} else {
|
||||
currentIndex += 2;
|
||||
|
||||
}
|
||||
|
||||
updateShownLevels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows those level which need to be shown and hides other ones.
|
||||
*/
|
||||
private synchronized void updateShownLevels() {
|
||||
List children = getChildren();
|
||||
int numButtons = children.size();
|
||||
int curNum = 0;
|
||||
boolean left = false;
|
||||
Point coords = new Point();
|
||||
|
||||
for (int i = 2; i < numButtons; i++) {
|
||||
LComponent butt = (LComponent) children.get(i);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("");
|
||||
System.err.println("LevelContainer: Got Child #" + i);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
if (i >= currentIndex && i < currentIndex + ENTRIES_PER_PAGE) {
|
||||
curNum = i - currentIndex;
|
||||
left = ((curNum % 2) == 0);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("\tIndex Into Viewport: " + curNum);
|
||||
System.err.println("\tLeft column? " + left);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
//Show:
|
||||
butt.setShown(true);
|
||||
//butt.bringToTop();
|
||||
|
||||
//Set Position:
|
||||
coords.x = 0;
|
||||
coords.y = 0;
|
||||
|
||||
if (curNum == 0) {
|
||||
//This is the first button:
|
||||
coords.x = getBounds().x;
|
||||
coords.y = getBounds().y + SPACING;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("\tFirst Button...");
|
||||
System.err.println("\t\tX - " + coords.x);
|
||||
System.err.println("\t\tY - " + coords.y);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
} else if (left) {
|
||||
//This is not the first button, but it will be in the left column:
|
||||
LComponent pc = (LComponent) children.get(i - 2);
|
||||
coords.x = getBounds().x;
|
||||
coords.y = pc.getBounds().y + pc.getBounds().height + SPACING;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("\tLeft Column...");
|
||||
System.err.println("\t\tX - " + coords.x);
|
||||
System.err.println("\t\tY - " + coords.y);
|
||||
System.err.flush();
|
||||
}
|
||||
} else {
|
||||
//This is not the first button, and it will be in the right column:
|
||||
LComponent pc = (LComponent) children.get(i - 1);
|
||||
coords.x = pc.getBounds().x + pc.getBounds().width + SPACING;
|
||||
coords.y = pc.getBounds().y;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.err.println("\tRight Column...");
|
||||
System.err.println("\t\tX - " + coords.x);
|
||||
System.err.println("\t\tY - " + coords.y);
|
||||
System.err.flush();
|
||||
}
|
||||
}
|
||||
|
||||
butt.setPosition(coords);
|
||||
|
||||
} else {
|
||||
//Hide:
|
||||
butt.setShown(false);
|
||||
// butt.setPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the mouse wheel rotation.
|
||||
*
|
||||
* @param numClicks The number of clicks the wheel was rotated. A
|
||||
* negative value means the wheel was rotated away from the user,
|
||||
* and positive means it was rotated towards the user.
|
||||
*/
|
||||
public synchronized void processMouseWheel(int numClicks) {
|
||||
if (numClicks < 0) {
|
||||
for (int i = numClicks; i < 0; i++) {
|
||||
scrollUp();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < numClicks; i++) {
|
||||
scrollDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
//Nothing (?) to paint here.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
package edu.gatech.cs2335.lemmings.gui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Color;
|
||||
//import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
//import java.awt.geom.Ellipse2D;
|
||||
//import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.BasicStroke;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
import edu.gatech.cs2335.lemmings.engine.Portal;
|
||||
import edu.gatech.cs2335.lemmings.engine.Lemming;
|
||||
import edu.gatech.cs2335.lemmings.engine.LevelExit;
|
||||
import edu.gatech.cs2335.lemmings.engine.LevelEntrance;
|
||||
|
||||
/**
|
||||
* Class MiniMap: Contains the minimap of a level.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 23, 2004) - Created the MiniMap class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @version Version 1.0, Apr. 23, 2004
|
||||
*/
|
||||
public final class MiniMap extends LLeafComponent {
|
||||
|
||||
/**
|
||||
* Describe variable <code>level</code> here.
|
||||
*
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* Stuff.
|
||||
*/
|
||||
private Dimension mapSize;
|
||||
|
||||
/**
|
||||
* Describe variable <code>scaleFactor</code> here.
|
||||
*
|
||||
*/
|
||||
private Rectangle2D.Double scaleFactor;
|
||||
|
||||
/**
|
||||
* This is a temporary variable to save the "normal" transformation
|
||||
* matrix.
|
||||
*/
|
||||
private AffineTransform saveAT;
|
||||
|
||||
/**
|
||||
* This is where the zoom transformation will be stored.
|
||||
*/
|
||||
private AffineTransform myTransform;
|
||||
|
||||
//Never got to this cool stuff. :( It's all ASCII art.
|
||||
// /**
|
||||
// * Describe variable <code>lemmingShape</code> here.
|
||||
// *
|
||||
// */
|
||||
// private Shape lemmingShape;
|
||||
|
||||
// /**
|
||||
// * Describe variable <code>entranceShape</code> here.
|
||||
// *
|
||||
// */
|
||||
// private Shape entranceShape;
|
||||
|
||||
// /**
|
||||
// * Describe variable <code>exitShape</code> here.
|
||||
// *
|
||||
// */
|
||||
// private Shape exitShape;
|
||||
|
||||
/**
|
||||
* The stroke to use for the border of the button.
|
||||
*/
|
||||
private Stroke borderStroke = new BasicStroke(3.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_ROUND);
|
||||
|
||||
/**
|
||||
* The color of the border of the button.
|
||||
*/
|
||||
private Color borderColor = Color.lightGray;
|
||||
|
||||
/**
|
||||
* Describe variable <code>coords</code> here.
|
||||
*
|
||||
*/
|
||||
private Point coords;
|
||||
|
||||
/**
|
||||
* Creates a new <code>MiniMap</code> instance.
|
||||
* @param l a <code>Level</code> value
|
||||
*/
|
||||
public MiniMap(Level l) {
|
||||
mapSize = new Dimension();
|
||||
myTransform = new AffineTransform();
|
||||
scaleFactor = new Rectangle2D.Double();
|
||||
|
||||
coords = new Point();
|
||||
|
||||
setLevel(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of level.
|
||||
* @return value of level.
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of level.
|
||||
* @param v Value to assign to level.
|
||||
*/
|
||||
public void setLevel(Level v) {
|
||||
this.level = v;
|
||||
|
||||
updateDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>worldToMini</code> method here.
|
||||
*
|
||||
* @param p a <code>Point</code> value
|
||||
*/
|
||||
protected void worldToMini(Point p) {
|
||||
p.x *= scaleFactor.width;
|
||||
p.y *= scaleFactor.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds of the button.
|
||||
*/
|
||||
protected void updateDimensions() {
|
||||
//Update map size:
|
||||
mapSize.width = level.getMap().getMap().getWidth();
|
||||
mapSize.height = level.getMap().getMap().getHeight();
|
||||
|
||||
//Update affine:
|
||||
int width = getBounds().width;
|
||||
int height = getBounds().height;
|
||||
|
||||
scaleFactor.width = (1.0 * width) / mapSize.width;
|
||||
scaleFactor.height = (1.0 * height) / mapSize.height;
|
||||
|
||||
myTransform.setToScale(scaleFactor.width, scaleFactor.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-copies self <b>into the component</b> passed in.
|
||||
*
|
||||
* @param component a <code>LComponent</code> value
|
||||
*/
|
||||
protected void copy(LComponent component) {
|
||||
//Blah. It's 3:33am. I'm not going to go around implementing
|
||||
//useless methods!
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all of the necessary drawing for this control only. The
|
||||
* children will be taken care of separately. This method need not
|
||||
* concern itself with them.
|
||||
*
|
||||
* @param g a <code>Graphics</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
protected boolean paint(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
//Render black background:
|
||||
g2d.setColor(Color.black);
|
||||
g2d.fill(getBounds());
|
||||
|
||||
//Render border around the button:
|
||||
g2d.setStroke(borderStroke);
|
||||
g2d.setColor(borderColor);
|
||||
g2d.draw(getBounds());
|
||||
|
||||
//Render the map itself:
|
||||
saveAT = g2d.getTransform();
|
||||
g2d.setTransform(myTransform);
|
||||
|
||||
g2d.drawImage(level.getMap().getGameMap(), null,
|
||||
(int) (getBounds().x / scaleFactor.width),
|
||||
(int) (getBounds().y / scaleFactor.height));
|
||||
|
||||
g2d.setTransform(saveAT);
|
||||
|
||||
//Render lemmings:
|
||||
g2d.setColor(Color.pink);
|
||||
for (int i = 0; i < level.getActiveLemmings().size(); i++) {
|
||||
Lemming l = (Lemming) level.getActiveLemmings().get(i);
|
||||
coords.x = l.getPosition().getX();
|
||||
coords.y = l.getPosition().getY();
|
||||
|
||||
worldToMini(coords);
|
||||
|
||||
g2d.drawString(".", coords.x + getBounds().x, coords.y + getBounds().y);
|
||||
}
|
||||
|
||||
//Render portals:
|
||||
for (int v = 0; v < level.getLevelPortals().size(); v++) {
|
||||
Portal p = (Portal) level.getLevelPortals().get(v);
|
||||
|
||||
coords.x = p.getPhysics().getPosition().getX();
|
||||
coords.y = p.getPhysics().getPosition().getY();
|
||||
|
||||
worldToMini(coords);
|
||||
|
||||
if (p instanceof LevelEntrance) {
|
||||
g2d.setColor(Color.yellow);
|
||||
|
||||
g2d.drawString("V",
|
||||
coords.x + getBounds().x,
|
||||
coords.y + getBounds().y);
|
||||
} else if (p instanceof LevelExit) {
|
||||
g2d.setColor(Color.green);
|
||||
|
||||
g2d.drawString("H",
|
||||
coords.x + getBounds().x,
|
||||
coords.y + getBounds().y);
|
||||
} else {
|
||||
g2d.setColor(Color.red);
|
||||
|
||||
g2d.drawString("X",
|
||||
coords.x + getBounds().x,
|
||||
coords.y + getBounds().y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class AbstractMessage: This class is the base for all network
|
||||
* messages that will be sent between the client and the server. All
|
||||
* of the more specific message classes will be derived from it and
|
||||
* will add more and more spcific functionality onto the basics
|
||||
* provided in this class.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 8, 2004) - Created the AbstractMessage class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg563g@mail.gatech.edu">Daniyar Zhanbekov</A>
|
||||
* @version Version 1.0, Apr 8, 2004
|
||||
*/
|
||||
|
||||
public abstract class AbstractMessage {
|
||||
|
||||
/**
|
||||
* This variable contains the four-character code for the message,
|
||||
* like: HELO, or QUIT.
|
||||
*/
|
||||
private String messageType;
|
||||
|
||||
/**
|
||||
* This string contains the name of the sender of this message,
|
||||
* which will either be "Server" for server messages, or the name of
|
||||
* the user for clients.
|
||||
*/
|
||||
private String messageAuthor;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AbstractMessage</code> instance.
|
||||
*/
|
||||
public AbstractMessage() {
|
||||
this(MessageSettings.TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AbstractMessage</code> instance.
|
||||
*
|
||||
* @param type a <code>String</code> value
|
||||
*/
|
||||
public AbstractMessage(final String type) {
|
||||
this(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AbstractMessage</code> instance.
|
||||
*
|
||||
* @param type a <code>String</code> value
|
||||
* @param author a <code>String</code> value
|
||||
*/
|
||||
public AbstractMessage(final String type, final String author) {
|
||||
messageType = type;
|
||||
messageAuthor = author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message type.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new message type.
|
||||
*
|
||||
* @param newType a <code>String</code> value
|
||||
*/
|
||||
protected final void setMessageType(final String newType) {
|
||||
this.messageType = newType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message type of the message string passed in.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public static String getMessageType(final String message) {
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (message.length() < MessageSettings.TYPE_LENGTH) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (message.indexOf("\037".charAt(0)) != MessageSettings.TYPE_LENGTH) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return message.substring(0, MessageSettings.TYPE_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the user that sent out the message.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String getAuthor() {
|
||||
return messageAuthor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives message author a new value.
|
||||
*
|
||||
* @param author a <code>String</code> value
|
||||
*/
|
||||
public final void setAuthor(final String author) {
|
||||
this.messageAuthor = author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the message fit for plain-text
|
||||
* transmission over the network.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public abstract String tokenize();
|
||||
|
||||
/**
|
||||
* Parses the string into the specific message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage parse(final String message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message from the data provided.
|
||||
*
|
||||
* @param data a <code>List</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Class ChangeLemmingFlowMessage: Sent to change lemming flow.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (April 08, 2004) - Created the ChangeSpeedMessage class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0,April 08 , 2004
|
||||
*/
|
||||
public class ChangeLemmingFlowMessage extends AbstractMessage {
|
||||
|
||||
/**
|
||||
* Speed associated with this message
|
||||
*/
|
||||
private int flowRate;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ChangeLemmingFlowMessage</code> instance.
|
||||
*
|
||||
* @param userName a <code>String</code> value
|
||||
*/
|
||||
public ChangeLemmingFlowMessage(final String userName) {
|
||||
super(MessageSettings.TYPE_FLOW, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message from the data provided.
|
||||
*
|
||||
* @param data a <code>List</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
if (data == null || (data.size() != 2)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String name = (String) (data.get(0));
|
||||
ChangeLemmingFlowMessage clfm = new ChangeLemmingFlowMessage(name);
|
||||
clfm.setLemmingFlow(((Integer) data.get(1)).intValue());
|
||||
|
||||
return clfm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the message fit for plain-text
|
||||
* transmission over the network.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String tokenize() {
|
||||
String message = getMessageType() + "\037" + getAuthor()
|
||||
+ "\037" + Integer.toString(flowRate);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string into the specific message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage parse(final String message) {
|
||||
String type = getMessageType(message);
|
||||
String name;
|
||||
StringTokenizer st = null;
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!type.equals(MessageSettings.TYPE_FLOW)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
st = new StringTokenizer(message, "\037");
|
||||
|
||||
//Message type:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
type = st.nextToken();
|
||||
|
||||
//Username:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
name = st.nextToken();
|
||||
|
||||
ChangeLemmingFlowMessage clfm = new ChangeLemmingFlowMessage(name);
|
||||
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
try {
|
||||
clfm.setLemmingFlow(Integer.parseInt(st.nextToken()));
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return clfm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for speed int
|
||||
* @return int , speed
|
||||
*/
|
||||
public int getLemmingFlow() {
|
||||
return flowRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier for speed int
|
||||
* @param flow , int for speed
|
||||
*/
|
||||
public void setLemmingFlow(int flow) {
|
||||
this.flowRate = flow;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Class ChangeSpeedMessage: Sent to change speed of game.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (April 08, 2004) - Created the ChangeSpeedMessage class.
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0,April 08 , 2004
|
||||
*/
|
||||
public class ChangeSpeedMessage extends AbstractMessage {
|
||||
|
||||
/**
|
||||
* Speed associated with this message.
|
||||
*/
|
||||
private int speed;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ChangeSpeedMessage</code> instance.
|
||||
*
|
||||
* @param userName a <code>String</code> value.
|
||||
*/
|
||||
public ChangeSpeedMessage(final String userName) {
|
||||
super(MessageSettings.TYPE_SPEED, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message from the data provided.
|
||||
*
|
||||
* @param data a <code>List</code> value.
|
||||
* @return an <code>AbstractMessage</code> value.
|
||||
*/
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
if (data == null || (data.size() != 2)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String name = (String) (data.get(0));
|
||||
ChangeSpeedMessage csm = new ChangeSpeedMessage(name);
|
||||
csm.setSpeed(((Integer) data.get(1)).intValue());
|
||||
|
||||
return csm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the message fit for plain-text
|
||||
* transmission over the network.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String tokenize() {
|
||||
String message = getMessageType() + "\037" + getAuthor()
|
||||
+ "\037" + Integer.toString(speed);
|
||||
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string into the specific message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage parse(final String message) {
|
||||
String type = getMessageType(message);
|
||||
String name;
|
||||
StringTokenizer st = null;
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!type.equals(MessageSettings.TYPE_SPEED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
st = new StringTokenizer(message, "\037");
|
||||
|
||||
//Message type:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
type = st.nextToken();
|
||||
|
||||
//Username:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
name = st.nextToken();
|
||||
|
||||
ChangeSpeedMessage csm = new ChangeSpeedMessage(name);
|
||||
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
try {
|
||||
csm.setSpeed(Integer.parseInt(st.nextToken()));
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return csm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for speed int.
|
||||
* @return int , speed
|
||||
*/
|
||||
public int getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier for speed int.
|
||||
* @param s , int for speed
|
||||
*/
|
||||
public void setSpeed(int s) {
|
||||
this.speed = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
|
||||
//import java.security.InvalidParameterException;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//import java.io.*;
|
||||
|
||||
//import java.net.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
//import java.io.PrintWriter;
|
||||
|
||||
//import java.io.OutputStreamWriter;
|
||||
|
||||
//import java.util.List;
|
||||
|
||||
//import java.util.Vector;
|
||||
|
||||
//import java.util.Date;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
public class ConnectionListener implements Runnable {
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
private int port;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
private long timeout;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* This variable is used to track whether the server is still
|
||||
|
||||
* alive. When it dies, it will simply set the serverQuit variable
|
||||
|
||||
* to true and this thread will terminate.
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
private boolean clientQuit;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*@param port p
|
||||
|
||||
*@param timeout t
|
||||
|
||||
*/
|
||||
|
||||
public ConnectionListener(int port, long timeout) {
|
||||
|
||||
this.port = port;
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
this.clientQuit = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* main thread establishes a server socket and accepts client
|
||||
|
||||
*/
|
||||
|
||||
public final void run() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
clientQuit = false;
|
||||
|
||||
ServerSocket serverSocket = null;
|
||||
|
||||
Socket clientSocket = null;
|
||||
|
||||
//opening a server socket
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
serverSocket = new ServerSocket(port);
|
||||
|
||||
|
||||
|
||||
} catch (IOException ioe) {
|
||||
|
||||
System.err.println("ConnectionListener:"
|
||||
|
||||
+ " Could not open server socket on port "
|
||||
|
||||
+ port + "\n");
|
||||
|
||||
System.err.println("IOException: " + ioe.getMessage() + "\n");
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Check if the socket is valid.
|
||||
|
||||
if (serverSocket == null || !serverSocket.isBound()) {
|
||||
|
||||
System.err.println("ConnectionListener: got bad socket \n");
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//keep waiting for connections
|
||||
|
||||
try {
|
||||
|
||||
while (!clientQuit) {
|
||||
|
||||
clientSocket = serverSocket.accept();
|
||||
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
|
||||
System.err.println("ConnectionListener: Couldn't accept connection: \n"
|
||||
|
||||
+ ioe.getMessage());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Class IdentificationMessage: Sends username to other player.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (April 08, 2004) - Created the IdentifiationMessage class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0,April 08 , 2004
|
||||
*/
|
||||
public class IdentificationMessage extends AbstractMessage {
|
||||
|
||||
/**
|
||||
* Creates a new <code>IdentificationMessage</code> instance.
|
||||
*
|
||||
* @param userName a <code>String</code> value
|
||||
*/
|
||||
public IdentificationMessage(final String userName) {
|
||||
super(MessageSettings.TYPE_HELO, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message from the data provided.
|
||||
*
|
||||
* @param data a <code>List</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
if (data == null || (data.size() != 1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new IdentificationMessage((String) (data.get(0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the message fit for plain-text
|
||||
* transmission over the network.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String tokenize() {
|
||||
String message = getMessageType() + "\037" + getAuthor();
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string into the specific message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage parse(final String message) {
|
||||
String type = getMessageType(message);
|
||||
String name;
|
||||
StringTokenizer st = null;
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!type.equals(MessageSettings.TYPE_HELO)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
st = new StringTokenizer(message, "\037");
|
||||
|
||||
//Message type:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
type = st.nextToken();
|
||||
|
||||
//Username:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
name = st.nextToken();
|
||||
|
||||
IdentificationMessage im = new IdentificationMessage(name);
|
||||
return im;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
//import java.util.Date;
|
||||
import java.net.Socket;
|
||||
//import java.net.ServerSocket;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import edu.gatech.cs2335.lemmings.graphics.Renderer;
|
||||
import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
import edu.gatech.cs2335.lemmings.engine.Level;
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
import edu.gatech.cs2335.lemmings.engine.GamePlayState;
|
||||
import java.awt.Rectangle;
|
||||
import edu.gatech.cs2335.lemmings.physics.Point;
|
||||
//import edu.gatech.cs2335.lemmings.gui.GamePlayPanel;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LemmingConnection {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contains the socket on which we want to listen to the server.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* A variable to keep track of when we should stop listening to the
|
||||
* server.
|
||||
*/
|
||||
private boolean clientQuit;
|
||||
|
||||
|
||||
/**
|
||||
*update
|
||||
*/
|
||||
private static final long UPDATE_FREQUENCY = 1;
|
||||
/**
|
||||
*update delay
|
||||
*/
|
||||
private static final long UPDATE_DELAY = (long) (UPDATE_FREQUENCY / 1000.0f);
|
||||
/**
|
||||
*verbose
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Creates a new <code>LemmingConnection</code> instance.
|
||||
* @param s a <code>Socket</code> value
|
||||
*/
|
||||
public LemmingConnection(Socket s) {
|
||||
socket = s;
|
||||
|
||||
if (!socket.isBound()) {
|
||||
throw new InvalidParameterException("LemmingConnection: "
|
||||
+ "Server socket not bound!\n");
|
||||
}
|
||||
|
||||
clientQuit = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>startListening</code> method here.
|
||||
*
|
||||
*/
|
||||
public void startListening() {
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection: Started listening...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
clientQuit = false;
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
String message = null;
|
||||
BufferedReader br = null;
|
||||
|
||||
//Open reader:
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(socket
|
||||
.getInputStream()));
|
||||
} catch (IOException ioe) {
|
||||
GameEngine.getInstance()
|
||||
.showNetworkError("Could not open connection to other player.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (!clientQuit) {
|
||||
//Get next message:
|
||||
try {
|
||||
message = br.readLine();
|
||||
|
||||
if (message == null) {
|
||||
throw new IOException("Server has dropped the connection.");
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
GameEngine.getInstance()
|
||||
.showNetworkError("Other player dropped connection...");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//send message to the LemmingNetworking
|
||||
LemmingNetworking.getInstance().receiveMessage(message);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection: Got message " + message);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
if (clientQuit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>startSending</code> method here.
|
||||
*
|
||||
*/
|
||||
public void startSending() {
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection: Started sending...");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
clientQuit = false;
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
long lastUpdate = System.currentTimeMillis();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("In Sending Thread. Starting While loop");
|
||||
}
|
||||
|
||||
while (!clientQuit) {
|
||||
|
||||
AbstractMessage am = getUpdateMessage();
|
||||
if (VERBOSE) {
|
||||
System.out.println("Got the Update(stats)Message");
|
||||
}
|
||||
// if (((GamePlayState) GameEngine.getInstance().getCurrentState())
|
||||
// .getGamePlayPanel().getRenderer() != null) {
|
||||
// AbstractMessage full = getFullUpdateMessage();
|
||||
// if (VERBOSE) {
|
||||
// System.out.println("got FullUpdateMessage");
|
||||
// }
|
||||
// if (full == null) {
|
||||
// continue;
|
||||
// }
|
||||
// if (VERBOSE) {
|
||||
// System.out.println("Full = " + full.tokenize());
|
||||
// }
|
||||
// sendMessage(full.tokenize());
|
||||
// }
|
||||
|
||||
|
||||
if (am == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
sendMessage(am.tokenize());
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection: sent message "
|
||||
+ am.tokenize());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
//Sleep some:
|
||||
lastUpdate += UPDATE_DELAY;
|
||||
try {
|
||||
Thread.sleep(Math
|
||||
.max(0, lastUpdate
|
||||
- System.currentTimeMillis()));
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
} finally {
|
||||
lastUpdate = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*@return boolean
|
||||
*/
|
||||
public boolean getClientQuit() {
|
||||
|
||||
return clientQuit;
|
||||
}
|
||||
|
||||
/**
|
||||
*mutator
|
||||
*@param value v
|
||||
*/
|
||||
public void setClientQuit(boolean value) {
|
||||
clientQuit = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getUpdateMessage</code> method here.
|
||||
*
|
||||
* @return an <code>AbstractNetworkMessage</code> value
|
||||
*/
|
||||
public AbstractMessage getUpdateMessage() {
|
||||
GamePlayState gps = null;
|
||||
|
||||
try {
|
||||
gps = (GamePlayState) GameEngine.getInstance().
|
||||
getCurrentState();
|
||||
} catch (ClassCastException cce) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Level l = gps.getLevel();
|
||||
|
||||
int lt = l.getNumLemmings();
|
||||
int lr = lt - l.getPendingLemmings().size();
|
||||
int ls = l.getLemmingsSaved();
|
||||
int ld = l.getActiveLemmings().size();
|
||||
|
||||
List data = new Vector();
|
||||
data.add("nUb");
|
||||
data.add(new Integer(lr));
|
||||
data.add(new Integer(ls));
|
||||
data.add(new Integer(ld));
|
||||
data.add(new Integer(lt));
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LC: ");
|
||||
System.out.println("\tPending: "
|
||||
+ l.getPendingLemmings().size());
|
||||
System.out.println("\tActive: "
|
||||
+ l.getActiveLemmings().size());
|
||||
System.out.println("\tKilled: "
|
||||
+ l.getLemmingHeaven().size());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
return MessageFactory.getInstance()
|
||||
.createMessage(MessageSettings.TYPE_STAT, data);
|
||||
}
|
||||
|
||||
/**
|
||||
*@return abstract message
|
||||
*/
|
||||
public AbstractMessage getFullUpdateMessage() {
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection"
|
||||
+ " inside getFullUpdateMessage");
|
||||
}
|
||||
|
||||
GamePlayState gps = null;
|
||||
|
||||
gps = (GamePlayState) GameEngine.getInstance()
|
||||
.getCurrentState();
|
||||
|
||||
|
||||
//Getting local data
|
||||
Level l = gps.getLevel();
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection"
|
||||
+ " getFullUpdateMessage gps.getLevel()" + l);
|
||||
}
|
||||
|
||||
|
||||
List lems = l.getActiveLemmings();
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection"
|
||||
+ " getFullUpdateMessage gps.ActiveLemmings()"
|
||||
+ lems.size());
|
||||
}
|
||||
|
||||
int savedLemmings = l.getLemmingsSaved();
|
||||
|
||||
GamePlayPanel gpp = gps.getGamePlayPanel();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection "
|
||||
+ " getFullUpdateMessage gps.getGamePlayPanel()"
|
||||
+ gpp);
|
||||
}
|
||||
|
||||
Renderer rend = gpp.getRenderer();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection "
|
||||
+ " getFullUpdateMessage gpp.getRenderer()" + rend);
|
||||
}
|
||||
|
||||
|
||||
Rectangle rect = rend.getMapViewPort();
|
||||
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("LemmingConnection "
|
||||
+ " getFullUpdateMessage rend.getMapViewPort()"
|
||||
+ rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int x = (int) rect.getX();
|
||||
int y = (int) rect.getY();
|
||||
Point point = new Point();
|
||||
point.setX(x);
|
||||
point.setY(y);
|
||||
|
||||
//Making list to build message from.
|
||||
List data = new Vector();
|
||||
data.add("nUb"); //Name
|
||||
data.add(point); //Viewpoint
|
||||
data.add(new Integer(savedLemmings)); //Num Lemmings saved
|
||||
//Num Lemmings out
|
||||
data.add(lems); //Added Lemmings to data.
|
||||
//data.add(terr); //terrain updates
|
||||
if (VERBOSE) {
|
||||
System.out.println("LC: ");
|
||||
System.out.println("\tSaved: "
|
||||
+ Integer.toString(l.getLemmingsSaved()));
|
||||
System.out.println("\tViewpoint x " + x);
|
||||
System.out.println("\tViewpoint y " + y);
|
||||
System.out.println("\tNumberActive: "
|
||||
+ l.getActiveLemmings().size());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
return MessageFactory.getInstance()
|
||||
.createMessage(MessageSettings.TYPE_UPDATE, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**Sends the abstract message to the client,
|
||||
*@param msg message
|
||||
*@return success/fail
|
||||
*/
|
||||
public boolean sendMessage(String msg) {
|
||||
|
||||
PrintWriter pr = null;
|
||||
|
||||
//Get output stream:
|
||||
try {
|
||||
pr = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
} catch (IOException ioe) {
|
||||
GameEngine.getInstance()
|
||||
.showNetworkError("Could not send message to other player.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Send message:
|
||||
pr.println(msg);
|
||||
pr.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*Stops the LemmingsConnection
|
||||
*/
|
||||
public void closeConnection() {
|
||||
clientQuit = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
//import java.io.PrintWriter;
|
||||
//import java.io.OutputStreamWriter;
|
||||
//import java.util.List;
|
||||
//import java.util.PhysicsVector;
|
||||
//import java.util.Date;
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import edu.gatech.cs2335.lemmings.engine.GameEngine;
|
||||
|
||||
/**
|
||||
* The <code>LemmingNetworking</code> class is the facade to the
|
||||
* entire package.
|
||||
*
|
||||
* @author <a href="mailto:gtg563g@gatech.edu">Daniyar Zhanbekov</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
public final class LemmingNetworking {
|
||||
|
||||
/**
|
||||
* Show debug output.
|
||||
*/
|
||||
private static final boolean VERBOSE = false;
|
||||
|
||||
/**
|
||||
* Implement as a singleton.
|
||||
*/
|
||||
private static LemmingNetworking instance = new LemmingNetworking();
|
||||
|
||||
/**
|
||||
* Lemming connection.
|
||||
*/
|
||||
private LemmingConnection connection;
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*
|
||||
* @return an <code>LemmingNetworking</code> value
|
||||
*/
|
||||
public static LemmingNetworking getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>listenForConnection</code> method here.
|
||||
*
|
||||
* @param port an <code>int</code> value
|
||||
*@return boolean
|
||||
*/
|
||||
public boolean listenForConnection(int port) {
|
||||
ServerSocket serverSocket = null;
|
||||
Socket clientSocket = null;
|
||||
|
||||
try {
|
||||
serverSocket = new ServerSocket(port);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
GameEngine.getInstance()
|
||||
.showNetworkError("Could not open server socket on port "
|
||||
+ port);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check if the socket is valid.
|
||||
if (serverSocket == null || !serverSocket.isBound()) {
|
||||
GameEngine.getInstance().showNetworkError("Could not use socket for "
|
||||
+ "connection.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
clientSocket = serverSocket.accept();
|
||||
} catch (IOException ioe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
connection = new LemmingConnection(clientSocket);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>connectTo</code> method here.
|
||||
*
|
||||
* @param host a <code>String</code> value
|
||||
* @param port an <code>int</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean connectTo(String host, int port) {
|
||||
Socket clientSocket = null;
|
||||
boolean connected = false;
|
||||
|
||||
try {
|
||||
//opening a client socket
|
||||
clientSocket = new Socket(host, port);
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
GameEngine.getInstance().showNetworkError("Could not find host: \""
|
||||
+ host + "\"");
|
||||
connected = false;
|
||||
return false;
|
||||
|
||||
} catch (IOException e) {
|
||||
GameEngine.getInstance().showNetworkError("Could not establish "
|
||||
+ "connection to host: \""
|
||||
+ host + "\"");
|
||||
connected = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
//since the socket is ok, starting a LemmingConnection
|
||||
connection = new LemmingConnection(clientSocket);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>shutDownNetworking</code> method here.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean shutDownNetworking() {
|
||||
if (connection != null) {
|
||||
connection.closeConnection();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>isConnected</code> method here.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
if (connection == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !connection.getClientQuit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>sendMessage</code> method here.
|
||||
*
|
||||
* @param message an <code>AbstractMessage</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean sendMessage(AbstractMessage message) {
|
||||
|
||||
String stringMessage = message.tokenize();
|
||||
|
||||
if (stringMessage == null) {
|
||||
GameEngine.getInstance().showNetworkError("Could not send message to "
|
||||
+ "other player. Connection"
|
||||
+ " dropped.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//call the LemmingConnection
|
||||
connection.sendMessage(stringMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>receiveMessage</code> method here.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
*/
|
||||
protected void receiveMessage(String message) {
|
||||
AbstractMessage msg = null;
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("Got Message:");
|
||||
System.out.println("\t" + message + "\n");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
msg = MessageFactory.getInstance().parseMessage(message);
|
||||
|
||||
if (msg == null) {
|
||||
//Got bad message format
|
||||
/*Who gives a shit?
|
||||
GameEngine.getInstance()
|
||||
.showNetworkError("Received malicious message from other player. "
|
||||
+ "Connection dropped.");
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
//forward the parsed message to the GameEngine
|
||||
GameEngine.getInstance().receiveMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe <code>getConnection</code> method here.
|
||||
*
|
||||
* @return a <code>LemmingConnection</code> value
|
||||
*/
|
||||
public LemmingConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
/**
|
||||
* Describe <code>getConnection</code> method here.
|
||||
*
|
||||
* @param client a <code>LemmingConnection</code> value
|
||||
*/
|
||||
|
||||
|
||||
protected void acceptConnection(Socket client) {
|
||||
connection = new LemmingConnection(client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
public class LevelFinishMessage extends AbstractMessage {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Creates a new <code>IdentificationMessage</code> instance.
|
||||
|
||||
*
|
||||
|
||||
* @param userName a <code>String</code> value
|
||||
|
||||
*/
|
||||
|
||||
public LevelFinishMessage(final String userName) {
|
||||
|
||||
super(MessageSettings.TYPE_LEVELEND, userName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Builds a message from the data provided.
|
||||
|
||||
*
|
||||
|
||||
* @param data a <code>List</code> value
|
||||
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
|
||||
*/
|
||||
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
@@ -0,0 +1,187 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class MessageFactory: Creates messages.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Apr. 8, 2004) - Created the MessageFactory class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg563g@mail.gatech.edu">Daniyar Zhanbekov</A>
|
||||
* @version Version 1.0, Jan. 26, 2004
|
||||
*/
|
||||
public final class MessageFactory {
|
||||
|
||||
/**
|
||||
* Implement as a singleton.
|
||||
*/
|
||||
private static MessageFactory instance;
|
||||
|
||||
/**
|
||||
* Creates a new <code>MessageFactory</code> instance.
|
||||
*/
|
||||
private MessageFactory() { }
|
||||
|
||||
/**
|
||||
* Singleton implementation.
|
||||
*
|
||||
* @return a <code>MessageFactory</code> value
|
||||
*/
|
||||
public static MessageFactory getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MessageFactory();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string passed in and returns the appropriate network message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
public AbstractMessage parseMessage(final String message) {
|
||||
String type = AbstractMessage.getMessageType(message);
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_PAUSE)) {
|
||||
return PauseMessage.parse(message);
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_UPDATE)) {
|
||||
return UpdateMessage.parse(message);
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_SPEED)) {
|
||||
return ChangeSpeedMessage.parse(message);
|
||||
}
|
||||
if (type.equals(MessageSettings.TYPE_STAT)) {
|
||||
return StatsMessage.parse(message);
|
||||
}
|
||||
if (type.equals(MessageSettings.TYPE_NUKE)) {
|
||||
return NukeRequestMessage.parse(message);
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_FLOW)) {
|
||||
return ChangeLemmingFlowMessage.parse(message);
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_HELO)) {
|
||||
return IdentificationMessage.parse(message);
|
||||
}
|
||||
|
||||
if (type.equals(MessageSettings.TYPE_LEVELEND)) {
|
||||
return LevelFinishMessage.parse(message);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a network message class from a list of data.
|
||||
*
|
||||
* @param messageType a <code>String</code> value
|
||||
* @param data a <code>List</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
public AbstractMessage createMessage(final String messageType,
|
||||
final List data) {
|
||||
if (messageType == null
|
||||
|| (messageType.length() != MessageSettings.TYPE_LENGTH)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_PAUSE)) {
|
||||
return PauseMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_UPDATE)) {
|
||||
return UpdateMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_SPEED)) {
|
||||
return ChangeSpeedMessage.buildMessage(data);
|
||||
}
|
||||
if (messageType.equals(MessageSettings.TYPE_STAT)) {
|
||||
return StatsMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_NUKE)) {
|
||||
return NukeRequestMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_FLOW)) {
|
||||
return ChangeLemmingFlowMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_HELO)) {
|
||||
return IdentificationMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_LEVELEND)) {
|
||||
return LevelFinishMessage.buildMessage(data);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a message of the specified type with the default
|
||||
* parameters. The message returned is basically considered empty.
|
||||
*
|
||||
* @param messageType a <code>String</code> value
|
||||
* @param authorName a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
public AbstractMessage makeBlankMessage(final String messageType,
|
||||
final String authorName) {
|
||||
if (messageType == null || messageType.equals("")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_PAUSE)) {
|
||||
return new PauseMessage(authorName);
|
||||
}
|
||||
|
||||
//if (messageType.equals(MessageSettings.TYPE_UPDATE)) {
|
||||
// return new UpdateMessage(authorName);
|
||||
//}
|
||||
if (messageType.equals(MessageSettings.TYPE_STAT)) {
|
||||
return new StatsMessage(authorName);
|
||||
}
|
||||
if (messageType.equals(MessageSettings.TYPE_SPEED)) {
|
||||
return new ChangeSpeedMessage(authorName);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_NUKE)) {
|
||||
return new NukeRequestMessage(authorName);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_FLOW)) {
|
||||
return new ChangeLemmingFlowMessage(authorName);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_HELO)) {
|
||||
return new IdentificationMessage(authorName);
|
||||
}
|
||||
|
||||
if (messageType.equals(MessageSettings.TYPE_LEVELEND)) {
|
||||
return new LevelFinishMessage(authorName);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Class MessageSettings: This class contains the settings shared
|
||||
|
||||
* among all the different messages, as well as the MessageFactory.
|
||||
|
||||
*
|
||||
|
||||
* <PRE>
|
||||
|
||||
* Revision History:
|
||||
|
||||
* v1.0 (Apr 8, 2004) - Created the MessageSettings class
|
||||
|
||||
* </PRE>
|
||||
|
||||
*
|
||||
|
||||
* @author <A HREF="mailto:gtg563g@mail.gatech.edu">Daniyar Zhanbekov</A>
|
||||
|
||||
* @version Version 1.0, Apr 8, 2004
|
||||
|
||||
*/
|
||||
|
||||
public final class MessageSettings {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Message type associated with all unknown messages.
|
||||
|
||||
*/
|
||||
|
||||
public static final String TYPE_UNKNOWN = "ABST";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Message type associated with stats update messages.
|
||||
|
||||
*/
|
||||
|
||||
public static final String TYPE_STAT = "STAT";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Message type associated with all pause messages.
|
||||
|
||||
*/
|
||||
|
||||
public static final String TYPE_PAUSE = "PAUS";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Message type associated with all update messages.
|
||||
|
||||
*/
|
||||
|
||||
public static final String TYPE_UPDATE = "UPDT";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Message type associated with all change speed messages.
|
||||
|
||||
*/
|
||||
|
||||
public static final String TYPE_SPEED = "SPED";
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package edu.gatech.cs2335.lemmings.networking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Class NukeRequestMessage: Sent by host or client when Nuke is
|
||||
* desired.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (April 08, 2004) - Created the NukeRequestMessage class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg284h@mail.gatech.edu">Andrew Knight</A>
|
||||
* @version Version 1.0,April 08 , 2004
|
||||
*/
|
||||
public class NukeRequestMessage extends AbstractMessage {
|
||||
|
||||
/**
|
||||
* Creates a new <code>NukeRequestMessage</code> instance.
|
||||
*
|
||||
* @param userName a <code>String</code> value
|
||||
*/
|
||||
public NukeRequestMessage(final String userName) {
|
||||
super(MessageSettings.TYPE_NUKE, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message from the data provided.
|
||||
*
|
||||
* @param data a <code>List</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage buildMessage(final List data) {
|
||||
if (data == null || (data.size() != 1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NukeRequestMessage((String) (data.get(0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the message fit for plain-text
|
||||
* transmission over the network.
|
||||
*
|
||||
* @return a <code>String</code> value
|
||||
*/
|
||||
public final String tokenize() {
|
||||
String message = getMessageType() + "\037" + getAuthor();
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string into the specific message.
|
||||
*
|
||||
* @param message a <code>String</code> value
|
||||
* @return an <code>AbstractMessage</code> value
|
||||
*/
|
||||
protected static AbstractMessage parse(final String message) {
|
||||
String type = getMessageType(message);
|
||||
String name;
|
||||
StringTokenizer st = null;
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!type.equals(MessageSettings.TYPE_NUKE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
st = new StringTokenizer(message, "\037");
|
||||
|
||||
//Message type:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
type = st.nextToken();
|
||||
|
||||
//Username:
|
||||
if (!st.hasMoreTokens()) { return null; }
|
||||
name = st.nextToken();
|
||||
|
||||
|
||||
return new NukeRequestMessage(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user