-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShip.java
166 lines (131 loc) · 4.03 KB
/
Ship.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import javax.swing.*;
import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.Observable;
class Ship extends Observable {
// FPS and initial position for ship to appear
public Ship(int fps, int x, int y) {
startPosition = new Point2d(x, y);
// set the dynamics based on 60 fps
double scale = 60.0 / fps;
thrust = 0.25 * scale;
gravity = 0.01 * scale;
decay = 0.005 * scale;
// the ship has it's own animation timer
timer = new Timer((int)(1000/fps), new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
update();
setChangedAndNotify();
}
});
reset(startPosition);
}
// animation timer
Timer timer;
// get the ship shape model
public final Rectangle2D.Double getShape() {
return new Rectangle2D.Double(position.x, position.y, 10, 10);
}
// resets the ship state to a start position and full tank
public void reset(Point2d position) {
this.position = (Point2d)position.clone();
velocity = new Vector2d(0, 0);
fuel = 50;
setPaused(true);
setChangedAndNotify();
}
// stop the ship
public void stop() {
velocity = new Vector2d(0, 0);
setPaused(true);
setChangedAndNotify();
}
public boolean isPaused() {
return !timer.isRunning();
}
public void setPaused(boolean paused) {
if (paused)
timer.stop();
else
timer.start();
setChangedAndNotify();
}
public Point2d getPosition() {
return position;
}
// where to put ship at start of game
Point2d startPosition;
// current postion of ship
Point2d position;
// safe landing speed
public double getSafeLandingSpeed() { return thrust; }
// direction and magnitude of ship movement
public Vector2d getVelocity() {
return velocity;
}
// magnitude of the ship's movement
public double getSpeed() {
return velocity.length();
}
Vector2d velocity = new Vector2d(0, 0);
// track how much fuel was used
public double getFuel() {
return fuel;
}
public void setFuel(int fuel) { this.fuel = fuel; }
double fuel;
// movement dynamics
double thrust;
double gravity;
double decay;
// animation update, call once per "frame"
public void update() {
// decay thrust with deadband
if (velocity.x > decay)
velocity.x -= decay;
else if (velocity.x < decay)
velocity.x += decay;
else
velocity.x = 0;
if (velocity.y > decay)
velocity.y -= decay;
else if (velocity.y < decay)
velocity.y += decay;
else
velocity.y = 0;
// keep it falling
velocity.y += gravity;
// finally update the position
position.add(velocity);
}
// methods to control the ship
// convienience methods for cardinal thrust directions
public void thrustUp() {
thrustVector(new Vector2d(0, -thrust));
}
public void thrustDown() {
thrustVector(new Vector2d(0, thrust));
}
public void thrustLeft() {
thrustVector(new Vector2d(-thrust, 0));
}
public void thrustRight() {
thrustVector(new Vector2d(thrust, 0));
}
// apply a vector of thrust
void thrustVector(Vector2d v) {
if (!isPaused() && fuel > 0) {
velocity.add(v);
fuel = Math.max(fuel - 1, 0);
}
}
// observable interface helper (often call these two together)
public void setChangedAndNotify() {
setChanged();
notifyObservers();
}
}