?? unit.java
字號:
}
}
//The remaining methods are intended to be over-rided by sub-classes of Unit.
//The default version of think() may suffice for many (all?) units.
/** Returns the number of frames needed to move forward one hex.
* @return How many frames it takes to move one hex.
*/
protected abstract int framesToMove();
/** Returns the number of frames needed to rotate one hex-side.
* @return How many frames it takes to rotate sixty degrees.
*/
protected abstract int framesToRotate();
/** Do the processing for a frame of animation while moving forward. */
protected abstract void animateMove();
/** Do the processing for a frame of animation while rotating left. */
protected abstract void animateRotateLeft();
/** Do the processing for a frame of animation while rotating right. */
protected abstract void animateRotateRight();
/** Think about what to do. Called by Update() when the Unit is sitting around, or just finished doing something (such as moving one hex or rotating one hex-side).
* Default version scans for enemies if in Guard Mode (changing to Pursuit Mode if one is detected),
* then figures out a direction to move if it has a destination.
*/
protected void think() {
//Decide where to go next. Reserve an adjacent hex if plausible.
//First, if a target is chosen, untarget it if it is dead
if(target != null && target.isDead()) {
target = null;
targetSSMDS = null;
if(mode == 2)
mode = 0;
}
int fChg = 0;
Hex next = null;
if(mode == 0) {
target = scan();
if(target == null) {
resX = x; resY = y;
action = 0;
return; //don't go anywhere
}else{
mode = 2;
targetSSMDS = firstSSMDS.getTarget(this, target);
}
}
if(mode == 1) // Go toward destination
resF = bestDirection(goalX,goalY); //Change arguments to control destination
if(mode == 2) // Pursue target
{
int fol = followRange();
goalX = target.x;
goalY = target.y;
confirmSubPlan(goalX,goalY);
resF = bestDirection(goalX,goalY);
if((fol >= goalX - x) &&
(fol >= x - goalX) &&
(fol >= goalY - y) &&
(fol >= y - goalY) &&
(fol >= goalX - x - goalY + y) &&
(fol >= x - goalX - y + goalY)) {
if(resF == f) {
action = 0;
}else{
if((resF - f > 0 && resF - f < 3) || resF - f < -3){
//rotate left
action = 1; frame = framesToRotate();
}else{
//rotate right
action = 2; frame = framesToRotate();
}
}
resX = x; resY = y;
return;
}
}
switch(traceMode)
{
case 0:
while(true){
switch(resF){
case 0: resX = x + 1; resY = y + 1; break;
case 1: resX = x; resY = y + 1; break;
case 2: resX = x - 1; resY = y; break;
case 3: resX = x - 1; resY = y - 1; break;
case 4: resX = x; resY = y - 1; break;
case 5: resX = x + 1; resY = y; break;
}
next = Hex.getHex(resX, resY);
if(next != null && next.reserve())
break;
if(resX == goalX && resY == goalY)
{
mode = 0;
return;
}
//Change resF. This causes resF to try
//one hex-side to the left, then one to the right,
//then two to the left, etc.
fChg *= -1;
fChg += (fChg == 0)?(subPlanBias):((fChg < 0)?(-1):(1));
resF += fChg;
if(resF < 0) resF += 6;
else if(resF > 5) resF -= 6;
if(fChg == 6 || fChg == -6) {//nowhere to go. Already checked all six sides.
action = 0;
resX = x; resY = y;
return;
}
}
fChg = resF - f;
if(fChg == 2 || fChg == 3 || fChg == -4)
traceMode = 1;
else if(fChg == -2 || fChg == -3 || fChg == 4)
traceMode = -1;
reserved = true;
Hex.getHex(x, y).unreserve();
break;
case 1:
resF = f - 1;
if(resF < 0) resF = 5;
while(true){
switch(resF){
case 0: resX = x + 1; resY = y + 1; break;
case 1: resX = x; resY = y + 1; break;
case 2: resX = x - 1; resY = y; break;
case 3: resX = x - 1; resY = y - 1; break;
case 4: resX = x; resY = y - 1; break;
case 5: resX = x + 1; resY = y; break;
}
next = Hex.getHex(resX, resY);
if(next != null && next.reserve())
break;
if(resX == goalX && resY == goalY)
{
mode = 0;
return;
}
//Change resF. Try starting from 60 degrees right leftward.
resF += 1;
if(resF > 5) resF -= 6;
if(resF == f - 1 || resF == f + 5) {//nowhere to go. Already checked all six sides.
action = 0;
resX = x; resY = y;
return;
}
}
confirmSubPlan(goalX,goalY);
if(resF == bestDirection(goalX,goalY));
traceMode = 0;
reserved = true;
Hex.getHex(x, y).unreserve();
break;
case -1:
resF = f + 1;
if(resF > 5) resF = 0;
while(true){
switch(resF){
case 0: resX = x + 1; resY = y + 1; break;
case 1: resX = x; resY = y + 1; break;
case 2: resX = x - 1; resY = y; break;
case 3: resX = x - 1; resY = y - 1; break;
case 4: resX = x; resY = y - 1; break;
case 5: resX = x + 1; resY = y; break;
}
next = Hex.getHex(resX, resY);
if(next != null && next.reserve())
break;
if(resX == goalX && resY == goalY)
{
mode = 0;
return;
}
//Change resF. Try starting from 60 degrees left rightward.
resF -= 1;
if(resF < 0) resF += 6;
if(resF == f + 1 || resF == f - 5) {//nowhere to go. Already checked all six sides.
action = 0;
resX = x; resY = y;
return;
}
}
confirmSubPlan(goalX,goalY);
if(resF == bestDirection(goalX,goalY));
traceMode = 0;
reserved = true;
Hex.getHex(x, y).unreserve();
break;
}
}
/** Returns the number of Hexes to get within if in Pursuit Mode.
* As long as the Unit is this close to its target, it will remain stationary and fire.
* This allows long range Units to abuse their range advantage by staying back while firing.
* @return The range to approach to, in hexes.
*/
public abstract int followRange();
/** Returns The maximum value of health for this Unit, which is the initial value for health.
* @return The amount of damage that must be taken to destroy the Unit.
*/
protected abstract int maxHealth();
/** Returns the number of damage points to be ignored from each hit.
* Under standard health/armor rules, a unit cannot take less than 1 damage per hit.
* @return The armor value of the unit.
*/
protected abstract int armor();
/** Applies damage to this Unit, possibly destroying it.
* This version uses the standard health/armor rules:
* <BR> A unit starts with a fixed amount of health and cannot exceed that amount.
* <BR> A unit has a (fixed ?) amount of armor.
* <BR> When a unit is hit by an attack, it loses health equal to the damage minus the armor, but a minimum of one.
* <BR> The unit is destroyed if it drops below 1 health.
*/
public void recieveDamage(int dam) {
if(dam > 0) //Presume possibility of healing 'weapons'
{
dam -= armor();
if(dam <= 0) dam = 1;
}
health -= dam;
if(health > maxHealth()) health = maxHealth();
if(health <= 0) {
action = 5;
frame = framesToDie();
((netwar.gui.NetwarPanel)netwar.Netwar.netwar.getDataViewer()).unitKilled(myPlayer.getNumber());
}
if (((netwar.gui.NetwarPanel)netwar.Netwar.netwar.getDataViewer()).selectedUnitIDMatch(getID()))
((netwar.gui.NetwarPanel)netwar.Netwar.netwar.getDataViewer()).updateUnitHealth(health);
}
/** Make applicable adjustments, then return true if the target is within the firing arc.
* The default version assumes that the Unit has a 120-degree firing arc, centered at the
* last hex-side it was facing, and the Unit does not have an independant turret.
* If the unit has an independant turret, it should override aim, and use aim to
* rotate the turret.
* @return True if the target is in the firing arc.
*/
protected boolean aim(){
if(target == null) return false;
if(target.myPlayer == myPlayer)
return false; //Don't shoot at own units, just follow them.
if(target.isDead()) {
target = null;
targetSSMDS = null;
if(mode == 2)
mode = 0;
return false;
}
int gx = target.x;
int gy = target.y;
int dxy;
gx -= x;
gy -= y;
dxy = gx - gy;
switch(f) {
case 0:
if(gx <= 0 || gy <= 0) return false;
break;
case 1:
if(gy <= 0 || dxy >= 0) return false;
break;
case 2:
if(dxy >= 0 || gx >= 0) return false;
break;
case 3:
if(gx >= 0 || gy >= 0) return false;
break;
case 4:
if(gy >= 0 || dxy <= 0) return false;
break;
case 5:
if(dxy <= 0 || gx <= 0) return false;
break;
}
return true;
}
/** Return True iff the Unit is already destroyed.
* Destuction occurs when health drops below 1.
* @return True if healt <= 0.
*/
public boolean isDead() {
return (health <= 0);
}
/** Return True if the Unit can be damaged.
* The Unit can be damaged if it is not yet destroyed.
* @return True if health > 0.
*/
public boolean damageable() {
return (health > 0);
}
public boolean repairable() {
return (health > 0 && health < maxHealth());
}
public boolean paralyzable() {
return (health > 0 && stun == 0);
}
public void recieveParalysis(int level)
{
if(stun == 0)
stun = level;
}
static final String[] PROPERTIES = {"Name", "Health", "Max Health", "Armor", "Following Range", "Moving Speed", "Rotating Speed"};
protected String[] PROPERTIES() {
return PROPERTIES;
}
protected String getProperty(int p) {
switch(p) {
case 0:
String name = getClass().getName();
return name.substring(name.lastIndexOf(".")+1);
case 1:
return Integer.toString(health);
case 2:
return Integer.toString(maxHealth());
case 3:
return Integer.toString(armor());
case 4:
return Integer.toString(followRange());
case 5:
return Integer.toString(framesToMove());
case 6:
return Integer.toString(framesToRotate());
default:
Assert.notFalse(false, "getProperty(int) error.");
}
return null;
}
public float getStatusFraction() {
return (float) health / maxHealth();
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -