Gridarta Editor
DefaultIsoGameObject.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.model.gameobject;
21 
22 import java.awt.Point;
23 import javax.swing.Icon;
24 import javax.swing.ImageIcon;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33 
38 public abstract class DefaultIsoGameObject<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends AbstractGameObject<G, A, R> {
39 
43  private static final long serialVersionUID = 1L;
44 
45  private static final int MAX_STRETCH = 8;
46 
47  private static final int MAX_STRETCH_DIAGONAL = 12;
48 
49  public static final int MAX_SUB_LAYERS = 7;
50 
54  @NotNull
55  public static final String Z = "z";
56 
60  @NotNull
61  public static final String LAYER = "layer";
62 
66  @NotNull
67  public static final String SUB_LAYER = "sub_layer";
68 
72  @NotNull
73  public static final String SYS_OBJECT = "sys_object";
74 
78  @NotNull
79  public static final String DRAW_DOUBLE_ALWAYS = "draw_double_always";
80 
84  @NotNull
85  public static final String DRAW_DOUBLE = "draw_double";
86 
90  @NotNull
91  public static final String ALIGN = "align";
92 
96  @NotNull
97  public static final String ZOOM = "zoom";
98 
102  @NotNull
103  public static final String ALPHA = "alpha";
104 
108  @NotNull
109  public static final String ROTATE = "rotate";
110 
114  @NotNull
115  public static final String GLOW_RADIUS = "glow_radius";
116 
120  @NotNull
121  private final transient FaceObjectProviders faceObjectProviders;
122 
127  @Nullable
128  private ImageIcon transFace;
129 
134  @Nullable
135  private ImageIcon doubleFace;
136 
141  @Nullable
142  private ImageIcon transDoubleFace;
143 
148  @Nullable
149  private ImageIcon stretchedFace;
150 
154  @NotNull
155  private final Point point = new Point();
156 
161  private boolean stretchFactorIsValid;
162 
166  private long stretchFactor;
167 
175  protected DefaultIsoGameObject(@NotNull final R archetype, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects) {
176  super(archetype, faceObjectProviders, animationObjects);
177  this.faceObjectProviders = faceObjectProviders;
178  }
179 
180  @Override
181  public boolean usesDirection() {
182  return getAttributeInt(IS_TURNABLE) != 0 || getAttributeInt(IS_ANIMATED) != 0;
183  }
184 
185  @Override
186  public void setObjectFace() {
187  transFace = null;
188  doubleFace = null;
189  transDoubleFace = null;
190  stretchedFace = null;
191  super.setObjectFace();
192  }
193 
198  @NotNull
199  public Icon getTransparentImage() {
200  if (transFace == null) {
201  transFace = faceObjectProviders.getTrans(this);
202  }
203  return transFace;
204  }
205 
210  @NotNull
211  public Icon getDoubleImage() {
212  if (doubleFace == null) {
213  doubleFace = faceObjectProviders.getDouble(this);
214  }
215  return doubleFace;
216  }
217 
222  @NotNull
224  if (transDoubleFace == null) {
225  transDoubleFace = faceObjectProviders.getTransDouble(this);
226  }
227  return transDoubleFace;
228  }
229 
234  public final int getYOffset() {
235  return getAttributeInt(LAYER) > 1 ? getAttributeInt(Z) : 0;
236  }
237 
245  private int getYFloorOffset(final int dx, final int dy) {
246  final MapSquare<G, A, R> mapSquare = getMapSquare();
247  if (mapSquare == null) {
248  return 0;
249  }
250 
251  point.x = mapSquare.getMapX() + dx;
252  point.y = mapSquare.getMapY() + dy;
253 
254  try {
255  for (final G gameObject : mapSquare.getMapModel().getMapSquare(point)) {
256  if (gameObject.getAttributeInt(LAYER) == 1 && gameObject.getAttributeInt(SUB_LAYER) == getAttributeInt(SUB_LAYER)) {
257  return gameObject.getAttributeInt(Z);
258  }
259  }
260  } catch (final IndexOutOfBoundsException ignored) {
261  // skip points outside map bounds
262  }
263 
264  return 0;
265  }
266 
271  public final void refreshStretchFactor() {
272  stretchFactorIsValid = false;
273  stretchedFace = null;
274  }
275 
282  public final long getStretchFactor() {
283  if (stretchFactorIsValid) {
284  return stretchFactor;
285  }
286 
287  int nwHeight = getYFloorOffset(-1, -1);
288  int nHeight = getYFloorOffset(0, -1);
289  int neHeight = getYFloorOffset(1, -1);
290  int swHeight = getYFloorOffset(-1, 1);
291  int sHeight = getYFloorOffset(0, 1);
292  int seHeight = getYFloorOffset(1, 1);
293  int wHeight = getYFloorOffset(-1, 0);
294  int eHeight = getYFloorOffset(1, 0);
295  final int myHeight = getYFloorOffset(0, 0);
296 
297  if (Math.abs(myHeight - eHeight) > MAX_STRETCH) {
298  eHeight = myHeight;
299  }
300 
301  if (Math.abs(myHeight - seHeight) > MAX_STRETCH_DIAGONAL) {
302  seHeight = myHeight;
303  }
304 
305  if (Math.abs(myHeight - sHeight) > MAX_STRETCH) {
306  sHeight = myHeight;
307  }
308 
309  if (Math.abs(myHeight - swHeight) > MAX_STRETCH_DIAGONAL) {
310  swHeight = myHeight;
311  }
312 
313  if (Math.abs(myHeight - wHeight) > MAX_STRETCH) {
314  wHeight = myHeight;
315  }
316 
317  if (Math.abs(myHeight - nwHeight) > MAX_STRETCH_DIAGONAL) {
318  nwHeight = myHeight;
319  }
320 
321  if (Math.abs(myHeight - nHeight) > MAX_STRETCH) {
322  nHeight = myHeight;
323  }
324 
325  if (Math.abs(myHeight - neHeight) > MAX_STRETCH_DIAGONAL) {
326  neHeight = myHeight;
327  }
328 
329  int top = Math.max(wHeight, nwHeight);
330  top = Math.max(top, nHeight);
331  top = Math.max(top, myHeight);
332 
333  int bottom = Math.max(sHeight, seHeight);
334  bottom = Math.max(bottom, eHeight);
335  bottom = Math.max(bottom, myHeight);
336 
337  int right = Math.max(nHeight, neHeight);
338  right = Math.max(right, eHeight);
339  right = Math.max(right, myHeight);
340 
341  int left = Math.max(wHeight, swHeight);
342  left = Math.max(left, sHeight);
343  left = Math.max(left, myHeight);
344 
345  int minHt = Math.min(top, bottom);
346  minHt = Math.min(minHt, left);
347  minHt = Math.min(minHt, right);
348  minHt = Math.min(minHt, myHeight);
349 
350  if (myHeight < 0 && left == 0 && right == 0 && top == 0 && bottom == 0) {
351  int top2 = Math.min(wHeight, nwHeight);
352  top2 = Math.min(top2, nHeight);
353  top2 = Math.min(top2, myHeight);
354 
355  int bottom2 = Math.min(sHeight, seHeight);
356  bottom2 = Math.min(bottom2, eHeight);
357  bottom2 = Math.min(bottom2, myHeight);
358 
359  int right2 = Math.min(nHeight, neHeight);
360  right2 = Math.min(right2, eHeight);
361  right2 = Math.min(right2, myHeight);
362 
363  int left2 = Math.min(wHeight, swHeight);
364  left2 = Math.min(left2, sHeight);
365  left2 = Math.min(left2, myHeight);
366 
367  top = top2 - top;
368  bottom = bottom2 - bottom;
369  right = right2 - right;
370  left = left2 - left;
371 
372  minHt = Math.min(top, bottom);
373  minHt = Math.min(minHt, left);
374  minHt = Math.min(minHt, right);
375  minHt = Math.min(minHt, myHeight);
376 
377  minHt = Math.abs(minHt);
378  top = Math.abs(top);
379  bottom = Math.abs(bottom);
380  left = Math.abs(left);
381  right = Math.abs(right);
382  }
383 
384  top -= minHt;
385  bottom -= minHt;
386  left -= minHt;
387  right -= minHt;
388 
389  top = Math.abs(Math.min(255, top));
390  bottom = Math.abs(Math.min(255, bottom));
391  left = Math.abs(Math.min(255, left));
392  right = Math.abs(Math.min(255, right));
393 
394  stretchFactor = bottom + (left << 8) + (right << 16) + (top << 24);
395  stretchFactorIsValid = true;
396  return stretchFactor;
397  }
398 
403  @NotNull
404  public Icon getStretchedImage(final long stretchFactor) {
405  if (stretchedFace == null) {
406  stretchedFace = faceObjectProviders.getStretched(this, stretchFactor);
407  }
408  return stretchedFace;
409  }
410 
417  public abstract boolean isDrawDouble(boolean drawDoubleFaces);
418 
425  public abstract boolean isStretched(boolean tileStretching);
426 
427  @NotNull
428  @Override
429  @SuppressWarnings("unchecked")
430  public G clone() {
431  //noinspection OverriddenMethodCallDuringObjectConstruction
433  return clone.getThis();
434  }
435 
436  @Override
437  public boolean isEqual(@NotNull final BaseObject<?, ?, ?, ?> gameObject) {
438  return super.isEqual(gameObject);
439  // ignore "scriptArchData"
440  // ignore "transFace"
441  }
442 
443  @Override
444  public void facesReloaded() {
445  transFace = null;
446  doubleFace = null;
447  transDoubleFace = null;
448  stretchedFace = null;
449  super.facesReloaded();
450  }
451 
452 }
int getMapX()
Returns the x coordinate on the map.
Definition: MapSquare.java:107
abstract boolean isStretched(boolean tileStretching)
Returns whether to draw this game object with stretching transformation.
static final String SYS_OBJECT
The name of the "sys_object" attribute.
Abstract base class of GameObject implementations.
ImageIcon getTransDouble(@NotNull final GameObject<?, ?, ?> gameObject)
Returns the transparent double face for a GameObject as an ImageIcon.
final int getYOffset()
Acquire Y offset of the object for rendering purposes.
final long getStretchFactor()
Acquire stretch factor of the object.
MapModel< G, A, R > getMapModel()
Returns the MapModel this map square is part of.
Definition: MapSquare.java:99
static final String ZOOM
The name of the "zoom" attribute.
static final String LAYER
The name of the "layer" attribute.
Gridarta can handle frame information of animations and allow the selection of an animation using a t...
static final String ALPHA
The name of the "alpha" attribute.
DefaultIsoGameObject(@NotNull final R archetype, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects)
Creates a new instance.
static final String GLOW_RADIUS
The name of the "glow_radius" attribute.
ImageIcon transDoubleFace
The transparent double face.
Base package of all Gridarta classes.
Reflects a game object (object on a map).
Definition: GameObject.java:36
Icon getTransparentDoubleImage()
Returns a transparent variant of the face for this GameObject.
Icon getTransparentImage()
Returns a transparent variant of the face for this GameObject.
abstract boolean isDrawDouble(boolean drawDoubleFaces)
Returns whether to draw this game object with double height.
static final String SUB_LAYER
The name of the "sub_layer" attribute.
MapSquare< G, A, R > getMapSquare(@NotNull Point pos)
Get the square at a specified location.
AnimationObjects is a container for AnimationObjects.
static final String Z
The name of the "z" attribute.
boolean isEqual(@NotNull final BaseObject<?, ?, ?, ?> gameObject)
ImageIcon getTrans(@NotNull final GameObject<?, ?, ?> gameObject)
Returns the transparent face for a GameObject as an ImageIcon.
Icon getStretchedImage(final long stretchFactor)
Returns a stretched variant of the face for this floor-type GameObject.
static final String ROTATE
The name of the "rotate" attribute.
Provider for faces of GameObjects and Archetypes.
final transient FaceObjectProviders faceObjectProviders
The FaceObjectProviders for looking up faces.
int getYFloorOffset(final int dx, final int dy)
Acquire Y offset at the specified coordinates, relative to the game object&#39;s coordinates and its sub-...
The face is the appearance of an object.
boolean stretchFactorIsValid
If true, the stored stretchFactor is valid and can be used in getStretchFactor() instead of calculati...
static final String DRAW_DOUBLE_ALWAYS
The name of the "draw_double_always" attribute.
final Point point
Cached point to avoid unnecessary allocations.
Icon getDoubleImage()
Returns a double variant of the face for this GameObject.
Default implementation for GameObject implementing classes.
ImageIcon getDouble(@NotNull final GameObject<?, ?, ?> gameObject)
Returns the double face for a GameObject as an ImageIcon.
static final String ALIGN
The name of the "align" attribute.
static final String DRAW_DOUBLE
The name of the "draw_double" attribute.
int getMapY()
Returns the y coordinate on the map.
Definition: MapSquare.java:115
ImageIcon getStretched(@NotNull final GameObject<?, ?, ?> gameObject, final long stretch)
Returns the stretched face for a GameObject as an ImageIcon.
final void refreshStretchFactor()
Invalidates stretch factor value calculated by getStretchFactor() and clears the stored stretched fac...
static final long serialVersionUID
The serial version UID.