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

📄 unit.java

📁 用java开发的一个实施策略游戏源码 值得学习一下
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
	Netwar
	Copyright (C) 2002  Daniel Grund, Kyle Kakligian, Jason Komutrattananon, & Brian Hibler.

	This file is part of Netwar.

	Netwar is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Netwar is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Netwar; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package netwar.game;
import java.awt.*;
import netwar.utils.Assert;

/** Abstract class which defines a mobile GameObject.
 * This provides default implementation of the following behaviors:
 * <BR> Guard mode in which the Unit scans for nearby enemies.
 * <BR> Move mode in which the Unit tries to reach a particular Hex.
 * <BR> Pursuit mode in which the Unit moves toward a particular GameObject,
 * up to a range less than the weapon range, and fires repeatedly if that
 * GameObject is a damagable object which is not part of the same team.
 * <BR> Receiving damage using the standard health/armor model.
 * <BR> Navigating obstacles using a simple alternate direction system.
 * @author Group N2 - Project Netwar
 * @author Daniel Grund
 */
public abstract class Unit extends GameObject {
	/** A value indicating the amount of damage still needed to destroy this Unit. */
	protected int health = maxHealth();
	/** A value indicating the number of frames to remain paralyzed. */
	protected int stun = 0;
	/** A code number indicating the direction that the Unit is facing */
	protected int f = 4;
	
	//Adjacent hex reservation data
	/** X part of the Hex coord reserved for this Unit to move into another Hex. */
	protected int resX;
	/** Y part of the Hex coord reserved for this Unit to move into another Hex. */
	protected int resY;
	/** The facing this Unit should have when moving into the reserved Hex. */
	protected int resF;
	/** True if the Unit has a Hex reserved to move into. */
	protected boolean reserved = false;
	//If traceMode = 0, use classic pathfinding intelligence.
	//If traceMode = 1, use Keep-Obstacles-On-Your-Right mode.
	//If traceMode = -1, use Keep-Obstacles-On-Your-Left mode.
	private int traceMode = 0;
	private boolean validSubPlan = false;
	private int subPlanDirection;
	private int subPlanBias;
	
