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.

377 lines
10 KiB

  1. package gameobjects;
  2. import java.awt.Graphics2D;
  3. import java.awt.image.BufferedImage;
  4. import java.util.LinkedList;
  5. import java.lang.reflect.*;
  6. import rendering.*;
  7. import collider.Collider;
  8. import controller.ObjectController;
  9. import playground.Playground;
  10. import org.apache.logging.log4j.Logger;
  11. import org.apache.logging.log4j.LogManager;
  12. /**
  13. * The class {@link GameObject} represents a (possibly animated) object appearing in a level of the
  14. * game. It is therefore attached to an instance of the class {@link Playground}. A GameObject has
  15. * at least the following properties:
  16. * <ul>
  17. * <li>2D screen position
  18. * <li>2D speed
  19. * <li>a name that is unique within a certain {@link Playground}<br>
  20. * <li>a reference to the {@link Playground} object it belongs to<br>
  21. * <li>a reference to an instance of {@link controller.ObjectController} that handles the movement
  22. * logic of the object<br>
  23. * <li>a (circular) radius for simple collision checking. This may be handled differently in
  24. * subclasses<br>
  25. * </ul>
  26. * The main task of GameObject, or its subclasses, is to draw the object on the screen, which is
  27. * handles by the {@link #draw(Graphics2D)} method. It is this method that must be redefined if a
  28. * new appearance should be realized. For introducing new behavior, it is sufficient to supply a
  29. * different {@link controller.ObjectController} instance when constructing a GameObject.
  30. */
  31. public abstract class GameObject {
  32. public static final int RADIUS = 0;
  33. public static final int RECTANGLE = 1;
  34. public static final int MASK = 2;
  35. protected Artist artist = null;
  36. public String id = null;
  37. protected double x = 0;
  38. protected double vx = 0;
  39. protected double y = 0;
  40. protected double vy = 0;
  41. protected BufferedImage mask = null; // UNDONE implement usage of mask
  42. protected boolean active = true;
  43. // public int collisionMode = GameObject.RADIUS;
  44. protected Playground playground = null;
  45. private ObjectController controller = null;
  46. public LinkedList<Collider> scol;
  47. private static Logger logger = LogManager.getLogger(GameObject.class);
  48. /**
  49. * Constructor to initialize a GameObject, respectively set the current {@link Playground}
  50. * instance this GameObject belongs to.
  51. *
  52. * @param id unique ID for this GameObject (should not be null or empty String)
  53. * @param playground the Playground the GameObject belongs to (should not be null)
  54. * @param x initial screen position in direction horizontal (positive value including zero)
  55. * @param y initial screen position in direction vertical (positive value including zero)
  56. * @param vx initial speed (velocity) in direction horizontal (can be negative, zero, positive)
  57. * @param vy initial speed (velocity) in direction horizontal (can be negative, zero, positive)
  58. */
  59. public GameObject(String id, Playground playground, double x, double y, double vx, double vy) {
  60. setX(x);
  61. setY(y);
  62. setVX(vx);
  63. setVY(vy);
  64. this.id = id;
  65. this.controller = null;
  66. this.scol = new LinkedList<Collider>();
  67. this.setPlayground(playground);
  68. }
  69. /**
  70. * Constructor to initialize a GameObject, respectively set the current Playground instance this
  71. * GameObject belongs to.
  72. *
  73. * @param id unique ID for this GameObject (should not be null or empty String)
  74. * @param playground the Playground the GameObject belongs to (should not be null)
  75. * @param controller controller instance to be used for this GameObject (can be null)
  76. * @param x initial screen position in direction horizontal (positive value including zero)
  77. * @param y initial screen position in direction vertical (positive value including zero)
  78. * @param vx initial speed (velocity) in direction horizontal (can be negative, zero, positive)
  79. * @param vy initial speed (velocity) in direction horizontal (can be negative, zero, positive)
  80. */
  81. public GameObject(String id, Playground playground, ObjectController controller, double x,
  82. double y, double vx, double vy) {
  83. this(id, playground, x, y, vx, vy);
  84. this.controller = controller;
  85. if (this.controller != null) {
  86. this.controller.setObject(this);
  87. this.controller.setPlayground(playground);
  88. }
  89. }
  90. /**
  91. * sets colliders.
  92. *
  93. * @param l LinkedList of Colliders.
  94. */
  95. public void setColliders(LinkedList<Collider> l) {
  96. this.scol = l;
  97. }
  98. /**
  99. * generates and sets collider(s) for this GameObject. This implementation does nothing. Intended
  100. * to be overridden by subclasses.
  101. *
  102. * @return instance of this GameObject (this).
  103. */
  104. public GameObject generateColliders() {
  105. return this;
  106. }
  107. /**
  108. * Sets the controller to use for this GameObject's logical behavior.
  109. *
  110. * @param c instance to be used.
  111. * @return the current instance (this).
  112. */
  113. public GameObject addController(ObjectController c) {
  114. this.controller = c;
  115. this.controller.setObject(this);
  116. this.controller.setPlayground(playground);
  117. return this;
  118. }
  119. /**
  120. * Sets the artist to be used for drawing the object onto visible canvas area.
  121. *
  122. * @param a instance to be used for calling {@link rendering.Artist#draw(Graphics2D)}.
  123. * @return the current instance (this).
  124. */
  125. public GameObject addArtist(Artist a) {
  126. this.artist = a;
  127. return this;
  128. }
  129. /**
  130. * saves the collider in the internal list of Colliders to be used for this GameObject.
  131. *
  132. * @param c instance to be added to internal list
  133. */
  134. public void addCollider(Collider c) {
  135. if (this.scol == null) {
  136. this.scol = new LinkedList<Collider>();
  137. }
  138. this.scol.add(c);
  139. }
  140. public Playground getPlayground() {
  141. return playground;
  142. }
  143. public void setPlayground(Playground playground) {
  144. this.playground = playground;
  145. }
  146. /**
  147. * calls via reflection a method of a component if this GameObjects instance and provides the
  148. * given value as String parameter.
  149. *
  150. * @param comp class name of GameObject component. Currently only "controller" is supported,
  151. * otherwise nothing happens.
  152. * @param property method name of the component to call.
  153. * @param value argument to pass to the method as String parameter.
  154. */
  155. public void setComponentProperty(String comp, String property, Object value) {
  156. if (comp.equals("controller")) {
  157. Class<? extends Object> clO = this.controller.getClass();
  158. for (Method m : clO.getMethods()) {
  159. if (m.getName().indexOf(property) != -1) {
  160. logger.debug("Method " + property + " found!!");
  161. try {
  162. m.invoke(this.getObjectController(), value);
  163. } catch (Exception e) {
  164. }
  165. }
  166. }
  167. }
  168. }
  169. public void setObjectFlag(String flag, Object value) {
  170. this.playground.setLevelFlag(this.id + "/" + flag, value);
  171. }
  172. public Object getObjectFlag(String flag) {
  173. return this.playground.getLevelFlag(this.id + "/" + flag);
  174. }
  175. public Object getOrCreateObjectFlag(String flag, Object createValue) {
  176. return this.playground.getOrCreateLevelFlag(this.id + "/" + flag, createValue);
  177. }
  178. public boolean isActive() {
  179. return active;
  180. }
  181. public GameObject setActive(boolean flag) {
  182. this.active = flag;
  183. return this;
  184. }
  185. /**
  186. * return the unique object ID.
  187. *
  188. * @return unique object ID
  189. */
  190. public String getId() {
  191. return id;
  192. }
  193. /**
  194. * gets the screen X position.
  195. *
  196. * @return screen x position
  197. */
  198. public double getX() {
  199. return x;
  200. }
  201. /**
  202. * gets the screen Y position.
  203. *
  204. * @return screen Y position
  205. */
  206. public double getY() {
  207. return y;
  208. }
  209. /**
  210. * gets the screen X speed in pixels per frame.
  211. *
  212. * @return screen x speed
  213. */
  214. public double getVX() {
  215. return vx;
  216. }
  217. /**
  218. * gets the screen Y speed in pixels per frame.
  219. *
  220. * @return screen y speed
  221. */
  222. public double getVY() {
  223. return vy;
  224. }
  225. /**
  226. * set screen x position.
  227. *
  228. * @param x new position
  229. */
  230. public void setX(double x) {
  231. if (this.active == true) {
  232. this.x = x;
  233. }
  234. }
  235. /**
  236. * set screen y position.
  237. *
  238. * @param y new position
  239. */
  240. public void setY(double y) {
  241. if (this.active == true) {
  242. this.y = y;
  243. }
  244. }
  245. /**
  246. * set screen x speed in pixel per frame
  247. *
  248. * @param vx new x speed
  249. */
  250. public void setVX(double vx) {
  251. if (this.active == true) {
  252. this.vx = vx;
  253. }
  254. }
  255. /**
  256. * set screen y speed in pixel per frame.
  257. *
  258. * @param vy new y speed.
  259. */
  260. public void setVY(double vy) {
  261. if (this.active == true) {
  262. this.vy = vy;
  263. }
  264. }
  265. /**
  266. * Sets a new object controller (replaces any former one).
  267. *
  268. * @param controller An instance of {@link controller.ObjectController} or one of its subclasses.
  269. */
  270. public void setObjectController(ObjectController controller) {
  271. this.controller = controller;
  272. }
  273. /**
  274. * Access to object controller.
  275. *
  276. * @return the controller for this object.
  277. */
  278. public ObjectController getObjectController() {
  279. return this.controller;
  280. }
  281. public double getGameTime() {
  282. return this.playground.getGameTime();
  283. }
  284. /**
  285. * Collision detection implemented by iteration through the own list of {@link collider.Collider}
  286. * and calling their {@link collider.Collider#collidesWith(Collider)} method to check collision
  287. * with the given parameter instance of other {@link GameObject}.
  288. *
  289. * @param other instance of the other GameObject to check collision with
  290. * @return true if collision is detected, false otherwise
  291. */
  292. public boolean collisionDetection(GameObject other) {
  293. if (this.scol == null) {
  294. return false;
  295. }
  296. for (Collider c : this.scol) {
  297. logger.trace(other.id);
  298. for (Collider o : other.scol) {
  299. if (c.collidesWith(o)) {
  300. logger.trace(c.id + " " + o.id);
  301. return true;
  302. }
  303. }
  304. }
  305. return false;
  306. }
  307. /**
  308. * triggers this GameObjects own controller (if set) to update the object.
  309. *
  310. * @see GameObject#controller
  311. */
  312. public void updateObject() {
  313. if (this.controller != null) {
  314. controller.updateObject();
  315. }
  316. }
  317. /**
  318. * Draws the object in its current state. Is called by the game engine, should NOT be called
  319. * otherwise.
  320. *
  321. * @param g object that has all the necessary drawing functionalities
  322. */
  323. public void draw(Graphics2D g) {
  324. if (this.artist != null) {
  325. this.artist.draw(g);
  326. }
  327. }
  328. }