diff options
author | Alexander Kriegisch <Alexander@Kriegisch.name> | 2024-01-04 10:12:59 +0700 |
---|---|---|
committer | Alexander Kriegisch <Alexander@Kriegisch.name> | 2024-01-06 10:09:11 +0100 |
commit | 61ceb8a58ea72d4c07ff0b2f669d5f84b75700ec (patch) | |
tree | 857d468f6c8cc4d83370ed9d526e79f3abdb3f2a /docs/examples/spacewar/Ship.java | |
parent | f7962810eca3ddda75d64b85caab2449eeff480e (diff) | |
download | aspectj-61ceb8a58ea72d4c07ff0b2f669d5f84b75700ec.tar.gz aspectj-61ceb8a58ea72d4c07ff0b2f669d5f84b75700ec.zip |
Move docs examples directory two levels up
Now, the location more closely resembles where it is on the website.
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/examples/spacewar/Ship.java')
-rw-r--r-- | docs/examples/spacewar/Ship.java | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/docs/examples/spacewar/Ship.java b/docs/examples/spacewar/Ship.java new file mode 100644 index 000000000..9978fe694 --- /dev/null +++ b/docs/examples/spacewar/Ship.java @@ -0,0 +1,296 @@ +/* + +Copyright (c) Xerox Corporation 1998-2002. All rights reserved. + +Use and copying of this software and preparation of derivative works based +upon this software are permitted. Any distribution of this software or +derivative works must comply with all applicable United States export control +laws. + +This software is made available AS IS, and Xerox Corporation makes no warranty +about the software, its performance or its conformity to any specification. + +|<--- this code is formatted to fit into 80 columns --->| +|<--- this code is formatted to fit into 80 columns --->| +|<--- this code is formatted to fit into 80 columns --->| + +Ship.java +Part of the Spacewar system. + +*/ + +package spacewar; + +class Ship extends SpaceObject { + + pointcut helmCommandsCut(Ship ship): + target(ship) && ( call(void rotate(int)) || + call(void thrust(boolean)) || + call(void fire()) ); + + + /** + * Energy and Damage are key values in the state of a ship. Energy is + * basically about fuel, and damage is about how bad a shape we are in. + * + * The energy related values are: + * <ul> + * <li>MAX_ENERGY</li> + * <li>BULLET_ENERGY</li> + * <li>ACCELERATION_ENERGY_FACTOR</li> + * <li>energy</li> + * </ul> + * The damage related values are: + * <ul> + * <li>MAX_DAMAGE</li> + * <li>BULLET_DAMAGE</li> + * <li>COLLISION_DAMAGE_FACTOR</li> + * <li>damage</li> + * </ul> + * Finally, REPAIR_RATE is the rate at which energy is consumed to fix + * damage. + * + */ + private static final int MAX_ENERGY = 100; + private static final int BULLET_ENERGY= 2; + private static final double ACCELERATION_COST_FACTOR = 0.05; + + //XXX was private + static final int MAX_DAMAGE = 100; + private static final int BULLET_DAMAGE = 15; + private static final double COLLISION_DAMAGE_FACTOR = 0.1; + + private static final double REPAIR_RATE = 0.08; + + + private static final int EXPLOSION_LENGTH = 10; + + static final int BULLET_SPEED = 10; + + static final int CLOCKWISE = 1; + static final int STOP = 0; + static final int COUNTERCLOCKWISE = (-1); + + static final double DEFAULT_ANGULAR_VELOCITY = 0.2; + static final double DEFAULT_ACCELERATION = .4; + + static private final int SIZE = 30; //Can't be changed for now!!! + + private double energy; // range: 0 to MAX_ENERGY + private double damage; // range: 0 to MAX_DAMAGE + private double orientation; // in degrees + private double angularVel; // in ??? + private double xAcc, yAcc, rAcc; // + private int countdown; // remaining explosion time + + private Pilot pilot; + + Ship(Game theGame, double xPos, double yPos, double orientation) { + super(theGame, xPos, yPos, 0, 0); + xAcc = 0; + yAcc = 0; + this.orientation = orientation; + angularVel = 0; + + energy = MAX_ENERGY; + damage = 0; + countdown = EXPLOSION_LENGTH; + } + + + int getSize() { return SIZE; } + + double getEnergy() { return energy; } + double getDamage() { return damage; } + double getOrientation() { return orientation; } + double getRAcc() { return rAcc; } + + Pilot getPilot() { return pilot; } + void setPilot (Pilot p) { pilot = p; } + + float getEnergyLevel() { + return (float)energy / (float)MAX_ENERGY; + } + float getDamageLevel() { + return (float)damage / (float)MAX_DAMAGE; + } + + /** returns false if energy is out, otherwise decrements energy by amount + * and returns true + */ + boolean expendEnergy(double amount) { + if (amount <= energy) { + energy -= amount; + return true; + } + else + return false; + } + + /** increments damage by amount and handles the destruction of a ship if + * damage reaches MAX_DAMAGE. + */ + void inflictDamage(double amount) { + if (amount < 0) // shouldn't happen + return; + damage = Math.min(MAX_DAMAGE, damage + amount); + if (damage == MAX_DAMAGE) + setIsAlive(false); + } + + /** repairs some damage + */ + void repairDamage(double amount) { + if (amount < 0) // shouldn't happen + return; + if (damage == 0) + return; + damage = Math.max(0, damage - amount); + } + + public void clockTick() { + if (! isAlive()) { + // + // If we aren't alive, but we are still in the registry, it means + // we are exploding. countdown counts the length of the explosion. + // + if (--countdown == 0) + die(); + } + else { + if (angularVel != 0) { + orientation += angularVel; + xAcc = rAcc * Math.cos(orientation); + yAcc = rAcc * Math.sin(orientation); + } + setXVel(getXVel() + xAcc); + setYVel(getYVel() + yAcc); + + //expend energy + if (!expendEnergy(rAcc * ACCELERATION_COST_FACTOR)) + rAcc = xAcc = yAcc = 0; + + // fix damage + if (energy > 10 && damage > REPAIR_RATE) { + expendEnergy(REPAIR_RATE); + repairDamage(REPAIR_RATE); + } + } + super.clockTick(); + } + + /** + * First check to make sure we have enough energy to accelerate. If + * we do, then go ahead and do so. Acceleration is in the direction + * we are already facing (i.e. orientation). + */ + void setAcceleration(double acc) { + if (acc * ACCELERATION_COST_FACTOR <= energy) { + rAcc = acc; + xAcc = rAcc * Math.cos(orientation); + yAcc = rAcc * Math.sin(orientation); + } + } + + /** + * First check to make sure we have enough energy to rotate. If + * we do, then go ahead and do so. + */ + void setAngularVelocity(double omega) { + // changing direction of rotation takes energy + if (!expendEnergy(Math.abs(omega - angularVel) / 2)) + return; + //sets amount of degree rotation per clock tick, in radians; + //clockwise is positive + angularVel = omega; + } + + /** affect rotation thrusters. Direction can be one of {@link + * #CLOCKWISE}, {@link #COUNTERCLOCKWISE}, or zero for turning off + * the thrusters. + */ + void rotate(int direction) { + setAngularVelocity( + direction == CLOCKWISE ? DEFAULT_ANGULAR_VELOCITY : + direction == COUNTERCLOCKWISE ? -DEFAULT_ANGULAR_VELOCITY : + 0); + } + + /** turn on acceleration */ + void thrust(boolean onOff) { + setAcceleration(onOff ? DEFAULT_ACCELERATION : 0); + } + + /** create a bullet and fire it */ + void fire() { + // firing a shot takes energy + if (!expendEnergy(BULLET_ENERGY)) + return; + + //create a bullet object so it doesn't hit the ship that's firing it + double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); + double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); + + // create the actual bullet + new Bullet( + getGame(), + (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), + (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), + xV, + yV); + } + + + void handleCollision(SpaceObject obj) { + if (obj instanceof Ship) { + // should never be called. ship - ship collisions are handled in + // Ship.bounce(Ship shipA, Ship shipB) + } + else if (obj instanceof Bullet) { + inflictDamage(BULLET_DAMAGE); + } + else if (obj instanceof EnergyPacket) { + double packetEnergy = ((EnergyPacket)obj).getEnergy(); + energy = Math.max(0, Math.min(energy + packetEnergy, MAX_ENERGY)); + } + else { + System.err.println("collision with UFO!"); + } + } + + static void bounce(Ship shipA, Ship shipB) { + double dx, dy, denominator, + xAccA, yAccA, xAccB, yAccB, damage, + xComp, yComp, dvx, dvy; + + dx = Math.abs(shipA.getXPos() - shipB.getXPos()); + dy = Math.abs(shipA.getYPos() - shipB.getYPos()); + denominator = Math.sqrt(dx * dx + dy * dy); + xComp = dx / denominator; + yComp = dy / denominator; + xAccA = shipB.getXVel() * xComp + shipA.getXVel() * (1 - xComp) - + shipA.getXVel(); + yAccA = shipB.getYVel() * yComp + shipA.getYVel() * (1 - yComp) - + shipA.getYVel(); + xAccB = shipA.getXVel() * xComp + shipB.getXVel() * (1 - xComp) - + shipB.getXVel(); + yAccB = shipA.getYVel() * yComp + shipB.getYVel() * (1 - yComp) - + shipB.getYVel(); + shipA.accelerate(xAccA, yAccA); + shipB.accelerate(xAccB, yAccB); + dvx = shipA.getXVel() - shipB.getXVel(); + dvy = shipA.getYVel() - shipA.getYVel(); + damage = COLLISION_DAMAGE_FACTOR * (dvx * dvx + dvy * dvy); + shipA.inflictDamage(damage); + shipB.inflictDamage(damage); + + // !!! + // !!! poopers! this does a local time warp. this has to be a + // !!! violation of the clockTick protocol + // !!! + while (Game.isCollision(shipA, shipB)) { + shipA.clockTick(); + shipB.clockTick(); + } + } +} |