📄 game.java
字号:
package fr.umlv.fourmIR2000;
import java.util.ArrayList;
import java.util.LinkedList;
import fr.umlv.fourmIR2000.ai.Intelligence;
import fr.umlv.fourmIR2000.frame.GameFrame;
import fr.umlv.fourmIR2000.frame.SelectBuilder;
import fr.umlv.fourmIR2000.insect.Insect;
import fr.umlv.fourmIR2000.insect.Team;
import fr.umlv.fourmIR2000.pictures.Values;
import fr.umlv.fourmIR2000.world.BadWorldFormatException;
import fr.umlv.fourmIR2000.world.World;
import fr.umlv.fourmIR2000.world.WorldPoint;
/**
* Manage the game. This class give elements to build the map, then control the play.
*/
public final class Game {
/** Differents types of world we could ask for in the level editor */
static enum typeWorld {
plain, marsh, mountain, desert, user
}
/** Difficulty level */
public static enum Difficulty {
EASY, MEDIUM, HARD
}
/** Type of file to load / save */
static enum TypeFile {
LEVEL, GAME
}
/** For serialization : version of the class */
private final static long serialVersionUID = 1L;
/** Map to use */
private final World world;
/** For the creation of the map : position of our antHill */
private WorldPoint antHill;
/** For the creation of the map : list of positions of other antHills */
private final ArrayList<WorldPoint> antHillOpp;
/** For the creation of the map : indicate if some change were made on the map */
private boolean levelModified;
/** For the creation of the map : indicate if we had finish to prepare the map */
private boolean initBreak;
/** For the game : boolean that indicate if we must stop the game or not */
private boolean gameBreak;
/** For the game : indicate that we are saving or loading a game, and that we must pause the current game */
private boolean gamePaused;
/** For the game initialization : indicate if the world is a new one or a loaded one */
private boolean newGame;
/** The game JFrame. We use it to assign listeners when we need them */
private final GameFrame gameFrame;
/** The GameListeners to work with. This object manage the listeners of the game */
private final GameListeners gameListeners;
/** Used for the wait of the game */
private long startTime;
/** The insect contr鬺ed by the player */
private Insect samantha;
/** Number of teams still alive in the current game */
private int nbOpponents;
/** Indicate if the button 'develop veterans' is activated or not */
private boolean isVeteransActivated;
/** Indicate if the button 'develop a bug' is activated or not */
private boolean isBugsActivated;
/** Indicate if the button 'develop a kamikaze' is activated or not */
private boolean isKamikazesActivated;
/** Counter of the player's ant death */
private int countDeath;
/**
* Constructor of a new game
* @param gameFrame the graphical frame to use for the game
*/
public Game(GameFrame gameFrame) {
this.gameFrame = gameFrame;
this.world = gameFrame.getWorld();
antHill = null;
antHillOpp = new ArrayList<WorldPoint>();
gameBreak = initBreak = levelModified = gamePaused = false;
newGame = true;
samantha = null;
nbOpponents = 0;
countDeath = 0;
isVeteransActivated = false;
isBugsActivated = false;
isKamikazesActivated = false;
gameListeners = new GameListeners(this, gameFrame);
gameListeners.initializeListeners();
}
/**
* Define a new random map for the current game
* @see #defineNewWorld(int, int, int, int)
* @param type Type of the world to generate
*/
@SuppressWarnings("incomplete-switch")
void defineNewWorld(final typeWorld type) {
// We get the world (WE DON'T DO the 'user' case)
switch (type) {
case plain: defineNewWorld(0, 3, 5, 2); break;
case marsh: defineNewWorld(0, 40, 5, 2); break;
case mountain: defineNewWorld(40, 1, 20, 2); break;
case desert: defineNewWorld(90, 1, 15, 1); break;
}
}
/**
* Generate a new world with user-select percentages
* @param percentDesert percent of desert tiles in the map
* @param percentWater percent of water tiles in the map
* @param percentRocks % of rocks to have in the map
* @param percentFood % of food to have in the map
*/
void defineNewWorld(final int percentDesert, final int percentWater, final int percentRocks, final int percentFood) {
final WorldPoint maxPoint = gameFrame.getAndValidSizeMap();
if (maxPoint == null)
return;
world.generateNewWorld(maxPoint.getX(), maxPoint.getY(), percentDesert, percentWater, percentRocks, percentFood);
getAntHillsPositions();
gameFrame.assignNewWorld(world);
gameListeners.replaceMainListener(GameListeners.MainLst.LST_Level);
levelModified = false;
// We center the view around the player's antHill
gameFrame.centerGamePaneAroundCoords(antHill);
}
/**
* Get the positions of the AntHills from the current 'world'
*/
void getAntHillsPositions() {
antHill = null;
antHillOpp.clear();
for (int y = 0; y < world.getHeight(); ++y)
for (int x = 0; x < world.getWidth(); ++x) {
WorldPoint p = world.getPoint(x, y);
if (world.getElement(x, y) == Values.antHill)
antHill = p;
else if (world.getElement(x, y) == Values.antHill_enemy)
antHillOpp.add(p);
}
}
/**
* Save the current game state (level or game) in a file
* @param typFile king of file to save (level, game ?)
* @return true if the operation was a success
*/
boolean saveStateToFile(final TypeFile typFile) {
final String file = SelectBuilder.showSelectFile( typFile == TypeFile.GAME ? "gam" : "lvl", false);
if (file == null)
return false;
try {
if (typFile == TypeFile.GAME)
world.saveGame(file);
else
world.saveLevel(file);
} catch (BadWorldFormatException bfe) {
SelectBuilder.showMessageAlert(gameFrame.getTitle(),
"Impossible to write on the "
+ (typFile == TypeFile.GAME ? "game" : "level")
+ " '" + file + "'." + "\nError : "
+ bfe.getMessage());
return false;
}
return true;
}
/**
* Load the current state (level or game) from a file
* @param typFile kind of file to load (level, game ?)
* @return true if the operation was a success
*/
boolean loadStateFromFile(final TypeFile typFile) {
final String file = SelectBuilder.showSelectFile( typFile == TypeFile.GAME ? "gam" : "lvl", true);
if (file == null)
return false;
try {
if (typFile == TypeFile.GAME) {
world.loadGame(file);
} else
world.loadLevel(file);
} catch (BadWorldFormatException bfe) {
SelectBuilder.showMessageAlert(gameFrame.getTitle(),
"The file '" + file + "' is not a valid "
+ (typFile == TypeFile.GAME ? "game" : "level")
+ ".\nError : " + bfe.getMessage());
return false;
}
gameFrame.assignNewWorld(world);
gameListeners.replaceMainListener(typFile == TypeFile.GAME ? GameListeners.MainLst.LST_Game : GameListeners.MainLst.LST_Level);
return true;
}
/**
* Part 1 of the game : creation of the map. It ends when the boolean isInitBreak become true
*/
void launchEditor() {
gameFrame.prepareGraphicForLevelEditor();
initBreak = false;
gameBreak = false;
gameListeners.replaceMainListener(GameListeners.MainLst.LST_Level);
defineNewWorld(typeWorld.plain);
}
/**
* Part 2 of the game : game itself. It ends when the boolean isGameBreak become true
*/
void launchGame() {
// Variables
int ancEnergySamantha = Integer.MIN_VALUE;
int ancFoodStock = Integer.MIN_VALUE;
int ancKnowledge = Integer.MIN_VALUE;
boolean isShieldActivated = false;
int nextKnowledgeVeteran = Team.KNOWLEDGE_FOR_SERGEANTS;
// Initialization
gameFrame.prepareGraphicForGame();
isVeteransActivated = false;
countDeath = 0;
gameFrame.updateGameButton(GameFrame.GameControls.GAM_Bug, false);
gameFrame.updateGameButton(GameFrame.GameControls.GAM_Kamikaze, false);
gameFrame.updateGameButton(GameFrame.GameControls.GAM_Shield, false);
gameFrame.updateGameButton(GameFrame.GameControls.GAM_Veteran, false);
// If it is as new game, we add the teams and stock food positions
nbOpponents = 0;
if (newGame) {
int nbColor = 0;
world.clearTeams();
world.addTeam(antHill, nbColor++, this);
for (WorldPoint p : antHillOpp) {
world.addTeam(p, nbColor++, this);
nbOpponents++;
}
createSamantha(false);
world.storeFood();
// If it is a saved one, we reassign all the transient variables
} else {
for (Team t : world.getTeams()) {
if (t.getMaster() != null)
nbOpponents++;
t.setGame(this);
t.setWorld(world);
}
samantha = world.getTeams().get(0).getMaster().addSamantha();
}
LinkedList<Intelligence> IA = new LinkedList<Intelligence>();
for(int i=1; i<world.getTeams().size(); i++) {
IA.add(new Intelligence(world.getTeams().get(i), gameFrame));
}
// We update all the indicators and the eventsListener
initBreak = false;
gameBreak = false;
gameListeners.replaceMainListener(GameListeners.MainLst.LST_Game);
// And we launch the game
while (!gameBreak) {
// if we are not paused, we move all the insects of the game
if (!gamePaused) {
for(Intelligence intelligence : IA)
intelligence.think();
for (Team team : world.getTeams()) {
/* BE CAREFUL : we CAN'T use an Iterator to get all the insects !!!
* >> If one of them die, his reference is 'squized' and the iterator generates a
* ConcurrentCallException because it looks at the wrong place for the next element.
* To avoid this, we take an array, so the reference of the insect is kept until the
* end of the turn.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -