This repository has been archived on 2025-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
citylimitsj/src/micropolisj/engine/Sprite.java
jason@long.name b18b51d08e refactor: remove isPic argument from cityMessage() notification
Have the decision of whether to show the message in the notification
pane be determined by the message type itself, rather than being
decided by the sender of the message.

git-svn-id: https://micropolis.googlecode.com/svn/trunk/micropolis-java@859 d9718cc8-9f43-0410-858b-315f434eb58c
2013-09-22 00:48:34 +00:00

224 lines
4.7 KiB
Java

// This file is part of MicropolisJ.
// Copyright (C) 2013 Jason Long
// Portions Copyright (C) 1989-2007 Electronic Arts Inc.
//
// MicropolisJ is free software; you can redistribute it and/or modify
// it under the terms of the GNU GPLv3, with additional terms.
// See the README file, included in this distribution, for details.
package micropolisj.engine;
import static micropolisj.engine.TileConstants.*;
public abstract class Sprite
{
Micropolis city;
//TODO- enforce read-only nature of the following properties
// (i.e. do not let them be modified directly by other classes)
public SpriteKind kind;
public int offx;
public int offy;
public int width = 32;
public int height = 32;
public int frame;
public int x;
public int y;
public int lastX;
public int lastY;
int dir;
protected Sprite(Micropolis engine, SpriteKind kind)
{
this.city = engine;
this.kind = kind;
}
protected final int getChar(int x, int y)
{
int xpos = x / 16;
int ypos = y / 16;
if (city.testBounds(xpos, ypos)) {
return (city.getTile(xpos, ypos) & LOMASK);
} else {
return -1;
}
}
/**
* For subclasses to override. Actually does the movement and animation
* of this particular sprite. Setting this.frame to zero will cause the
* sprite to be unallocated.
*/
protected abstract void moveImpl();
/**
* Perform this agent's movement and animation.
*/
public final void move()
{
lastX = x;
lastY = y;
moveImpl();
city.fireSpriteMoved(this);
}
/**
* Tells whether this sprite is visible.
*/
public final boolean isVisible()
{
return this.frame != 0;
}
/**
* Computes direction from one point to another.
* @return integer between 1 and 8, with
* 1 == north,
* 3 == east,
* 5 == south,
* 7 == west.
*/
static final int getDir(int orgX, int orgY, int desX, int desY)
{
final int Gdtab [] = { 0, 3, 2, 1, 3, 4, 5, 7, 6, 5, 7, 8, 1 };
int dispX = desX - orgX;
int dispY = desY - orgY;
int z = dispX < 0 ? (dispY < 0 ? 11 : 8) : (dispY < 0 ? 2 : 5);
dispX = Math.abs(dispX);
dispY = Math.abs(dispY);
int absDist = dispX + dispY;
if (dispX * 2 < dispY) z++;
else if (dispY * 2 < dispX) z--;
if (z >= 1 && z <= 12) {
return Gdtab[z];
}
else {
assert false;
return 0;
}
}
/**
* Computes manhatten distance between two points.
*/
static final int getDis(int x0, int y0, int x1, int y1)
{
return Math.abs(x0-x1) + Math.abs(y0-y1);
}
/**
* Replaces this sprite with an exploding sprite.
*/
final void explodeSprite()
{
this.frame = 0;
city.makeExplosionAt(x, y);
int xpos = x/16;
int ypos = y/16;
switch (kind) {
case AIR:
city.crashLocation = new CityLocation(xpos, ypos);
city.sendMessageAt(MicropolisMessage.PLANECRASH_REPORT, xpos, ypos);
break;
case SHI:
city.crashLocation = new CityLocation(xpos, ypos);
city.sendMessageAt(MicropolisMessage.SHIPWRECK_REPORT, xpos, ypos);
break;
case TRA:
case BUS:
city.crashLocation = new CityLocation(xpos, ypos);
city.sendMessageAt(MicropolisMessage.TRAIN_CRASH_REPORT, xpos, ypos);
break;
case COP:
city.crashLocation = new CityLocation(xpos, ypos);
city.sendMessageAt(MicropolisMessage.COPTER_CRASH_REPORT, xpos, ypos);
break;
}
city.makeSound(xpos, ypos, Sound.EXPLOSION_HIGH);
}
/**
* Checks whether another sprite is in collision ranges.
* @return true iff the sprite is in collision range
*/
final boolean checkSpriteCollision(Sprite otherSprite)
{
if (!isVisible()) return false;
if (!otherSprite.isVisible()) return false;
return (getDis(this.x, this.y, otherSprite.x, otherSprite.y) < 30);
}
/**
* Destroys whatever is at the specified location,
* replacing it with fire, rubble, or water as appropriate.
*/
final void destroyTile(int xpos, int ypos)
{
if (!city.testBounds(xpos, ypos))
return;
int z = city.getTile(xpos, ypos);
int t = z & LOMASK;
if (t >= TREEBASE) {
if (isBridge(z)) {
city.setTile(xpos, ypos, RIVER);
return;
}
if (!isCombustible(z)) {
return; //cannot destroy it
}
if (isZoneCenter(z)) {
city.killZone(xpos, ypos, z);
if (t > RZB) {
city.makeExplosion(xpos, ypos);
}
}
if (checkWet(t)) {
city.setTile(xpos, ypos, RIVER);
}
else {
city.setTile(xpos, ypos,
(char) (TINYEXP | BULLBIT));
}
}
}
/**
* Helper function for rotating a sprite.
* @param p the sprite's current attitude (1-8)
* @param d the desired attitude (1-8)
* @return the new attitude
*/
static final int turnTo(int p, int d)
{
if (p == d)
return p;
if (p < d) {
if (d - p < 4) p++;
else p--;
}
else {
if (p - d < 4) p--;
else p++;
}
if (p > 8) return 1;
if (p < 1) return 8;
return p;
}
}