	/** Sets the facing of the Unit when it is created */
	protected void param(int p) {
		f = p;
		resX = x;
		resY = y;
	}
	//Default setGoal()s for a mobile Unit.
	/** Sets the unit to Guard Mode */
	public void setGoal() {
		//Set to 0  (remain stationary)
		mode = 0;
                traceMode = 0;
	}
	/** Sets the unit to Move Mode
	 * @param gx The X part of the Hex coordinate to move to.
	 * @param gy The Y part of the Hex coordinate to move to.
	 */
	public void setGoal(int gx, int gy) {
		//Set to 1 (go to destination)
		mode = 1;
                traceMode = 0;
		goalX = gx;
		goalY = gy;
	}
	/** Sets the Unit to Pursuit Mode
	 * @param u The GameObject to approach/pursue and attack (if not an ally).
	 */
	public void setGoal(GameObject u) {
		//Set to 2 (pursue target)
		mode = 2;
                traceMode = 0;
		target = u;
		targetSSMDS = firstSSMDS.getTarget(this, target);
		goalX = u.x;
		goalY = u.y;
	}
	//Default update for a mobile unit.
	/** Called once per time-step to perform necessary processing.
	 * Provides default logic to determine what animation is in place,
	 * fire a weapon if possible, etc.
	 */
	protected void update() {
		if(isDead()) {
			animateDie();
			return;
		}
		if(stun > 0) {
			stun--;
			return;
		}
		
		//Firing logic.
		if(reload > 0) {
			reload--;
			aim();
		}else{
			if(aim())
			{
				if(targetSSMDS.getDistanceSquared() <= weaponRangeSquared()) {
					if(fire())
						reload = weaponDelay();
				}
			}
		}
			
		if(frame == 0) {	//AI decision frame.
			if(!reserved) {
				//Don't know where I'm going, so I'd better think
				think(); //separate function for subclasses to overload
			}
			//If I know where I'm going next, I'll go.
			if(reserved) //Reserved the next hex already, check if I can move.
			{
				if(resF == f) //facing toward the hex. Now just wait for the unit to move.
				{
					if(Hex.getHex(resX, resY).isEmpty()) {
						action = 3; frame = framesToMove();
					}else //Wait for the hex to be clear.
						action = 0;
				}else{ //need to rotate toward the destination.
					if((resF - f > 0 && resF - f < 3) || resF - f < -3){
						//rotate left
						action = 1; frame = framesToRotate();
					}else{
						//rotate right
						action = 2; frame = framesToRotate();
					}
				}
			}
		}
		switch(action)
		{
			case 1: //Turn left
				animateRotateLeft();
				frame--;
				if(frame == 0)
					f++;
				if(f == 6) f = 0;
			break;
			case 2: //Turn right
				animateRotateRight();
				frame--;
				if(frame == 0)
					f--;
				if(f == -1) f = 5;
			break;
			case 3: //Move forward
				animateMove();
				
				if(firstSSMDS != null){
					//Update SSMDSs for this unit. Note, that this is not simple because the things reorder themselves when updated.
					SelfSortingMutualDistanceSquared ssmds[] = new SelfSortingMutualDistanceSquared[GameObjects.getLength() - 1];
					if(ssmds.length > 0) {
						int i = 0;
						SelfSortingMutualDistanceSquared curr = firstSSMDS;
						for(; i < ssmds.length; i++)
						{
							ssmds[i] = curr;
							curr = curr.getNext(this);
						}
						for(i = 0; i < ssmds.length; i++)
						{
							ssmds[i].update();
						}
					}
				}
				
				frame--;
				if(frame == 0) {
					Hex.getHex(x,y).leave(this);
					switch(f)
					{
						case 0:	x++;	y++;	break;
						case 1:		y++;	break;
						case 2:	x--;		break;
						case 3:	x--;	y--;	break;
						case 4:		y--;	break;
						case 5:	x++;		break;
					}
					Hex.getHex(x,y).enter(this);
					reserved = false; //Remember: The hex I am in is still reserved for me.
					confirmSubPlan(goalX, goalY);
					if(mode == 1 && x == goalX && y == goalY)
						mode = 0;
					think(); //Try to decide on a new space to be in, so this one can be unreserved.
				}
			break;
			case 4: //Making
				animateMake();
				frame--;
			break;
			default:
				frame = 0;
		}
	}
	/** Returns the facing code for the 'best' direction to head.
	 * Assumes the Unit is going from its current location to (gx, gy)
	 * with no obstacles in between. Other code will adjust for obstacles.
	 * @param gx The x part of the destination hex coordinate.
	 * @param gy The y part of the destination hex coordinate.
	 * @return The idealized facing code.
	 */
	protected int bestDirection(int gx, int gy){
		int dxy;
		if(validSubPlan)
			return subPlanDirection;
		gx -= x;
		gy -= y;
		dxy = gx - gy;
		if(gx == 0) {//Goal is vertically aligned.
			if(gy == 0) { //Already at goal.
				subPlanDirection = f;
				subPlanBias = 1;
			}else if(gy < 0) { //Goal is south (facing 4)
				subPlanDirection = 4;
				subPlanBias = 1;
			}else{ //Goal is north (facing 1)
				subPlanDirection = 1;
				subPlanBias = 1;
			}
		}else if(gx > 0) {//Goal is somewhere to the east.
			if(gy == 0) { //Goal is south-east (facing 5)
				subPlanDirection = 5;
				subPlanBias = 1;
			}else if(gy < 0) { //Goal is between facings 4 and 5
				if(gx > -1 * gy) { //Goal is closer to facing 5
					subPlanDirection = 5;
					subPlanBias = -1;
				}else{
					subPlanDirection = 4;
					subPlanBias = 1;
				}
			}else{ //Goal is between facings 5 and 1. First compare against facing 0.
				if(dxy == 0) { //Goal is north-east (facing 0)
					subPlanDirection = 0;
					subPlanBias = 1;
				}else if(dxy < 0) { //Goal is between facings 0 and 1
					if(gy > 2 * gx) { //Goal is closer to facing 1
						subPlanDirection = 1;
						subPlanBias = -1;
					}else{
						subPlanDirection = 0;
						subPlanBias = 1;
					}
				}else{ //Goal is between facings 5 and 0
					if(gx > 2 * gy) { //Goal is closer to facing 5
						subPlanDirection = 5;
						subPlanBias = 1;
					}else{
						subPlanDirection = 0;
						subPlanBias = -1;
					}
				}
			}
		}else{ //Goal is somewhere to the west.
			if(gy == 0) { //Goal is north-west (facing 2)
				subPlanDirection = 2;
				subPlanBias = 1;
			}else if(gy > 0) { //Goal is between facings 1 and 2
				if(gy > -1 * gx) { //Goal is closer to facing 1
					subPlanDirection = 1;
					subPlanBias = 1;
				}else{
					subPlanDirection = 2;
					subPlanBias = -1;
				}
			}else{ //Goal is between facings 2 and 4. First compare against facing 3.
				if(dxy == 0) { //Goal is south-west (facing 3)
					subPlanDirection = 3;
					subPlanBias = 1;
				}else if(dxy > 0) { //Goal is between facings 3 and 4
					if(gy < 2 * gx) { //Goal is closer to facing 4
						subPlanDirection = 4;
						subPlanBias = -1;
					}else{
						subPlanDirection = 3;
						subPlanBias = 1;
					}
				}else{ //Goal is between facings 2 and 3
					if(gx < 2 * gy) { //Goal is closer to facing 2
						subPlanDirection = 2;
						subPlanBias = 1;
					}else{
						subPlanDirection = 3;
						subPlanBias = -1;
					}
				}
			}
		}
		validSubPlan = true;
		return subPlanDirection;
	}
	/** Checks to make sure that the idealized direction to get to the destination is still good.
	 * If the previously calculated best direction would no longer cause the Unit to get
	 * closer to its destination, a flag is set to calculate a new direction the next time
	 * the direction is checked.
	 * @param gx The (updated) x part of the goal hex coordinate.
	 * @param gy The (updated) y part of the goal hex coordinate.
	 */
	protected void confirmSubPlan(int gx, int gy) {
		//Used when either the goal changes, or the unit moves.
		//Makes sure the current subPlan direction still makes sense.
		//If not, invalidate it so that it will be recalculated.
		int dxy;
		gx -= x;
		gy -= y;
		dxy = gx - gy;
		switch(subPlanDirection) {
			case 0:
				if(gx <= 0 || gy <= 0) validSubPlan = false;
			break;
			case 1:
				if(gy <= 0 || dxy >= 0) validSubPlan = false;
			break;
			case 2:
				if(dxy >= 0 || gx >= 0) validSubPlan = false;
			break;
			case 3:
				if(gx >= 0 || gy >= 0) validSubPlan = false;
			break;
			case 4:
				if(gy >= 0 || dxy <= 0) validSubPlan = false;
			break;
			case 5:
				if(dxy <= 0 || gx <= 0) validSubPlan = false;
			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -