📄 world.java
字号:
package fr.umlv.fourmIR2000.world;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import fr.umlv.fourmIR2000.Game;
import fr.umlv.fourmIR2000.insect.Insect;
import fr.umlv.fourmIR2000.insect.Team;
import fr.umlv.fourmIR2000.pictures.Values;
import fr.umlv.lawrence.impl.DefaultGridModel;
/**
* World to use with the game.
* This is a sort of container of all objects that must be drawn on the JPanel.
*/
public final class World implements Serializable {
/** For serialization : version of the class */
private final static long serialVersionUID = 1L;
/** Model used to draw pictures BE CAREFUL : We don't want it to be serializable !!! */
private transient DefaultGridModel<Values> model;
/** Shortest path finding */
private transient PathFinding path;
/** Size X of the game */
private int sizeX;
/** Size Y of the game */
private int sizeY;
/** Matrix of Floor elements */
private Floor tab[][];
/** Array of teams playing */
private ArrayList<Team> tabTeam;
/** Array of food present in the game */
private ArrayList<WorldPoint> tabFood;
/** The point of the map who has the focus */
private WorldPoint selectedPoint;
/**
* Create a new World for playing
* @param sizeX Size X of the game (the real size is this size + size of the left menu)
* @param sizeY Size Y of the game
*/
public World(int sizeX, int sizeY) {
// Errors detection
if (sizeX < 1) sizeX = 1;
if (sizeY < 1) sizeY = 1;
// Initialization of the variables
this.sizeX = sizeX;
this.sizeY = sizeY;
tabTeam = new ArrayList<Team>();
tabFood = new ArrayList<WorldPoint>();
path = null;
selectedPoint = null;
initializeGridModel();
}
/**
* Give the GridModel used by the world
* @return the DefaultGridModel to use in a GridPane
* @see fr.umlv.lawrence.GridPane
*/
public DefaultGridModel<Values> getModel() {
return model;
}
/**
* Generate an new world, and store the position of the two antHills
* >> The first antHill is the one we play with
* @param maxX new X maximal coord
* @param maxY new Y maximal coord
* @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
*/
public void generateNewWorld(int maxX, int maxY, int percentDesert, int percentWater, int percentRocks, int percentFood) {
sizeX = maxX;
sizeY = maxY;
RandomWorld rndWorld = new RandomWorld(sizeX, sizeY, percentDesert, percentWater, percentRocks, percentFood);
tab = rndWorld.getWorld();
tabTeam.clear();
path = new PathFinding(this);
initializeGridModel();
refresh();
}
/**
* Initialize a new GridModel with the current 'Floor' elements
*/
private void initializeGridModel() {
@SuppressWarnings("unchecked")
Set<Values>[] array = (Set<Values>[]) new Set<?>[sizeX * sizeY];
int i = 0;
for (int y=0; y < sizeY; ++y)
for (int x=0; x < sizeX; ++x) {
array[i]=EnumSet.noneOf(Values.class);
if (tab == null)
array[i].add(Values.grass);
else
array[i].addAll(tab[y][x].getPictures());
i++;
}
model = new DefaultGridModel<Values>(sizeY, sizeX, Arrays.asList(array));
}
/**
* Store the food positions in an array. This way, all insects can find where is the nearest food.
*/
public void storeFood() {
tabFood.clear();
for (int y = 0; y < sizeY; ++y)
for (int x = 0; x < sizeX; ++x)
if (tab[y][x].getType() == Values.food)
tabFood.add(tab[y][x].getPoint());
}
/**
* Give the width of the map
* @return the width of the map (+ the size of the menu)
*/
public int getWidth() {
return sizeX;
}
/**
* Give the height of the map
* @return the height of the map
*/
public int getHeight() {
return sizeY;
}
/**
* Return the value of the element at this tile
* @param x X position
* @param y Y position
* @return the value
*/
public Values getElement(int x, int y) {
if (isPositionAvailable(x, y))
return tab[y][x].getType();
return null;
}
/**
* Return the value of the background element at this tile
* @param x X position
* @param y Y position
* @return the value
*/
public Values getBackgroundElement(int x, int y) {
if (isPositionAvailable(x, y))
return tab[y][x].getBackgroundType();
return null;
}
/**
* Assign an element for the backgroun of a specific tile
* @param x X posiiton
* @param y Y position
* @param type value to assign
* @param isDirect true to redraw immediately, false to wait for a refresh() call
* @see #refresh()
*/
public void setElement(int x, int y, Values type, boolean isDirect) {
if (isPositionAvailable(x, y)) {
// We update the ground element
tab[y][x].setType(type);
tab[y][x].setObstacle(Values.isObstacle(type));
// And we inform the model that it has changed
updateModelAndAdjacentTiles(x, y, isDirect);
}
}
/**
* Assign an element for the backgroun of a specific tile
* @param floor the floor element to update
* @param isDirect true to redraw immediately, false to wait for a refresh() call
* @see #refresh()
*/
public void setElement(Floor floor, boolean isDirect) {
int x = floor.getPoint().getX();
int y = floor.getPoint().getY();
if (isPositionAvailable(x, y)) {
// We update the ground element and the graphics of tiles around
tab[y][x] = floor;
WorldBlur.blurFloor(tab, floor);
WorldBlur.blurAdjacentFloors(tab, floor);
// And we inform the model that it has changed
updateModelAndAdjacentTiles(x, y, isDirect);
}
}
/**
* Try to update the pictures of all adjacent tiles
* @param x the X coord of the main tile
* @param y the Y coord of the main tile
* @param isDirect true to redraw immediately, false to wait for a refresh() call
* @see #refresh()
*/
private void updateModelAndAdjacentTiles(int x, int y, boolean isDirect) {
updateModel(x, y, isDirect);
if (isPositionAvailable(x-1, y)) updateModel(x-1, y, isDirect);
if (isPositionAvailable(x+1, y)) updateModel(x+1, y, isDirect);
if (isPositionAvailable(x, y-1)) updateModel(x, y-1, isDirect);
if (isPositionAvailable(x, y+1)) updateModel(x, y+1, isDirect);
}
/**
* Indicate if the specified position is crossable or not, without
* regarding if there is an insect or not in the tile.
* @param p The position to check
* @return true if it is crossable
*/
private boolean isBackgroundCrossable(WorldPoint p) {
return isPositionAvailable(p) && !tab[p.getY()][p.getX()].isObstacle();
}
/**
* Indicate if the specified position is crossable or not, regarding
* if there is an insect on it
* @param p The position to check
* @return true if it is crossable
*/
public boolean isCrossable(WorldPoint p) {
return isBackgroundCrossable(p) && tab[p.getY()][p.getX()].getInsect() == null;
}
/**
* Indicate if the specified position is available for an insect or not
* @param x X position
* @param y Y position
* @return true if the tile is free
* @see #isPositionAvailable(WorldPoint)
*/
public boolean isPositionAvailable(int x, int y) {
return (x < 0 || y < 0 || x >= sizeX || y >= sizeY) ? false : true;
}
/**
* Indicate if the specified position is available for an insect or not
* @param p the point to check
* @return true if the tile is free
* @see #isPositionAvailable(int, int)
*/
boolean isPositionAvailable(final WorldPoint p) {
return isPositionAvailable(p.getX(), p.getY());
}
/**
* Tell us if we can move to the chosen destination.
* Be careful: we can only move of one tile !
* @param src the source Point
* @param dest the destination Point
* @return true if we can go there
*/
public boolean canMoveHere(WorldPoint src, WorldPoint dest) {
int destX = dest.getX();
int destY = dest.getY();
// Bad position ? We quit immediatly
if (src.distance(dest) >= 2 || ! isPositionAvailable(dest) || tab[destY][destX].isObstacle())
return false;
/* We check for diagonals : we can't move in a diagonal if there are block all around.
* ie. if we want to go Upper/Left, and if there are rocks on left and upper, we can't go. */
int x = src.getX();
int y = src.getY();
final WorldPoint UpLeft = getPoint(x - 1, y - 1);
final WorldPoint Up = getPoint(x, y - 1);
final WorldPoint UpRight = getPoint(x + 1, y - 1);
final WorldPoint Left = getPoint(x - 1, y);
final WorldPoint Right = getPoint(x + 1, y);
final WorldPoint DownLeft = getPoint(x - 1, y + 1);
final WorldPoint Down = getPoint(x, y + 1);
final WorldPoint DownRight = getPoint(x + 1, y + 1);
if ( (dest.equals(UpLeft) && !isCrossable(Up) && !isCrossable(Left))
|| (dest.equals(UpRight) && !isCrossable(Up) && !isCrossable(Right))
|| (dest.equals(DownLeft) && !isCrossable(Down) && !isCrossable(Left))
|| (dest.equals(DownRight) && !isCrossable(Down) && !isCrossable(Right))
)
return false;
return true;
}
/**
* Give the list of all insects that are around a point
* @param me insect who calls the verification
* @param radius the radius to check around the insect
* @param wantAFriend if true return our friends. If false, return the ennemies
* @return true if exists or false;
*/
public LinkedList<Insect> giveInsectAround(Insect me, int radius, boolean wantAFriend) {
WorldPoint p = me.getPos();
LinkedList<Insect> result= new LinkedList<Insect>();
for(int y = p.getY() - radius; y <= p.getY() + radius; y++) {
for (int x = p.getX() - radius; x <= p.getX() + radius; x++) {
if (isPositionAvailable(x, y)) {
Floor floor = tab[y][x];
if (! floor.getPoint().equals(p)) {
Insect insect = floor.getInsect();
if (insect != null) {
boolean isOurTeam = insect.getTeam().equals(me.getTeam());
if ((isOurTeam && wantAFriend) || (!isOurTeam && !wantAFriend))
result.add(insect);
}
}
}
}
}
return result;
}
/**
* Add a team of insects to the world. The first team would be the team we play with !
* >> it works because we use an ArrayList
* @param antHill point of the antHill
* @param color color of the team
* @param game the gameassociated (to perform some special actions when an antQueen die for example)
*/
public void addTeam(WorldPoint antHill, int color, Game game) {
Team team = new Team(this, antHill, color, game);
team.addMaster();
tabTeam.add(team);
}
/**
* Add an insect in the game
* @param insect new insect to add
* @return true if we can add the insect in the specified place
*/
public boolean addInsect(Insect insect) {
if (insect == null)
return false;
WorldPoint p = insect.getPos();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -