📄 aircraft.java
字号:
import java.awt.*;
/**
* A simulated aircraft.
*
* @author James M. Clarke
* @version 02/03/2007
*/
public class Aircraft
{
private Position where;
private float xpos;
private float ypos;
private float velocity;
private float angle;
private float anglechangerate;
private String id;
private int state;
private Runway targetRunway;
private Queue targetQueue;
private boolean hasLanded;
/**
* Constructor for Aircraft objects
* @param tr the runway the aircraft should land at if trying to land
* @param tq the queue the queue the aircraft should join if trying to queue
*/
public Aircraft(Runway tr, Queue tq)
{
//set the target runway and target queue passed as parameters
targetRunway = tr;
targetQueue = tq;
//Create a random plane name consisting of two alphabetic and three alphanumeric characters
id = randomLetter() + randomLetter() + String.valueOf((int) (Math.random()*1000));
//Give the plane an initial state of 0, which is "landing"
state = 0;
//Create the new aircraft at a random Position at the edge of the screen
float genAng = (float) ( (((float) Math.random())-0.5F) * 4 * Math.PI);
where = Position.atAngleDistance(new Position(250F, 250F), genAng, 250F);
//Create the aircraft so it is pointing at its target runway already
angle = Position.angleToNorth(targetRunway.getPosition(), where);
//set the maximum rate at which the aircraft can turn (in radians per "tick")
anglechangerate = 0.005F;
//set the speed at which the aircraft moves
velocity = 0.2F;
}
public boolean hasLanded()
{
return hasLanded;
}
/**
* Return a random alphabetic character
*
* @return a randomly chosen letter
*/
public String randomLetter()
{
char[] letters = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
return String.valueOf(letters[(int) (Math.random()*26)]);
}
/**
* Accessor method for the id number of this Aircraft
*
* @return the id number of this Aircraft
*/
public String getID()
{
return id;
}
/**
* Return the id number of this aircraft when toString() is called
* @see java.lang.Object#toString
* @return the id number of this Aircraft, plus "(Landed)" if it is on the ground
*/
public String toString()
{
if (state == 5)
{ return getID() + "(Landed)"; }
else if (state == 7)
{ return getID() + "(Destroyed)"; }
else
{ return getID(); }
}
/**
* Accessor method for the position of this Aircraft
*
* @return where this Aircraft currently is
*/
public Position where()
{
return where;
}
/**
* Changes state of the aircraft so that it begins to attempt a landing
*/
public void land()
{
if ( !(state == 5) && !(state == 7)) {state = 0;}
}
/**
* Changes state of the aircraft so that it begins to attempt a landing at the specified runway
* @param aRunway the runway to land on
*/
public void land(Runway aRunway)
{
if ( !(state == 5) && !(state == 7)) {state = 0; targetRunway = aRunway;}
}
/**
* Changes state of the aircraft so that it is turning to the left
*/
public void turnLeft()
{
if ( !(state == 5) && !(state == 7)) {state = 1;}
}
/**
* Changes state of the aircraft so that it is turning to the right
*/
public void turnRight()
{
if ( !(state == 5) && !(state == 7)) {state = 2;}
}
/**
* Changes state of the aircraft so that it is attempting to join a queue
*/
public void goToQueue()
{
if ( (state == 0) || (state == 1) || (state == 2) || (state == 6)) { state = 3;}
}
/**
* Changes state of the aircraft so that it is queueing
*/
public void queue()
{
if (state == 3) {state = 4;}
}
/**
* Changes state of the aircraft so that it is on the ground
*/
public void touchDown()
{
if (state == 0) {state = 5; hasLanded = true; where = targetRunway.getEnd();}
}
/**
* Changes state of the aircraft so that it is leaving the simulation
*/
public void leave()
{
if (hasLanded == true && !(state == 7)) { state = 6; }
}
public void destroy()
{
state = 7;
}
/**
* Accessor method for the current state of this Aircraft
*
* @return the state of the Aircraft
*/
public int getState()
{
return state;
}
/**
* Draws the aircraft so it can be displayed
*
* @param graphic a Graphics2D to draw the runway onto
*/
public void draw(Graphics2D graphic)
{
//Draw an aircraft.
//Only draw the aircraft if it isn't on the ground.
if (!(state == 5) && (!(state == 7)) && (Position.distance(new Position(250, 250), where)<250))
{
//works out the three points that represent the aircraft
Position p1 = Position.atAngleDistance(where, angle, 10F);
Position p2 = Position.atAngleDistance(where, angle + (2*((float) Math.PI)/3), 5F);
Position p3 = Position.atAngleDistance(where, angle + (4*((float) Math.PI)/3), 5F);
//Calculate and round our points, and put them in two arrays
int[] xpoints = { (int) p1.getX(), (int) p2.getX(), (int) p3.getX()};
int[] ypoints = { (int) p1.getY(), (int) p2.getY(), (int) p3.getY()};
//Make a new triangle out of the points and draw that triangle
graphic.draw( new Polygon( xpoints , ypoints ,3) );
//Draw the aircrafts id number to the bottom right of it
graphic.drawString(id, where.getX(), where.getY() + 10);
}
}
/**
* Checks if this plane has reached its target runway.
* Aircraft are considered to have reached it if they are within 1px of the start of the runway, and are within 0.1 radians of the correct angle to land.
*
* @return whether the plane has reach the start of the target runway at the correct angle
*/
public boolean isLanded()
{
Position target = targetRunway.getPosition();
if (
(where.getX() < (target.getX()+1))
&&
(where.getX() > (target.getX()-1))
&&
(where.getY() < (target.getY()+1))
&&
(where.getY() > (target.getY()-1))
&&
(Angle.diffClockwise(targetRunway.getAngle(), angle) < 0.1 || Angle.diffAnticlockwise(targetRunway.getAngle(), angle) < 0.1)
)
{ return true; }
return false;
}
/**
* Checks if this plane has reached its target queue.
* Aircraft are considered to have reached it if they are within 1px of point where they should join the queue, and are within 0.1 radians of the correct angle to join.
*
* @return whether the plane is able to join the queue
*/
public boolean isAtQueue()
{
Position target = targetQueue.getPosition();
if (
(where.getX() < (target.getX()+1))
&&
(where.getX() > (target.getX()-1))
&&
(where.getY() < (target.getY()+1))
&&
(where.getY() > (target.getY()-1))
&&
(Angle.diffClockwise(targetQueue.getAngle(), angle) < 0.1 || Angle.diffAnticlockwise(targetQueue.getAngle(), angle) < 0.1)
)
{ return true; }
return false;
}
/**
* Moves the position of the plane in the current angle at the current velocity the distance it would move in one time unit
*/
public void move()
{
where = Position.atAngleDistance(where, angle, velocity);
}
/**
* Change the angle of the plane the maximum angle possible in one time unit in order to point the plane towards a target
*
* @param target the position to home towards
*/
public void home(Position target)
{
//home to the point we have chosen
//calculate the angle from our present position to the target
double angToTarget = Position.angleToNorth(where, target);
angToTarget += (Math.PI);
//find the difference between the aircraft's current heading and the one to it's destination
float diff = Angle.diffClockwise((float) angToTarget, angle);
//if it is easiest to turn right to reach that angle turn right, otherwise turn left
if ( (diff > (Math.PI))) {
//Turn right
angle += anglechangerate;
}
else
{
//Turn left
angle -= anglechangerate;
}
angle = Angle.normal(angle);
}
/**
* Change the angle of the plane the maximum angle possible in one time unit in order to point the plane towards a target, and so that it reaches the target pointing in a specific direction.
* This method takes into account the turning circle of the plane.
*
* @param target the position to home towards
* @param targetAngle the angle the aircraft should point in when it reaches the destination
*/
public void homeAngleAndPosition(Position target, float targetAngle)
{
// radius of the circles planes turn in before landing
float turningCircle = 50F; //((float) (velocity/ (2 * Math.cos( (Math.PI/2) - (anglechangerate*0.8)))));
//id = String.valueOf(turningCircle);
//find the centres of the two turning circles
Position circleCentre1 = Position.atAngleDistance(target, targetAngle + ((float) (Math.PI/2)), turningCircle);
Position circleCentre2 = Position.atAngleDistance(target, targetAngle - ((float) (Math.PI/2)), turningCircle);
//calcuate the target:
// 1) find the angle to the circle centre
float theta1 = Position.angleToNorth(where, circleCentre1);
float theta2 = Position.angleToNorth(where, circleCentre2);
// 2) find the distance to the circle centre
float dist1 = Position.distance(where, circleCentre1);
float dist2 = Position.distance(where, circleCentre2);
// 3) find the angle from the circle centre
float rho1 = (float) Math.acos( (turningCircle/dist1) );
float rho2 = (float) Math.acos( (turningCircle/dist2) );
// check we've not got infinity; if we have, pretend it is 0
if (java.lang.Float.isNaN(rho1)) { rho1 = 0; };
if (java.lang.Float.isNaN(rho2)) { rho2 = 0; };
// 4) get the points on the turning circles where the approach intersects the circle
// (a) for the clockwise circle
Position circle1Target = Position.atAngleDistance(circleCentre1, theta1+rho1, turningCircle);
// (b) and for the anticlockwise circle
Position circle2Target = Position.atAngleDistance(circleCentre2, -(rho2-theta2), turningCircle);
//get the angle from the runway end to the two possible points
float ang = Position.angleToNorth(target, circle1Target);
float ang2 = Position.angleToNorth(target, circle2Target);
//find distance from target angle; choose the target position that has the smallest angle
ang = Angle.diffClockwise(ang, targetAngle);
ang2 = Angle.diffAnticlockwise(ang2, targetAngle);
if (ang > ang2)
{
home(circle2Target);
}
else
{
home(circle1Target);
}
}
/**
* Changes the angle of the plane the maximum amount possible in one unit of time. The direction of the change in angle depends on the state of the plane.
*/
public void findAngle()
{
if (state == 1) { angle -= anglechangerate; }
if (state == 2) { angle += anglechangerate; }
if (state == 3) { homeAngleAndPosition(targetQueue.getPosition(), targetQueue.getAngle()); }
if (state == 4) { angle += anglechangerate; }
if (state == 6) { home(Position.atAngleDistance(new Position(250,250), Position.angleToNorth(where, new Position(250,250)) , 250)); }
if (state == 0) { homeAngleAndPosition(targetRunway.getPosition(), targetRunway.getAngle()); }
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -