import greenfoot.*; import java.lang.Math.*; /** * Gun: shoots (i. e. emits) missiles (like a Factory). Handles shooting timeouts. * Can be put into a spaceship. * * @author Jannis Andrija Schnitzer, Martin Schend * @version 2011-01-22 */ public class Gun { /** * This variable determines how many turns the gun has to wait before it may emit another bullet. * It is counted down; when it reaches 0, we can shoot. Otherwise, the gun will just shoot out * thin air (i. e., a null pointer) when asked for a missile. * * @see #missile() */ protected int timer; /** * The number to which timer is set after a bullet has been launched. (I. e., the number of turns * that will pass between two missiles. */ protected int recovery; /** * Speed the missiles are set to when launched. */ protected Vector speed; /** * Side the gun (and so the missiles) is on. */ protected int side; /** * Level of the gun (and thus of the missiles). */ protected int level; /** * X distance of launched bullets from spaceship center. */ protected int dx; /** * @see #dx */ protected int dy; /** * Absolute value of the speed vector that's set to missiles. */ protected double abs_speed; /** * Angle the missiles are launched with (to y axis, value in radians). */ protected double angle; /** * Direction the gun is facing. Allows for easier dy calculation in subclasses. * * @see #dy */ protected int direction; /** * Initial recovery time of this kind of gun. (Without alteration by FasterGuns, that is.) */ public static int initial_recovery; public Gun(double the_abs_speed, double the_angle) { this.setSpeed(the_abs_speed, the_angle); init(); } public Gun(Vector the_speed) { this.setSpeed(the_speed); init(); } public Gun() { this(1.0, 0.0); } /** * Return an exact copy of this gun. Used especially in the MoreGuns powerup. * TODO: make this more dynamic. * * @see MoreGuns */ public Gun copy_gun() { Gun g = new Gun(abs_speed, angle); g.setRecovery(recovery); g.setLevel(level); return g; } protected void init() { timer = 0; recovery = 10; initial_recovery = -1; // *coughs* dx = 0; dy = 0; if (abs_speed < 0.0) direction = -1; else direction = 1; level = 1; } public void setSpeed(Vector the_speed) { speed = new Vector(the_speed); abs_speed = speed.length(); angle = Math.asin(speed.getX()/abs_speed); } public void setSpeed(double the_abs_speed, double the_angle) { abs_speed = the_abs_speed; angle = the_angle; speed = new Vector(abs_speed * Math.sin(angle), -abs_speed * Math.cos(angle)); } /** * Send a tick to the gun every time act() is called in the containing * spaceship. This is used to handle the internal firing timer. */ public void tick() { timer -= 1; } protected Missile get_missile() { return new Missile(); } /** * Emit a new bullet or null if not ready yet. * * @return the bullet or null */ public Missile missile() { if (timer <= 0) { Missile m = this.get_missile(); m.setSpeed(speed); m.setSide(side); m.setRotation((int)Math.toDegrees(angle)); timer = recovery; return m; } else { return null; } } public int get_dx() { return dx; } public int get_dy() { return dy; } public void set_dx(int new_dx) { dx = new_dx; } public void set_dy(int new_dy) { dy = new_dy; } public int getSide() { return side; } public void setSide(int new_side) { side = new_side; } public int getTimer() { return timer; } public void setTimer(int timer_value) { timer = timer_value; } public int getLevel() { return level; } public void setLevel(int the_level) { level = the_level; } public int getRecovery() { return recovery; } public void setRecovery(int the_recovery) { recovery = the_recovery; } public double getAbsSpeed() { return abs_speed; } public double getAngle() { return angle; } public static int getInitialRecovery() { return initial_recovery; } public static void setInitialRecovery(int the_recovery) { initial_recovery = the_recovery; } }