This repository has been archived by the owner on Aug 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPlayer.java
398 lines (338 loc) · 10.8 KB
/
Player.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
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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/**
* A player character
*
* Last edit: 6/18/2020
* @author Celeste, Eric
* @version 1.1
* @since 1.0
*/
import java.util.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class Player extends Character {
/**
* Contains key bindings for moving the player around
*/
public final RestaurantBindings restaurantMovement;
/**
* Key bindings for player jumping
*/
public final CashRunBindings cashRunMovement;
/**
* Contains key bindings for moving the player around
*/
public final FridgeTilesBindings fridgeTilesMovement;
/**
* ---
*/
public boolean jumped;
/**
* ---
*/
public int speed;
/**
* Keeps track of the player's hygiene throughout the game
*/
public HygieneTracker hygienicTracker;
/**
* Keeps track of the player's "failures" to prevent infection from the virus
*/
public Map<String, Integer> failures;
/**
* Static map of a male player's steps. Used to cache loading
*/
public static Map<String, Image> maleSteps;
/**
* Static map of a female player's steps. Used to cache loading
*/
public static Map<String, Image> femaleSteps;
static {
maleSteps = new HashMap<String, Image>();
femaleSteps = new HashMap<String, Image>();
}
/**
* Constructs a Character object and loads the appropriate sprites into the steps map
* @param name the Character's name, as chosen by the user
* @param gender the gender of the Character chosen
*/
public Player(String name, char gender) {
super(name,"player",gender);
speed = 0;
jumped = false;
hygienicTracker = new HygieneTracker();
failures = new HashMap<String, Integer>();
restaurantMovement = new RestaurantBindings();
fridgeTilesMovement = new FridgeTilesBindings();
cashRunMovement = new CashRunBindings();
}
/**
* Set player clothing
* @param clothing the clothing type
*/
public void setClothing(char clothing) {
clothingType = clothing;
}
/**
* Set player clothing
* @param equipment the protective equipment type
*/
public void setEquipment(String equipment) {
protectiveEquipment = equipment;
}
/**
* Adds a mask to the player's PPE, if not already present
*/
public void putOnMask() {
hygienicTracker.update("mask");
if (protectiveEquipment.indexOf("M") == -1)
protectiveEquipment = "M" + protectiveEquipment.replace("N","");
}
/**
* Removes a mask from the player's PPE, if present
*/
public void takeOffMask() {
if (protectiveEquipment.indexOf("M") != -1) {
protectiveEquipment = protectiveEquipment.substring(1);
if (protectiveEquipment.length() == 0) protectiveEquipment = "N";
}
}
/**
* Adds gloves to the player's PPE, if not already present
*/
public void putOnGloves() {
hygienicTracker.update("gloves");
if (protectiveEquipment.indexOf("G") == -1)
protectiveEquipment = protectiveEquipment.replace("N","") + "G";
}
/**
* Removes gloves from the player's PPE, if present
*/
public void takeOffGloves() {
protectiveEquipment = protectiveEquipment.charAt(0) == 'M' ? "M" : "N";
}
/**
* Cleans the users hands (i.e. updates the hand cleaning tracker)
*/
public void cleanHands() {
hygienicTracker.update("clean hands");
}
/**
* Set player coordinates and change outfit as necessary
* @param x the x coordinate
* @param y the y coordinate
*/
public void setCoordinates(int x, int y) {
super.setCoordinates(x, y);
setClothing(y > Restaurant.KITCHEN_LINE ? 'C' : 'W');
}
/**
* Loads the image files into the steps HashMap for each character subclass
*/
@Override
protected void loadSprites() {
if (gender == 'M' && maleSteps.size() == 0) maleSteps = loadSprites('M');
else if (gender == 'F' && femaleSteps.size() == 0) femaleSteps = loadSprites('F');
steps = gender == 'M' ? maleSteps : femaleSteps;
}
/**
* Loads the image files into a static steps HashMap
* <p> Intended to be called for preloading
* @param gender the gender to be loaded
*/
public static Map<String, Image> loadSprites(char gender) {
Map<String, Image> steps = new HashMap<String, Image>();
String[][] keys = {{"S", "E", "N", "W"},
{"1", "2", "3", "4"},
{"C", "W"},
{"N", "M", "G", "MG"}};
String[] imgs = {"C", "W", "W_M", "W_G", "W_MG"};
int[][][] coords = {{{112, 304}, {112, 288}, {96, 304}, {112, 288}},
{{112, 304}, {112, 352}, {96, 304}, {48, 352}},
{{112, 288}, {112, 288}, {112, 288}, {112, 288}},
{{112, 288}, {112, 352}, {112, 288}, {48, 352}}};
for(int s = 0; s < 5; s++) {
Image spritesheet = Utility.loadImage("Player"+gender+"_"+imgs[s]+".png",(int)(2048/4.8),(int)(2048/4.8));
BufferedImage buffsheet = Utility.toBufferedImage(spritesheet);
for(int y = 0; y < 4; y++) {
for(int x = 0; x < 4; x++) {
String key = keys[0][y]+"-"+keys[1][x]+"-"+(s==0?keys[2][0]:keys[2][1])+"-"+(s>1?keys[3][s-1]:keys[3][0]);
BufferedImage sprite = buffsheet
.getSubimage((int)(x*512/4.8+coords[(gender=='M'?0:2)+(s==0?0:1)][y][0]/4.8), (int)(y*512/4.8+16/4.8),
(int)(coords[(gender=='M'?0:2)+(s==0?0:1)][y][1]/4.8), 100);
steps.put(key, sprite);
}
}
}
return steps;
}
/**
* Checks the user's hygiene and updates the tracker.
* <p> This method is intended to be called in between stations.
* @param nextStn the next station that the user is about to go to
*/
public void checkHygiene(String nextStn) {
if (!nextStn.equals("covid counter")) {
if (getPPE().indexOf("M") == -1) {
addFailure("You did not wear a mask prior to a task");
}
if (!hygienicTracker.getLastTask().equals(nextStn) && !hygienicTracker.getLastTask("gloves").equals(hygienicTracker.getLastTask()) && !hygienicTracker.getLastTask("gloves").equals("covid counter")) {
addFailure("You did not change your gloves in between tasks");
}
}
hygienicTracker.setLastTask(nextStn);
}
/**
* Updates the list of improper preventative measures taken
* @param failure the failure to be updated
*/
public void addFailure(String failure) {
failures.put(failure, failures.getOrDefault(failure, 0) + 1);
}
@Override
public String getType() {
return "Player" + gender + "_" + clothingType + (protectiveEquipment.equals("N") ? "" : "_" + protectiveEquipment);
}
/**
* Keeps track of the frequency and/or presence of the player's hygienic practices
*/
private class HygieneTracker {
/**
* The last time, relative to the system time, that the player performed a "change" of some sort (the key, e.g. glove changing)
*/
private Map<String, Long> lastChangeTime;
/**
* The last task performed prior to changing a PPE
*/
private Map<String, String> lastChangeTask;
/**
* The last task that the user performed
*/
private String lastTask;
/**
* Default constructor
*/
public HygieneTracker() {
lastChangeTime = new HashMap<String, Long>();
lastChangeTask = new HashMap<String, String>();
lastTask = "entry";
}
/**
* Set the last change time of a given key to be the current moment
* @param key the key to be updated
*/
public void update(String key) {
if (key.equals("gloves")) {
if (!getLastTask("clean hands").equals(lastTask)) {
addFailure("You did not sanitize your hands before changing gloves");
}
}
lastChangeTime.put(key, System.currentTimeMillis());
lastChangeTask.put(key, lastTask);
}
/**
* @return the last time a given key word was changed, or -1 if it was never changed
*/
public long getLastUpdate(String key) {
return lastChangeTime.getOrDefault(key, -1l);
}
/**
* @return the last task prior to a given key word was changed, or "" if it was never changed
*/
public String getLastTask(String key) {
return lastChangeTask.getOrDefault(key, "");
}
public String getLastTask() {
return lastTask;
}
public void setLastTask(String task) {
lastTask = task;
}
}
/**
* Manages key bindings for the fridge tiles minigame
*/
public class FridgeTilesBindings extends ScreenMovement {
public FridgeTilesBindings() {
super("fridge");
}
@Override
protected void loadKeyBindings() {
movementMap.put("left", new Movement("left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if(x_coord-80 > 280)
x_coord -= 80;
}
}));
movementMap.put("right", new Movement("right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if(x_coord+80 < 520)
x_coord += 80;
}
}));
}
}
/**
* Manages key bindings for the cash run minigame
*/
public class CashRunBindings extends ScreenMovement {
public CashRunBindings() {
super("cash");
}
@Override
protected void loadKeyBindings() {
movementMap.put("jump", new Movement("jump", KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
jumped = true;
speed = 56;
}
}));
}
}
/**
* Manages key bindings for the restaurant
*/
public class RestaurantBindings extends ScreenMovement {
public RestaurantBindings() {
super("rest");
}
@Override
protected void loadKeyBindings() {
final String [] keys = {"up", "down", "left", "right"};
final char [] dirs = "NSWE".toCharArray();
final int [] strokes = {KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT};
for (int i=0;i<keys.length;i++) {
// resolves error: local variables referenced from an inner class must be final or effectively final
final int index = i;
movementMap.put(keys[index], new Movement(keys[index], KeyStroke.getKeyStroke(strokes[index], 0), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (lastMvTime.compareNow(dirs[index])) {
if (index < 2) y_coord += DELTA_DIST * (dirs[index] == 'N' ? -1 : 1);
else x_coord += DELTA_DIST * (dirs[index] == 'W' ? -1 : 1);
char origDir = direction;
direction = dirs[index];
if (hasCollided(Restaurant.boundaries)) {
// undo
if (index < 2) y_coord -= DELTA_DIST * (dirs[index] == 'N' ? -1 : 1);
else x_coord -= DELTA_DIST * (dirs[index] == 'W' ? -1 : 1);
direction = origDir;
return;
}
if (index < 2) {
setClothing(y_coord > Restaurant.KITCHEN_LINE ? 'C' : 'W');
int changeY = Restaurant.topY - DELTA_DIST* (dirs[index] == 'N' ? -1 : 1);
if ((index == 0 && changeY < 0 && y_coord < Restaurant.MAP_HEIGHT - Utility.FRAME_HEIGHT/2 - height/2) ||
(index == 1 && y_coord > (Utility.FRAME_HEIGHT - height)/2 && changeY > -Restaurant.MAP_HEIGHT + Utility.FRAME_HEIGHT))
Restaurant.topY = changeY;
}
stepNo++;
CovidCashier.frame.repaint();
}
}
}));
}
}
}
}