Methapolis  0.27
 All Classes Namespaces Files Functions Variables Enumerator
Sprite.java
Go to the documentation of this file.
1 // This file is part of MicropolisJ.
2 // Copyright (C) 2013 Jason Long
3 // Portions Copyright (C) 1989-2007 Electronic Arts Inc.
4 //
5 // MicropolisJ is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU GPLv3, with additional terms.
7 // See the README file, included in this distribution, for details.
8 
9 package micropolisj.engine;
10 
11 import java.io.Serializable;
12 
13 import static micropolisj.engine.TileConstants.RIVER;
14 import static micropolisj.engine.TileConstants.RZB;
15 import static micropolisj.engine.TileConstants.TINYEXP;
16 import static micropolisj.engine.TileConstants.TREEBASE;
17 import static micropolisj.engine.TileConstants.checkWet;
18 import static micropolisj.engine.TileConstants.isBridge;
19 import static micropolisj.engine.TileConstants.isCombustible;
20 import static micropolisj.engine.TileConstants.isZoneCenter;
21 
29 public abstract class Sprite implements Serializable {
30  transient Micropolis city;
31 
32  // TODO- enforce read-only nature of the following properties
33  // (i.e. do not let them be modified directly by other classes)
34 
35  public SpriteKind kind;
36 
37  public int offx;
38  public int offy;
39  public int width = 32;
40  public int height = 32;
41 
42  public int frame;
43  public int x;
44  public int y;
45 
46  public int lastX;
47  public int lastY;
48 
49  int dir;
50 
51  protected Sprite(Micropolis engine, SpriteKind kind) {
52  this.city = engine;
53  this.kind = kind;
54  }
55 
56  public void setMicropolis(Micropolis micro) {
57  city = micro;
58  }
59 
60  protected final int getChar(int x, int y) {
61  int xpos = x / 16;
62  int ypos = y / 16;
63  if(city.testBounds(xpos, ypos)) {
64  return city.getTile(xpos, ypos);
65  }
66  else {
67  return -1;
68  }
69  }
70 
71  protected int tilePosToPixel(int x) {
72  return x * 16 + 8;
73  }
74 
75  protected int pixelToTilePos(int x) {
76  return (x - 8) / 16;
77  }
78 
84  protected abstract void moveImpl();
85 
89  public final void move() {
90  lastX = x;
91  lastY = y;
92  moveImpl();
93  city.fireSpriteMoved(this);
94  }
95 
99  public final boolean isVisible() {
100  return this.frame != 0;
101  }
102 
109  static int getDir(int orgX, int orgY, int desX, int desY) {
110  final int Gdtab[] = {
111  0, 3, 2, 1, 3, 4, 5, 7, 6, 5, 7, 8, 1
112  };
113  int dispX = desX - orgX;
114  int dispY = desY - orgY;
115 
116  int z = dispX < 0 ? (dispY < 0 ? 11 : 8) : (dispY < 0 ? 2 : 5);
117 
118  dispX = Math.abs(dispX);
119  dispY = Math.abs(dispY);
120 // int absDist = dispX + dispY;
121 
122  if(dispX * 2 < dispY)
123  z++;
124  else if(dispY * 2 < dispX)
125  z--;
126 
127  if(z >= 1 && z <= 12) {
128  return Gdtab[z];
129  }
130  else {
131  assert false;
132  return 0;
133  }
134  }
135 
139  static final int getDis(int x0, int y0, int x1, int y1) {
140  return Math.abs(x0 - x1) + Math.abs(y0 - y1);
141  }
142 
146  protected void explodeSprite() {
147  this.frame = 0;
148 //
149 // if(kind == SpriteKind.ROC) {
150 // city.makeGiantExplosionAt(x, y, city.getPlayerInfo(ownerID).researchState.getRocketRadius());
151 // }
152 // else {
153  city.makeExplosionAt(x, y);
154 // }
155 
156  int xpos = x / 16;
157  int ypos = y / 16;
158 
159  switch(kind) {
160  case AIR:
161  city.crashLocation = new CityLocation(xpos, ypos);
162  city.sendMessageAt(MicropolisMessage.PLANECRASH_REPORT, xpos, ypos);
163  break;
164  case SHI:
165  city.crashLocation = new CityLocation(xpos, ypos);
166  city.sendMessageAt(MicropolisMessage.SHIPWRECK_REPORT, xpos, ypos);
167  break;
168  case TRA:
169  case BUS:
170  city.crashLocation = new CityLocation(xpos, ypos);
171  city.sendMessageAt(MicropolisMessage.TRAIN_CRASH_REPORT, xpos, ypos);
172  break;
173  case COP:
174  city.crashLocation = new CityLocation(xpos, ypos);
175  city.sendMessageAt(MicropolisMessage.COPTER_CRASH_REPORT, xpos, ypos);
176  break;
177  // TODO: message
178 // case ROC:
179 // city.crashLocation = new CityLocation(xpos, ypos);
180 // city.sendMessageAt(MicropolisMessage.ROCKETCRASH_REPORT, xpos, ypos);
181 // break;
182  default:
183  break;
184  }
185 
186  city.makeSound(xpos, ypos, Sound.EXPLOSION_HIGH);
187  // TODO CUSTOM
188  remove();
189  }
190 
191  public void remove() {
192  this.city.sprites.remove(this);
193  }
194 
200  final boolean checkSpriteCollision(Sprite otherSprite) {
201  if(!isVisible())
202  return false;
203  if(!otherSprite.isVisible())
204  return false;
205 
206  return (getDis(this.x, this.y, otherSprite.x, otherSprite.y) < 30);
207  }
208 
213  final void destroyTile(int xpos, int ypos) {
214  if(!city.testBounds(xpos, ypos))
215  return;
216 
217  int t = city.getTile(xpos, ypos);
218 
219  if(t >= TREEBASE) {
220  if(isBridge(t)) {
221  city.setTile(xpos, ypos, RIVER);
222  return;
223  }
224  if(!isCombustible(t)) {
225  return; // cannot destroy it
226  }
227  if(isZoneCenter(t)) {
228  city.killZone(xpos, ypos, t);
229  if(t > RZB) {
230  city.makeExplosion(xpos, ypos);
231  }
232  }
233  if(checkWet(t)) {
234  city.setTile(xpos, ypos, RIVER);
235  }
236  else {
237  city.setTile(xpos, ypos, TINYEXP);
238  }
239  }
240  }
241 
251  static final int turnTo(int p, int d) {
252  if(p == d)
253  return p;
254  if(p < d) {
255  if(d - p < 4)
256  p++;
257  else
258  p--;
259  }
260  else {
261  if(p - d < 4)
262  p--;
263  else
264  p++;
265  }
266  if(p > 8)
267  return 1;
268  if(p < 1)
269  return 8;
270  return p;
271  }
272 
273 }