⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.java

📁 SIMULATION FOURMILIERE -3D-ISOMETRIQUE
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
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 + -