toolstroke: add sound support for tooleffect class
git-svn-id: https://micropolis.googlecode.com/svn/trunk/micropolis-java@642 d9718cc8-9f43-0410-858b-315f434eb58c
This commit is contained in:
parent
4d3649884d
commit
1b19af8057
6 changed files with 164 additions and 212 deletions
|
@ -13,118 +13,125 @@ class Bulldozer extends ToolStroke
|
|||
@Override
|
||||
public ToolResult apply()
|
||||
{
|
||||
ToolResult checkResult = check();
|
||||
if (checkResult != ToolResult.SUCCESS) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
Rectangle b = getBounds();
|
||||
if (b.width == 1 && b.height == 1 &&
|
||||
isZoneCenter(city.getTile(b.x, b.y)))
|
||||
{
|
||||
return dozeZone(b.x, b.y);
|
||||
}
|
||||
ToolEffect eff = new ToolEffect(city, b.x, b.y);
|
||||
|
||||
int countDozed = 0;
|
||||
for (int y = b.y; y < b.y+b.height; y++) {
|
||||
for (int x = b.x; x < b.x+b.width; x++) {
|
||||
// scan selection area for rubble, forest, etc...
|
||||
for (int y = 0; y < b.height; y++) {
|
||||
for (int x = 0; x < b.width; x++) {
|
||||
|
||||
char tile = city.getTile(x, y);
|
||||
if (isDozeable(tile)) {
|
||||
countDozed++;
|
||||
int tile = eff.getTile(x, y);
|
||||
if (isDozeable(tile) && !isZoneCenter(tile)) {
|
||||
|
||||
dozeField(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ToolResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolResult check()
|
||||
{
|
||||
Rectangle b = getBounds();
|
||||
if (b.width == 1 && b.height == 1 &&
|
||||
isZoneCenter(city.getTile(b.x, b.y)))
|
||||
{
|
||||
int cost = 1;
|
||||
return city.budget.totalFunds >= cost ?
|
||||
ToolResult.SUCCESS :
|
||||
ToolResult.INSUFFICIENT_FUNDS;
|
||||
}
|
||||
|
||||
int countDozed = 0;
|
||||
for (int y = b.y; y < b.y+b.height; y++) {
|
||||
for (int x = b.x; x < b.x+b.width; x++) {
|
||||
|
||||
char tile = city.getTile(x, y);
|
||||
if (isDozeable(tile)) {
|
||||
countDozed++;
|
||||
dozeField(new TranslatedToolEffect(eff, x, y));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int cost = 1 * countDozed;
|
||||
return city.budget.totalFunds < cost ? ToolResult.INSUFFICIENT_FUNDS :
|
||||
countDozed != 0 ? ToolResult.SUCCESS :
|
||||
ToolResult.NONE;
|
||||
// scan selection area for zones...
|
||||
for (int y = 0; y < b.height; y++) {
|
||||
for (int x = 0; x < b.width; x++) {
|
||||
|
||||
if (isZoneCenter(eff.getTile(x,y))) {
|
||||
dozeZone(new TranslatedToolEffect(eff, x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eff.apply();
|
||||
}
|
||||
|
||||
ToolResult dozeZone(int xpos, int ypos)
|
||||
void dozeZone(ToolEffectIfc eff)
|
||||
{
|
||||
assert city.testBounds(xpos, ypos);
|
||||
|
||||
char currTile = city.getTile(xpos, ypos);
|
||||
char tmp = (char)(currTile & LOMASK);
|
||||
int currTile = eff.getTile(0, 0);
|
||||
|
||||
// zone center bit is set
|
||||
assert isZoneCenter(currTile);
|
||||
|
||||
city.spend(1);
|
||||
switch (checkSize(tmp))
|
||||
eff.spend(1);
|
||||
switch (checkSize(currTile))
|
||||
{
|
||||
case 3:
|
||||
city.makeSound(xpos, ypos, Sound.EXPLOSION_HIGH);
|
||||
putRubble(xpos, ypos, 3, 3);
|
||||
eff.makeSound(0, 0, Sound.EXPLOSION_HIGH);
|
||||
putRubble(new TranslatedToolEffect(eff, -1, -1), 3, 3);
|
||||
break;
|
||||
case 4:
|
||||
city.makeSound(xpos, ypos, Sound.EXPLOSION_LOW);
|
||||
putRubble(xpos, ypos, 4, 4);
|
||||
eff.makeSound(0, 0, Sound.EXPLOSION_LOW);
|
||||
putRubble(new TranslatedToolEffect(eff, -1, -1), 4, 4);
|
||||
break;
|
||||
case 6:
|
||||
city.makeSound(xpos, ypos, Sound.EXPLOSION_BOTH);
|
||||
putRubble(xpos, ypos, 6, 6);
|
||||
eff.makeSound(0, 0, Sound.EXPLOSION_BOTH);
|
||||
putRubble(new TranslatedToolEffect(eff, -1, -1), 6, 6);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
break;
|
||||
}
|
||||
return ToolResult.SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
ToolResult dozeField(int xpos, int ypos)
|
||||
void dozeField(ToolEffectIfc eff)
|
||||
{
|
||||
char tile = city.getTile(xpos, ypos);
|
||||
int tile = eff.getTile(0, 0);
|
||||
|
||||
// check dozeable bit
|
||||
assert isDozeable(tile);
|
||||
|
||||
tile = neutralizeRoad(tile);
|
||||
if (isOverWater(tile))
|
||||
if (isOverWater((char)tile))
|
||||
{
|
||||
// dozing over water, replace with water.
|
||||
city.setTile(xpos, ypos, RIVER);
|
||||
eff.setTile(0, 0, RIVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
// dozing on land, replace with land. Simple, eh?
|
||||
city.setTile(xpos, ypos, DIRT);
|
||||
eff.setTile(0, 0, DIRT);
|
||||
}
|
||||
|
||||
city.spend(1);
|
||||
return ToolResult.SUCCESS;
|
||||
eff.spend(1);
|
||||
return;
|
||||
}
|
||||
|
||||
void putRubble(ToolEffectIfc eff, int w, int h)
|
||||
{
|
||||
for (int yy = 0; yy < h; yy++) {
|
||||
for (int xx = 0; xx < w; xx++) {
|
||||
int tile = eff.getTile(xx,yy);
|
||||
if (tile == CLEAR)
|
||||
continue;
|
||||
tile = tile & LOMASK;
|
||||
if (tile != RADTILE && tile != DIRT) {
|
||||
int nTile = (TINYEXP + city.PRNG.nextInt(3))
|
||||
| ANIMBIT | BULLBIT;
|
||||
eff.setTile(xx, yy, nTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int checkSize(int tile)
|
||||
{
|
||||
tile = tile & LOMASK;
|
||||
if ((tile >= (RESBASE-1) && tile <= (PORTBASE-1)) ||
|
||||
(tile >= (LASTPOWERPLANT+1) && tile <= (POLICESTATION+4)))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if ((tile >= PORTBASE && tile <= LASTPORT) ||
|
||||
(tile >= COALBASE && tile <= LASTPOWERPLANT) ||
|
||||
(tile >= STADIUMBASE && tile <= LASTZONE))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (tile == TileConstants.AIRPORT)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,12 @@ class ToolEffect implements ToolEffectIfc
|
|||
}
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void makeSound(int dx, int dy, Sound sound)
|
||||
{
|
||||
preview.makeSound(dx, dy, sound);
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void setTile(int dx, int dy, int tileValue)
|
||||
{
|
||||
|
@ -45,6 +51,12 @@ class ToolEffect implements ToolEffectIfc
|
|||
preview.spend(amount);
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void toolResult(ToolResult tr)
|
||||
{
|
||||
preview.toolResult(tr);
|
||||
}
|
||||
|
||||
ToolResult apply()
|
||||
{
|
||||
if (originX - preview.offsetX < 0 ||
|
||||
|
|
|
@ -7,6 +7,8 @@ public interface ToolEffectIfc
|
|||
*/
|
||||
int getTile(int dx, int dy);
|
||||
|
||||
void makeSound(int dx, int dy, Sound sound);
|
||||
|
||||
/**
|
||||
* Sets the tile value at a relative location.
|
||||
*/
|
||||
|
@ -16,4 +18,6 @@ public interface ToolEffectIfc
|
|||
* Deduct an amount from the controller's cash funds.
|
||||
*/
|
||||
void spend(int amount);
|
||||
|
||||
void toolResult(ToolResult tr);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package micropolisj.engine;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
import static micropolisj.engine.TileConstants.*;
|
||||
|
||||
public class ToolPreview implements ToolEffectIfc
|
||||
|
@ -9,11 +9,28 @@ public class ToolPreview implements ToolEffectIfc
|
|||
public int offsetY;
|
||||
public short [][] tiles;
|
||||
public int cost;
|
||||
public ToolResult toolResult;
|
||||
public List<SoundInfo> sounds;
|
||||
|
||||
public static class SoundInfo
|
||||
{
|
||||
public int dx;
|
||||
public int dy;
|
||||
public Sound sound;
|
||||
|
||||
SoundInfo(int dx, int dy, Sound sound)
|
||||
{
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
this.sound = sound;
|
||||
}
|
||||
}
|
||||
|
||||
ToolPreview()
|
||||
{
|
||||
this.tiles = new short[1][1];
|
||||
this.tiles[0][0] = CLEAR;
|
||||
this.sounds = new ArrayList<SoundInfo>();
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
|
@ -84,6 +101,12 @@ public class ToolPreview implements ToolEffectIfc
|
|||
}
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void makeSound(int dx, int dy, Sound sound)
|
||||
{
|
||||
sounds.add(new SoundInfo(dx, dy, sound));
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void setTile(int dx, int dy, int tileValue)
|
||||
{
|
||||
|
@ -96,4 +119,10 @@ public class ToolPreview implements ToolEffectIfc
|
|||
{
|
||||
cost += amount;
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void toolResult(ToolResult tr)
|
||||
{
|
||||
this.toolResult = tr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,73 +32,36 @@ public class ToolStroke
|
|||
|
||||
public ToolResult apply()
|
||||
{
|
||||
ToolResult checkResult = check();
|
||||
if (checkResult != ToolResult.SUCCESS) {
|
||||
return checkResult;
|
||||
}
|
||||
ToolResult tr = ToolResult.NONE;
|
||||
|
||||
Rectangle r = getBounds();
|
||||
for (int i = r.y; i < r.y + r.height; i += tool.getHeight()) {
|
||||
for (int j = r.x; j < r.x + r.width;
|
||||
j += tool.getWidth()) {
|
||||
apply1(j + (tool.getWidth() >= 3 ? 1 : 0),
|
||||
i + (tool.getHeight() >= 3 ? 1 : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
// TODO- actually check the result of application
|
||||
return ToolResult.SUCCESS;
|
||||
}
|
||||
ToolEffect eff = new ToolEffect(city, r.x, r.y);
|
||||
|
||||
ToolResult checkZoneTool()
|
||||
{
|
||||
Rectangle b = getBounds();
|
||||
int cost = 0;
|
||||
int numPlaced = 0;
|
||||
|
||||
for (int i = b.y; i < b.y + b.height; i += tool.getHeight()) {
|
||||
for (int j = b.x; j < b.x + b.width; j += tool.getWidth()) {
|
||||
int x = j + (tool.getWidth() >= 3 ? 1 : 0);
|
||||
int y = i + (tool.getHeight() >= 3 ? 1 : 0);
|
||||
int c = costToPlaceZone(x, y);
|
||||
|
||||
if (c != Integer.MAX_VALUE) {
|
||||
numPlaced++;
|
||||
cost += c;
|
||||
for (int i = 0; i < r.height; i += tool.getHeight()) {
|
||||
for (int j = 0; j < r.width; j += tool.getWidth()) {
|
||||
ToolResult tmp = apply1(
|
||||
new TranslatedToolEffect(eff, j, i)
|
||||
);
|
||||
if (tmp == ToolResult.SUCCESS) {
|
||||
tr = tmp;
|
||||
}
|
||||
else if (tr == ToolResult.NONE) {
|
||||
tr = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numPlaced == 0 ? ToolResult.NONE :
|
||||
cost <= city.budget.totalFunds ? ToolResult.SUCCESS :
|
||||
ToolResult.INSUFFICIENT_FUNDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SUCCESS if the operation will succeed, and at least
|
||||
* one tile will be changed;
|
||||
* INSUFFICIENT_FUNDS in case there's not enough money,
|
||||
* and NONE is it is a null op.
|
||||
*/
|
||||
ToolResult check()
|
||||
{
|
||||
switch (tool)
|
||||
{
|
||||
// case RAIL:
|
||||
// case ROADS:
|
||||
// case WIRE:
|
||||
// return checkRailRoadWireTool();
|
||||
// case PARK:
|
||||
// return checkParkTool();
|
||||
default:
|
||||
return checkZoneTool();
|
||||
ToolResult tmp = eff.apply();
|
||||
if (tmp != ToolResult.NONE) {
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
return tr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ToolResult apply1(int xpos, int ypos)
|
||||
ToolResult apply1(ToolEffectIfc eff)
|
||||
{
|
||||
ToolEffect eff = new ToolEffect(city, xpos, ypos);
|
||||
ToolResult tr = ToolResult.SUCCESS;
|
||||
|
||||
switch (tool)
|
||||
|
@ -108,43 +71,43 @@ public class ToolStroke
|
|||
break;
|
||||
|
||||
case RESIDENTIAL:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, RESBASE);
|
||||
tr = applyZone(eff, 3, 3, RESBASE);
|
||||
break;
|
||||
|
||||
case COMMERCIAL:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, COMBASE);
|
||||
tr = applyZone(eff, 3, 3, COMBASE);
|
||||
break;
|
||||
|
||||
case INDUSTRIAL:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, INDBASE);
|
||||
tr = applyZone(eff, 3, 3, INDBASE);
|
||||
break;
|
||||
|
||||
case FIRE:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, FIRESTBASE);
|
||||
tr = applyZone(eff, 3, 3, FIRESTBASE);
|
||||
break;
|
||||
|
||||
case POLICE:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, POLICESTBASE);
|
||||
tr = applyZone(eff, 3, 3, POLICESTBASE);
|
||||
break;
|
||||
|
||||
case POWERPLANT:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, COALBASE);
|
||||
tr = applyZone(eff, 4, 4, COALBASE);
|
||||
break;
|
||||
|
||||
case STADIUM:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, STADIUMBASE);
|
||||
tr = applyZone(eff, 4, 4, STADIUMBASE);
|
||||
break;
|
||||
|
||||
case SEAPORT:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, PORTBASE);
|
||||
tr = applyZone(eff, 4, 4, PORTBASE);
|
||||
break;
|
||||
|
||||
case NUCLEAR:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, NUCLEARBASE);
|
||||
tr = applyZone(eff, 4, 4, NUCLEARBASE);
|
||||
break;
|
||||
|
||||
case AIRPORT:
|
||||
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 6, 6, AIRPORTBASE);
|
||||
tr = applyZone(eff, 6, 6, AIRPORTBASE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -152,11 +115,7 @@ public class ToolStroke
|
|||
throw new Error("unexpected tool: "+tool);
|
||||
}
|
||||
|
||||
if (tr != ToolResult.SUCCESS) {
|
||||
return tr;
|
||||
}
|
||||
|
||||
return eff.apply();
|
||||
return tr;
|
||||
}
|
||||
|
||||
public void dragTo(int xdest, int ydest)
|
||||
|
@ -196,38 +155,6 @@ public class ToolStroke
|
|||
return r;
|
||||
}
|
||||
|
||||
int costToPlaceZone(int xpos, int ypos)
|
||||
{
|
||||
final int width = tool.getWidth();
|
||||
final int height = tool.getHeight();
|
||||
|
||||
int cost = tool.getToolCost();
|
||||
boolean canBuild = true;
|
||||
for (int rowNum = 0; rowNum < height; rowNum++) {
|
||||
for (int colNum = 0; colNum < width; colNum++) {
|
||||
int x = xpos - 1 + colNum;
|
||||
int y = ypos - 1 + rowNum;
|
||||
|
||||
char tileValue = (char) (city.getTile(x,y) & LOMASK);
|
||||
if (tileValue != DIRT)
|
||||
{
|
||||
if (city.autoBulldoze)
|
||||
{
|
||||
if (canAutoBulldozeZ(tileValue))
|
||||
cost++;
|
||||
else
|
||||
canBuild = false;
|
||||
}
|
||||
else
|
||||
canBuild = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return canBuild ? cost :
|
||||
Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
ToolResult applyZone(ToolEffectIfc eff, int width, int height, char tileBase)
|
||||
{
|
||||
int cost = tool.getToolCost();
|
||||
|
@ -556,22 +483,6 @@ public class ToolStroke
|
|||
return;
|
||||
}
|
||||
|
||||
void putRubble(int xpos, int ypos, int w, int h)
|
||||
{
|
||||
for (int xx = xpos - 1; xx <= xpos + w-2; xx++) {
|
||||
for (int yy = ypos - 1; yy <= ypos + h-2; yy++) {
|
||||
if (city.testBounds(xx, yy)) {
|
||||
int tile = city.getTile(xx,yy) & LOMASK;
|
||||
if (tile != RADTILE && tile != DIRT) {
|
||||
int nTile = (TINYEXP + city.PRNG.nextInt(3))
|
||||
| ANIMBIT | BULLBIT;
|
||||
city.setTile(xx, yy, (char)nTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isBigZone(int tile)
|
||||
{
|
||||
if (tile >= RESBASE && tile <= LASTZONE)
|
||||
|
@ -583,27 +494,4 @@ public class ToolStroke
|
|||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int checkSize(int tile)
|
||||
{
|
||||
if ((tile >= (RESBASE-1) && tile <= (PORTBASE-1)) ||
|
||||
(tile >= (LASTPOWERPLANT+1) && tile <= (POLICESTATION+4)))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if ((tile >= PORTBASE && tile <= LASTPORT) ||
|
||||
(tile >= COALBASE && tile <= LASTPOWERPLANT) ||
|
||||
(tile >= STADIUMBASE && tile <= LASTZONE))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (tile == TileConstants.AIRPORT)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,12 @@ class TranslatedToolEffect implements ToolEffectIfc
|
|||
return base.getTile(x+dx, y+dy);
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void makeSound(int x, int y, Sound sound)
|
||||
{
|
||||
base.makeSound(x+dx, y+dy, sound);
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void setTile(int x, int y, int tileValue)
|
||||
{
|
||||
|
@ -30,4 +36,10 @@ class TranslatedToolEffect implements ToolEffectIfc
|
|||
{
|
||||
base.spend(amount);
|
||||
}
|
||||
|
||||
//implements ToolEffectIfc
|
||||
public void toolResult(ToolResult tr)
|
||||
{
|
||||
base.toolResult(tr);
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue