-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathQActor.java
More file actions
320 lines (296 loc) · 13 KB
/
Copy pathQActor.java
File metadata and controls
320 lines (296 loc) · 13 KB
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
import greenfoot.*;
/**
* CLASS: QActor (subclass of Actor)<br>
* AUTHOR: danpost (greenfoot.org username)<br>
* CREATION DATE: September 5, 2014<br>
* MODIFIED: October 6, 2014 - seperated rotation and movement vectors;
* also, changed from using vector and speed fields to horizontal and vertical speed fields<br>
* MODIFIED: October 8, 2014 - added two needed 'move' methods and corrected documentation<br>
* <br>
* NOTE: not intended for use in gridded worlds (worlds with a cell-size greater than one).<br>
* <br>
* DESCRIPTION: an extension of the Actor class that provides smooth movement and turning; also,
* it provides options for the behavior of the actor, 'boundedAction', when reaching bounded limits
* (the edges of the world plus or minus an offset value saved in the'boundedRange' field.<br>
* <br>
* The class works by dividing each unit (pixel or degree) into 1/100ths of that unit. When adding an
* actor into the world, setting its location in the world or setting its rotation, normal values are
* given. When moving or turning (adjusting using the current location or rotation as a reference), one
* hundred times the actual changes are given. The values given do not have to be even multiples of one
* hundred, which allows multiple in-between speeds of moving and turning to be available to your actors,
* including very small rates of speed without the need for delay counters.
*
* The class contains horizontal and vertical speed fields, 'vX' and 'vY' that work in the same unitary
* scale. There are methods to get and set these field values and a method, 'addForce' to adjust these
* values by way of applying a force which is represented by a length (strength of force) and vector
* (direction of force). Both parts of the force are given in '100x' for accuracy.
*/
public abstract class QActor extends Actor
{
protected static final int QVAL = 100; // smoothness value
/** bounds action value -- indicates no restrictions */
protected static final int UNBOUND = 0;
/** bounds action value -- indicates no movement beyond bounds */
protected static final int LIMIT = 1;
/** bounds action value -- indicates actor is removed upon reaching bounds */
protected static final int REMOVE = 2;
/** bounds action value -- indicates actor is transported to opposite world edge upon reaching bounds */
protected static final int WRAP = 3;
/** bounds action value -- indicates actor turns toward center upon reaching bounds */
protected static final int BOUNCE = 4;
/** Speed, specially for chaser, by default is 100 */
private static int healthPower;
public static int speed = 1;
private int qX, qY; // fine-tuned location coordinates (100x)
private int vX, vY; // fine-tuned speeds along the horizontal axis and the vertial axis (100x)
private int qR; // fine-tuned rotation (100x)
private int boundedAction, boundedRange; // world edge fields
private boolean rotationalBounce;
/**
* as the main method for movement, uses the current horizontal and vertical speed values to
* relocate the actor, then checks the bounds of the actor to perform set actions; all 'move'
* methods call this method and can be called by subclasses for continuous movement along the
* same direction; the other methods that use it are 'move(int)', which will move the actor in the
* direction it is facing and 'move(int, int)', which will move the actor in the direction given.
*/
public void move()
{
qX += vX; // adjust x coordinate value of q-location
qY += vY; // adjust y coordinate value of q-locaation
super.setLocation(qX/QVAL, qY/QVAL); // set current location of actor
boundsAct(); // check for and perform bounded edge action
rotationalBounce = false;
}
/**
* overrides the Actor class 'setLocation(int, int)' method to allow the q-location values to be corrected
*
* @param x the world x location to place the actor
* @param y the world y location to place the actor
*/
public void setLocation(int x, int y)
{
super.setLocation(x, y); // set location of actor
qX = getX()*QVAL; // set x coordinate value of q-location
qY = getY()*QVAL; // set y coordinate value of q-location
}
/**
* overrides the Actor class 'turn(int)' method to allow the q-rotation value to be adjusted
*
* @param amount the change in rotation as a fine-tuned value (100x)
*/
public void turn(int amount)
{
qR = (qR+amount+360*QVAL)%(360*QVAL); // adjust q-rotation value
super.setRotation(qR/QVAL); // set current rotation
}
/**
* overrides the Actor class 'turnTowards(int, int)' method to allow the q-rotation value to be corrected
*
* @param x the world x coordinate of the point to face
* @param y the world y coordinate of the point to face
*/
public void turnTowards(int x, int y)
{
super.turnTowards(x, y); // turn towards point
qR = getRotation()*QVAL; // set q-rotation value
}
/**
* overrides the Actor class 'setRotation(int)' method to allow the q-rotation value to be corrected
*
* @param angle the angle in degrees at which the rotation of the actor is to be set
*/
public void setRotation(int angle)
{
super.setRotation(angle); // set actor rotation
qR = getRotation()*QVAL; // set q-rotation value
}
/**
* adds a force to the movement of the actor
*
* @param amount the strength of the force as a fine-tuned value (100x)
* @param direction the direction of the force in fine-tuned degrees (100x)
*/
public void addForce(int amount, int direction)
{
amount = amount * speed;
vX += Math.cos((double)direction*Math.PI/(180*QVAL))*(double)amount; // new horizontal speed
vY += Math.sin((double)direction*Math.PI/(180*QVAL))*(double)amount; // new vertical speed
}
/**
* applys a force to (moves) the actor
*
* @param amount the strength of the force as a fine-tuned value (100x)
* @param direction the direction of the force in fine-tuned degrees (100x)
*/
public void move(int amount, int direction)
{
int holdX = vX, holdY = vY; // save the current values
vX = 0; vY = 0; // clear the values
addForce(amount, direction);
move();
vX = holdX; vY = holdY; // restore saved values
}
/**
* overrides the Actor class 'move(int)' method to use the given fine-tuned distance with the
* fine-tuned rotation of the actor for the direction
*
* @param amount the fine-tuned distanc value to move (100x)
*/
public void move(int amount)
{
move(amount, qR);
rotationalBounce = true;
}
/**
* sets the action and range fields for behavior when bounds are exceeded by actor
*
* @param action one of the bounds action values of this class
* @param range offset from edge the action is to occur
*/
public void setBoundedAction(int action, int range)
{
boundedAction = action%5; // the given action
boundedRange = range; // the given range offset where positive direction is away from center
}
/**
* internal method to perform the bounded action that is currently set to the actor
*/
private void boundsAct()
{
switch(boundedAction)
{
case UNBOUND: // no bounded action taken
break;
case LIMIT: // no movement beyond bounds
if (qX <= -boundedRange*QVAL)
{
setQLocation(-boundedRange*QVAL, qY);
if (vX < 0) vX = 0;
}
if (qY <= -boundedRange*QVAL)
{
setQLocation(qX, -boundedRange*QVAL);
if (vY < 0) vY = 0;
}
if (qX >= (getWorld().getWidth()+boundedRange-1)*QVAL)
{
setQLocation((getWorld().getWidth()+boundedRange-1)*QVAL, qY);
if (vX > 0) vX = 0;
}
if (qY >= (getWorld().getHeight()+boundedRange-1)*QVAL)
{
setQLocation(qX, (getWorld().getHeight()+boundedRange-1)*QVAL);
if (vY > 0) vY = 0;
}
break;
case REMOVE: // actor is removed at bounds
if (getX() <= -boundedRange ||
getX() >= getWorld().getWidth()+boundedRange-1 ||
getY() <= -boundedRange ||
getY() >= getWorld().getHeight()+boundedRange-1)
getWorld().removeObject(this);
break;
case WRAP: // actor is transported to opposite world edge at bounds
if (getX() <= -boundedRange)
setLocation(getX()+getWorld().getWidth()+boundedRange*2-2, getY());
else if (getY() <= -boundedRange)
setLocation(getX(), getY()+getWorld().getHeight()+boundedRange*2-2);
else if (getX() >= getWorld().getWidth()+boundedRange-1)
setLocation(1-boundedRange, getY());
else if (getY() >= getWorld().getHeight()+boundedRange-1)
setLocation(getX(), 1-boundedRange);
break;
case BOUNCE: // actor faces toward center at bounds
if (rotationalBounce)
{
if ((getX() <= -boundedRange && qR > 9000 && qR < 27000) || (getX() >= getWorld().getWidth()+boundedRange-1 && (qR < 9000 || qR > 27000)))
{
setQRotation((54000-qR)%36000);
}
if ((getY() <= -boundedRange && qR > 18000) || (getY() >= getWorld().getHeight()+boundedRange-1 && qR < 18000))
{
setQRotation((72000-qR)%36000);
}
}
else
{
if ((getX() <= -boundedRange && vX < 0) || (getX() >= getWorld().getWidth()+boundedRange-1 && vX > 0)) vX = -vX;
if ((getY() <= -boundedRange && vY < 0) || (getY() >= getWorld().getHeight()+boundedRange-1 && vY > 0)) vY = -vY;
}
break;
}
}
/**
* sets the location of the actor to fined-tuned coordinate values
*
* @param x the fine-tuned x-coordinate value (100x)
* @param y the fine-tuned y-coordinate value (100x)
*/
public void setQLocation(int x, int y)
{
qX = x;
qY = y;
super.setLocation(qX/QVAL, qY/QVAL);
}
/**
* sets the rotation of the actor to a fined-tuned value
*
* @param amount the fine-tuned rotational value for the actor in degrees (100x)
*/
public void setQRotation(int amount)
{
qR = amount;
super.setRotation(qR/QVAL);
}
/**
* returns the fine-tuned x-coordinate for the locationof the actor (100x)
*
* @return the fine-tuned value of the x-coordinate for the location of the actor
*/
protected int getQX() { return qX; }
/**
* returns the fine-tuned y-coordinate for the location of the actor (100x)
*
* @return the fine-tuned value of the y-coordinate for the location of the actor
*/
protected int getQY() { return qY; }
/**
* returns the fine-tuned rotation of the actor (100x)
*
* @return the fine-tuned rotation of the actor
*/
protected int getQR() { return qR; }
/**
* returns the fine-tuned speed along the horizontal (100x)
*
* @return the fine-tuned value of the speed of the actor along the horizontal
*/
protected int getVX() { return vX; }
/**
* returns the fine-tuned speed along the vertical (100x)
*
* @return the fine-tuned value of the speed of the actor along the vertical
*/
protected int getVY() { return vY; }
/**
* sets the horizontal speed to the given fine-tuned value (100x)
*
* @param speed the fine-tuned value the horizontal speed is to be set to
*/
protected void setVX(int speed) { vX = speed; }
/**
* sets the vertical speed to the given fine-tuned value (100x)
*
* @param speed the fine-tuned value the horizontal speed is to be set to
*/
protected void setVY(int speed) { vY = speed; }
public static void setHealthPower(int hp) {
healthPower = hp;
}
public static int getHealthPower() {
return healthPower;
}
public static void setSpeed(int p_speed) {
speed = p_speed;
}
}