You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

363 lines
10 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. package playground;
  2. import java.awt.Graphics2D;
  3. import java.util.HashMap;
  4. import java.util.LinkedList;
  5. import java.util.Map;
  6. import java.util.Stack;
  7. import java.awt.event.*;
  8. import gameobjects.GameObject;
  9. import org.apache.logging.log4j.Logger;
  10. import org.apache.logging.log4j.LogManager;
  11. /**
  12. * Playground represents a level of the game, focusing on the game LOGIC, i.e., not so much on the
  13. * graphical representation. In particular, an instance of Playground
  14. * <ul>
  15. * <li>manages the different moving or static objects in a level (e.g., collisions, adding objects,
  16. * removing objects). This is mainly done by the methods {@link #addObject}, {@link #deleteObject}.
  17. * <li>processes keyboard inputs provided by GameLoop in {@link #processKeyEvents(Stack)} and
  18. * {@link #processMouseEvents(Stack)}
  19. * <li>represents the state of a level represented by <b>flags</b>. Each flag has a name (a String)
  20. * and an arbitrary value of any type. Methods: {@link #setLevelFlag(String, Object)},
  21. * {@link #getLevelFlag(String)}. As an example, the current score is a flag usually named "points",
  22. * with an Integer as a value. This value can be retrieved and manipulated using the above mentioned
  23. * methods.
  24. * </ul>
  25. */
  26. public abstract class Playground {
  27. public static final int FLAGS_GLOBAL = 1;
  28. public static final int FLAGS_LEVEL = 2;
  29. public static final int FLAGS_ALL = 3;
  30. protected int canvasX = -1;
  31. protected int canvasY = -1;
  32. /** only one set of objects exists concurrently so this can be static */
  33. protected static HashMap<String, GameObject> gameObjects = new HashMap<String, GameObject>();
  34. /** only one set of objects exists concurrently so this can be static */
  35. protected static HashMap<String, Object> flags = new HashMap<String, Object>();
  36. protected String level = "";
  37. protected double timeStep = 0;
  38. protected double gameTime = 0;
  39. LinkedList<GameObject> addables = new LinkedList<GameObject>();
  40. LinkedList<String> removables = new LinkedList<String>();
  41. // HashMap<Integer,Integer> keys ;
  42. Stack<KeyEvent> keyEvents;
  43. Stack<MouseEvent> mouseEvents;
  44. protected boolean pausedFlag = false;
  45. private static Logger logger = LogManager.getLogger(Playground.class);
  46. public Playground() {
  47. this.canvasX = -1;
  48. this.canvasY = -1;
  49. }
  50. // here, the level communicates its size preference to the GameUI
  51. // called automatically
  52. public abstract int preferredSizeX();
  53. public abstract int preferredSizeY();
  54. /**
  55. * Adds a graphics object to a level.
  56. *
  57. * @param o GameObject The object to be added
  58. */
  59. public void addObject(GameObject o) {
  60. // gameObjects.put(o.getId(), o);
  61. addables.addLast(o);
  62. }
  63. /**
  64. * Adds a graphics object to a level.
  65. *
  66. * @param o GameObject The object to be added
  67. */
  68. public void addObjectNow(GameObject o) {
  69. gameObjects.put(o.getId(), o);
  70. }
  71. /**
  72. * Puts objects with a certain substring in their name into a LinkedLisrt and returns them.
  73. *
  74. * @param substr The string that must be part of the object name if object is to be
  75. * considered found.
  76. * @param filterInactive if set true only active objects are considered.
  77. * @return a reference to a LinkedList filled with all objects that have <b>substr</b> in their name
  78. */
  79. public LinkedList<GameObject> collectObjects(String substr, boolean filterInactive) {
  80. LinkedList<GameObject> l = new LinkedList<GameObject>();
  81. for (Map.Entry<String, GameObject> entry : Playground.gameObjects.entrySet()) { // Iterator
  82. // usage
  83. GameObject obj = entry.getValue();
  84. if (obj.getId().contains(substr)) {
  85. if (filterInactive == true) {
  86. if (obj.isActive()) {
  87. l.add(obj);
  88. }
  89. } else {
  90. l.add(obj);
  91. }
  92. }
  93. }
  94. return l;
  95. };
  96. /**
  97. * Removes a graphics object from a level.
  98. *
  99. * @param id String The unique identifier of the object
  100. */
  101. public void deleteObject(String id) {
  102. // gameObjects.remove(id);
  103. removables.addLast(id);
  104. }
  105. /**
  106. * Removes a graphics object from a level immediately, CAUTION.
  107. *
  108. * @param id String The unique identifier of the object
  109. */
  110. public void deleteObjectNow(String id) {
  111. gameObjects.remove(id);
  112. }
  113. /**
  114. * Retrieves a graphics object by name.
  115. *
  116. * @param id String Unique id of the object
  117. * @return reference to the requested game object, or null if not found
  118. */
  119. public GameObject getObject(String id) {
  120. return gameObjects.get(id);
  121. }
  122. /**
  123. * Sets a level-wide permanent flag.
  124. *
  125. * @param flag String Q unique name in this level. If it exists value is overwritten.
  126. * @param value Object Any Object can be the value of a flag!
  127. */
  128. public static void setGlobalFlag(String flag, Object value) {
  129. flags.put("/global/" + flag, value);
  130. }
  131. public Object setLevelFlag(String flag, Object value) {
  132. flags.put("/" + this.level + "/" + flag, value);
  133. return value;
  134. }
  135. /**
  136. * mode can be: FLAGS_ALL (all), FLAGS_GLOBAL(global), FLAGs_LEVEL(level)
  137. *
  138. * @param mode can be only one of {@link #FLAGS_GLOBAL} {@link #FLAGS_ALL} or {@link #FLAGS_LEVEL }
  139. */
  140. public void resetFlags(int mode) {
  141. LinkedList<String> delKeys = new LinkedList<String>();
  142. for (Map.Entry<String, Object> entry : Playground.flags.entrySet()) {
  143. logger.trace(entry.getKey() + " IndexofGlobal = " + entry.getKey().indexOf("/global/"));
  144. if ((mode == FLAGS_GLOBAL) && (entry.getKey().indexOf("/global/") != -1)) {
  145. logger.debug("GLOBAL: scheduling for removal: " + entry.getKey());
  146. delKeys.add(entry.getKey());
  147. } else if ((mode == FLAGS_LEVEL) && (entry.getKey().indexOf("/global/") == -1)) {
  148. logger.debug("LEVEL: scheduling for removal: " + entry.getKey());
  149. delKeys.add(entry.getKey());
  150. } else if (mode == FLAGS_ALL) {
  151. logger.debug("ALL: scheduling for removal: " + entry.getKey());
  152. delKeys.add(entry.getKey());
  153. }
  154. }
  155. for (String str : delKeys) {
  156. logger.trace("removing key " + str);
  157. flags.remove(str);
  158. }
  159. }
  160. /**
  161. * Retrieves a level-wide flag by name.
  162. *
  163. * @param flag String Unique flag id
  164. * @return the value associated with <b>flag</b>, or <b>null</b> if the flag does not exist.
  165. */
  166. public static Object getGlobalFlag(String flag) {
  167. return flags.get("/global/" + flag);
  168. }
  169. /**
  170. * checks for existence and if not creates the new global flag with the given initial value. Returns
  171. * the value. afterwards it is guaranteed that no priorly existing value is overridden and that it
  172. * definitely exists (created if not present before).
  173. *
  174. * @param flag String name for the global flag (created if not present)
  175. * @param value Object value to be stored (used only if flag was not present)
  176. * @return the current value of the flag (maybe the initial one in case flag was not there before)
  177. */
  178. public static Object getOrCreateGlobalFlag(String flag, Object value) {
  179. Object tmp = getGlobalFlag(flag);
  180. if (tmp == null) {
  181. setGlobalFlag(flag, value);
  182. return value;
  183. } else {
  184. return tmp;
  185. }
  186. }
  187. public Object getLevelFlag(String flag) {
  188. return flags.get("/" + this.level + "/" + flag);
  189. }
  190. public Object getOrCreateLevelFlag(String flag, Object createValue) {
  191. Object tmp = getLevelFlag(flag);
  192. if (tmp == null) {
  193. return setLevelFlag(flag, createValue);
  194. } else {
  195. return tmp;
  196. }
  197. }
  198. /**
  199. * Reinitializes the level.
  200. */
  201. public void reset() {
  202. gameObjects.clear();
  203. }
  204. public boolean isPaused() {
  205. return this.pausedFlag;
  206. }
  207. public void setPaused(boolean p) {
  208. this.pausedFlag = p;
  209. }
  210. public void togglePause() {
  211. pausedFlag = !pausedFlag;
  212. }
  213. /**
  214. * Method meant to be filled with own code, processes Keyboard inputs.
  215. *
  216. * @param keyEvents all collected {@link KeyEvent}s collected since last game loop.
  217. */
  218. public void processKeyEvents(Stack<KeyEvent> keyEvents) {
  219. this.keyEvents = keyEvents;
  220. Playground.setGlobalFlag("inputs", keyEvents);
  221. }
  222. public void processMouseEvents(Stack<MouseEvent> mouseEvents) {
  223. this.mouseEvents = mouseEvents;
  224. Playground.setGlobalFlag("inputs", mouseEvents);
  225. }
  226. public Stack<KeyEvent> getKeyEvents() {
  227. return this.keyEvents;
  228. }
  229. public Stack<MouseEvent> getMouseEvents() {
  230. return this.mouseEvents;
  231. }
  232. /**
  233. * Method meant to be filled with own code, handles the entore game logic (collision checks, timed
  234. * events, ...).
  235. *
  236. */
  237. public abstract void applyGameLogic();
  238. /**
  239. * Sets up a single level. Prepares all objects etc.
  240. *
  241. * @param level String a string identifying the level number etc
  242. */
  243. public abstract void prepareLevel(String level);
  244. public abstract boolean gameOver();
  245. public abstract boolean levelFinished();
  246. public int getSizeX() {
  247. return canvasX;
  248. }
  249. public int getSizeY() {
  250. return canvasY;
  251. }
  252. /**
  253. * Calls all object update methods in level. Internal, never call directly.
  254. *
  255. */
  256. public void updateObjects() {
  257. for (GameObject gameObject : gameObjects.values()) { // Iterator usage
  258. if (gameObject.isActive() == true) {
  259. gameObject.updateObject();
  260. logger.trace("updated object " + gameObject.scol);
  261. }
  262. }
  263. for (GameObject o : addables) { // Iterator usage
  264. addObjectNow(o);
  265. }
  266. for (String s : removables) { // Iterator usage
  267. deleteObjectNow(s);
  268. }
  269. removables.clear();
  270. addables.clear();
  271. }
  272. public void setTimestep(double s) {
  273. timeStep = s;
  274. }
  275. public double getTimestep() {
  276. return timeStep;
  277. }
  278. /**
  279. * set the game time value (in seconds)
  280. *
  281. * @param s seconds the game is running
  282. */
  283. public void setGameTime(double s) {
  284. this.gameTime = s;
  285. }
  286. /** returns time in seconds since level start */
  287. public double getGameTime() {
  288. return this.gameTime;
  289. }
  290. /**
  291. * To be redefined!! Draws mainly h level background and global information like points etc.
  292. *
  293. * @param g2 Graphics2D abstract drawing object of java Swing, used to carry out all drawing
  294. * operations.
  295. */
  296. public abstract void redrawLevel(Graphics2D g2);
  297. /**
  298. * Internal, do not call directly.
  299. *
  300. * @param g2 Graphics2D abstract drawing object of java Swing, used to carry out all drawing
  301. * operations.
  302. */
  303. public void redraw(Graphics2D g2) {
  304. redrawLevel(g2);
  305. for (GameObject gameObject : gameObjects.values()) {
  306. if (gameObject.isActive()) {
  307. gameObject.draw(g2);
  308. }
  309. }
  310. }
  311. }