Ship07.java
package com.bozoid.cis370.hw07;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*; // for AffineTransform
import javax.swing.*;
import java.util.Date; // for getTime()
/**
A simple spaceship for CISC370-011 homework #7.
@author Walt Leipold
*/
public class Ship07
{
/**
Create a <code>Ship07</code> at the specified location and angle.
@param x initial x-location of the Ship07
@param y initial y-location of the Ship07
@param theta initial angle of the Ship07 (vertical==PI/2)
*/
public Ship07(double x,double y,double theta)
{
ship_x = x;
ship_y = y;
ship_theta = theta;
fuel_used = 0.0;
lastTime = (new Date()).getTime();
}
/**
Draw the ship on the specified graphics context.
@param g <code>Graphics</code> context to draw on
@param cmd_main is the main thruster firing?
@param cmd_cw is the clockwise thruster firing?
@param cmd_ccw is the counterclockwise firing?
*/
public void drawShip(Graphics g,
boolean cmd_main,
boolean cmd_cw,
boolean cmd_ccw)
{
AffineTransform af = new AffineTransform();
af.scale(1.0,-1.0); // To get a right-handed coord system.
af.translate(ship_x,ship_y);
af.rotate(ship_theta);
vplot(g,hull,ship_color,af);
if (cmd_main)
vplot(g,flame,flame_color,af);
if (cmd_cw)
vplot(g,rcs_cw,flame_color,af);
if (cmd_ccw)
vplot(g,rcs_ccw,flame_color,af);
}
/**
Plot a list of point lists in the given color, with coordinates
transformed according the the given AffineTransform.
@param g The graphics context.
@param v An array of arrays of doubles, each of which stores
a list of points in [x,y,x,y,...] order. For each array
of doubles, the method plots a line of the specified color
between each adjacent pair of points.
@param c <code>Color</code> to draw with.
@param af An <code>AffineTransform</code> to transform each (x,y)
pair from simulation space to window coordinates before
plotting.
*/
public static void vplot(Graphics g,
double[][] v,Color c,AffineTransform af)
{
int i,j;
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(c);
for (i=0; i<v.length; i++) {
double temp[] = new double[v[i].length];
af.transform(v[i],0,temp,0,v[i].length/2);
for (j=0; j<v[i].length-3; j+=2)
g2.drawLine(
(int)(temp[j]), (int)(temp[j+1]),
(int)(temp[j+2]),(int)(temp[j+3]));
}
}
/**
Every tick of the timer, simulate the fuel consumption and
constant-speed rotation of the ship.
@param cmd_main is the main thruster firing?
@param cmd_cw is the clockwise thruster firing?
@param cmd_ccw is the counterclockwise thruster firing?
*/
public void oneTick(
boolean cmd_main,
boolean cmd_cw,
boolean cmd_ccw)
{
long tstamp = (new Date()).getTime();
double time_increment = // Time (secs) since last frame.
(double)(tstamp - lastTime)/1000.0;
if (active) {
if (cmd_cw) { // Clockwise thruster.
fuel_used += CW_FLOW * time_increment;
v_theta -= ANG_ACCEL * time_increment;
}
if (cmd_ccw) { // Counterclockwise thruster.
fuel_used += CCW_FLOW * time_increment;
v_theta += ANG_ACCEL * time_increment;
}
if (cmd_main) { // Main thruster.
fuel_used += MAIN_FLOW * time_increment;
v_x += Math.cos(ship_theta) *
LINEAR_ACCEL * time_increment;
v_y += Math.sin(ship_theta) *
LINEAR_ACCEL * time_increment;
}
// Add in the (possible) gravitational component.
v_y -= gravity * time_increment;
// Now that we've updated all the velocities, update
// the ship's position and angle.
ship_x += v_x * time_increment;
ship_y += v_y * time_increment;
ship_theta += (v_theta * time_increment) % (2.0*Math.PI);
}
lastTime = tstamp;
}
// Accessors.
public boolean getActive() { return active; }
public double getX() { return ship_x; }
public double getY() { return ship_y; }
public double getTheta() { return ship_theta; }
public double getFuel() { return fuel_used; }
public double getGravity() { return gravity; }
// Mutators.
public void setActive(boolean flag) { active = flag; }
public void setX(double x) { ship_x = x; }
public void setY(double y) { ship_y = y; }
public void setGravity(double gravity) { this.gravity = gravity; }
// Where is the ship, and how fast is it moving?
private double ship_x = 0.0;
private double ship_y = 0.0;
private double ship_theta = Math.PI/2.0;
private double v_x = 0.0;
private double v_y = 0.0;
private double v_theta = 0.0;
private double gravity = 0.0; // Force in negative y direction.
private double fuel_used = 0.0; // Fuel accumulator.
private long lastTime = 0; // Real time of last sim step.
private boolean active = true; // Is the simulation active?
private double ANG_ACCEL = 0.6; // radians/sec2
private double LINEAR_ACCEL = 25.0; // pixels/sec2
// Flow rates in kg/s.
static final double CW_FLOW = 5.0;
static final double CCW_FLOW = 5.0;
static final double MAIN_FLOW = 50.0;
// Colors and point lists for the ship and flame shapes.
private Color ship_color = Color.WHITE;
private Color flame_color = Color.RED;
private static double[][] hull,flame,rcs_ccw,rcs_cw;
static {
hull = new double[][] { // The ship.
{ 78.0, 0.0, // hull
40.0, 9.0,
26.0, 10.0,
-8.0, 10.0,
-50.0, 6.0,
-50.0, -6.0,
-8.0, -10.0,
26.0, -10.0,
40.0, -9.0,
78.0, 0.0},
{ 35.0, 3.0, // window 1
32.0, 0.0,
35.0, -3.0,
38.0, 0.0,
35.0, 3.0},
{ 22.0, 3.0, // window 2
19.0, 0.0,
22.0, -3.0,
25.0, 0.0,
22.0, 3.0},
{ 9.0, 3.0, // window 3
6.0, 0.0,
9.0, -3.0,
12.0, 0.0,
9.0, 3.0},
{-50.0, 6.0, // right fin
-8.0, 10.0,
-70.0, 34.0,
-50.0, 6.0},
{-50.0, -6.0, // left fin
-8.0, -10.0,
-70.0, -34.0,
-50.0, -6.0},
{-70.0, 2.0, // center fin
-8.0, 0.0,
-70.0, -2.0,
-70.0, 2.0}};
flame = new double[][] { // Main thruster flame.
{ -50.0, -6.0, -96.0, 0.0, -50.0, 6.0}};
rcs_ccw = new double[][] { // Counterclockwise thruster flame.
{ 26.0, -10.0, 26.0, -34.0},
{ 26.0, -10.0, 36.0, -26.0},
{ 26.0, -10.0, 16.0, -26.0},
{ -8.0, 10.0, -8.0, 34.0},
{ -8.0, 10.0, 0.0, 26.0},
{ -8.0, 10.0, -16.0, 26.0}};
rcs_cw = new double[][] { // Clockwise thruster flame.
{ 26.0, 10.0, 26.0, 34.0},
{ 26.0, 10.0, 36.0, 26.0},
{ 26.0, 10.0, 16.0, 26.0},
{ -8.0, -10.0, -8.0, -34.0},
{ -8.0, -10.0, 0.0, -26.0},
{ -8.0, -10.0, -16.0, -26.0}};
}
}