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:
jason@long.name 2013-05-16 23:44:54 +00:00
parent 4d3649884d
commit 1b19af8057
6 changed files with 164 additions and 212 deletions

View file

@ -13,118 +13,125 @@ class Bulldozer extends ToolStroke
@Override @Override
public ToolResult apply() public ToolResult apply()
{ {
ToolResult checkResult = check();
if (checkResult != ToolResult.SUCCESS) {
return checkResult;
}
Rectangle b = getBounds(); Rectangle b = getBounds();
if (b.width == 1 && b.height == 1 && ToolEffect eff = new ToolEffect(city, b.x, b.y);
isZoneCenter(city.getTile(b.x, b.y)))
{
return dozeZone(b.x, b.y);
}
int countDozed = 0; // scan selection area for rubble, forest, etc...
for (int y = b.y; y < b.y+b.height; y++) { for (int y = 0; y < b.height; y++) {
for (int x = b.x; x < b.x+b.width; x++) { for (int x = 0; x < b.width; x++) {
char tile = city.getTile(x, y); int tile = eff.getTile(x, y);
if (isDozeable(tile)) { if (isDozeable(tile) && !isZoneCenter(tile)) {
countDozed++;
dozeField(x, y); dozeField(new TranslatedToolEffect(eff, 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++;
} }
} }
} }
int cost = 1 * countDozed; // scan selection area for zones...
return city.budget.totalFunds < cost ? ToolResult.INSUFFICIENT_FUNDS : for (int y = 0; y < b.height; y++) {
countDozed != 0 ? ToolResult.SUCCESS : for (int x = 0; x < b.width; x++) {
ToolResult.NONE;
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); int currTile = eff.getTile(0, 0);
char currTile = city.getTile(xpos, ypos);
char tmp = (char)(currTile & LOMASK);
// zone center bit is set // zone center bit is set
assert isZoneCenter(currTile); assert isZoneCenter(currTile);
city.spend(1); eff.spend(1);
switch (checkSize(tmp)) switch (checkSize(currTile))
{ {
case 3: case 3:
city.makeSound(xpos, ypos, Sound.EXPLOSION_HIGH); eff.makeSound(0, 0, Sound.EXPLOSION_HIGH);
putRubble(xpos, ypos, 3, 3); putRubble(new TranslatedToolEffect(eff, -1, -1), 3, 3);
break; break;
case 4: case 4:
city.makeSound(xpos, ypos, Sound.EXPLOSION_LOW); eff.makeSound(0, 0, Sound.EXPLOSION_LOW);
putRubble(xpos, ypos, 4, 4); putRubble(new TranslatedToolEffect(eff, -1, -1), 4, 4);
break; break;
case 6: case 6:
city.makeSound(xpos, ypos, Sound.EXPLOSION_BOTH); eff.makeSound(0, 0, Sound.EXPLOSION_BOTH);
putRubble(xpos, ypos, 6, 6); putRubble(new TranslatedToolEffect(eff, -1, -1), 6, 6);
break; break;
default: default:
assert false; assert false;
break; 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 // check dozeable bit
assert isDozeable(tile); assert isDozeable(tile);
tile = neutralizeRoad(tile); tile = neutralizeRoad(tile);
if (isOverWater(tile)) if (isOverWater((char)tile))
{ {
// dozing over water, replace with water. // dozing over water, replace with water.
city.setTile(xpos, ypos, RIVER); eff.setTile(0, 0, RIVER);
} }
else else
{ {
// dozing on land, replace with land. Simple, eh? // dozing on land, replace with land. Simple, eh?
city.setTile(xpos, ypos, DIRT); eff.setTile(0, 0, DIRT);
} }
city.spend(1); eff.spend(1);
return ToolResult.SUCCESS; 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;
}
}
} }

View file

@ -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 //implements ToolEffectIfc
public void setTile(int dx, int dy, int tileValue) public void setTile(int dx, int dy, int tileValue)
{ {
@ -45,6 +51,12 @@ class ToolEffect implements ToolEffectIfc
preview.spend(amount); preview.spend(amount);
} }
//implements ToolEffectIfc
public void toolResult(ToolResult tr)
{
preview.toolResult(tr);
}
ToolResult apply() ToolResult apply()
{ {
if (originX - preview.offsetX < 0 || if (originX - preview.offsetX < 0 ||

View file

@ -7,6 +7,8 @@ public interface ToolEffectIfc
*/ */
int getTile(int dx, int dy); int getTile(int dx, int dy);
void makeSound(int dx, int dy, Sound sound);
/** /**
* Sets the tile value at a relative location. * Sets the tile value at a relative location.
*/ */
@ -16,4 +18,6 @@ public interface ToolEffectIfc
* Deduct an amount from the controller's cash funds. * Deduct an amount from the controller's cash funds.
*/ */
void spend(int amount); void spend(int amount);
void toolResult(ToolResult tr);
} }

View file

@ -1,6 +1,6 @@
package micropolisj.engine; package micropolisj.engine;
import java.util.Arrays; import java.util.*;
import static micropolisj.engine.TileConstants.*; import static micropolisj.engine.TileConstants.*;
public class ToolPreview implements ToolEffectIfc public class ToolPreview implements ToolEffectIfc
@ -9,11 +9,28 @@ public class ToolPreview implements ToolEffectIfc
public int offsetY; public int offsetY;
public short [][] tiles; public short [][] tiles;
public int cost; 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() ToolPreview()
{ {
this.tiles = new short[1][1]; this.tiles = new short[1][1];
this.tiles[0][0] = CLEAR; this.tiles[0][0] = CLEAR;
this.sounds = new ArrayList<SoundInfo>();
} }
//implements ToolEffectIfc //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 //implements ToolEffectIfc
public void setTile(int dx, int dy, int tileValue) public void setTile(int dx, int dy, int tileValue)
{ {
@ -96,4 +119,10 @@ public class ToolPreview implements ToolEffectIfc
{ {
cost += amount; cost += amount;
} }
//implements ToolEffectIfc
public void toolResult(ToolResult tr)
{
this.toolResult = tr;
}
} }

View file

@ -32,73 +32,36 @@ public class ToolStroke
public ToolResult apply() public ToolResult apply()
{ {
ToolResult checkResult = check(); ToolResult tr = ToolResult.NONE;
if (checkResult != ToolResult.SUCCESS) {
return checkResult;
}
Rectangle r = getBounds(); Rectangle r = getBounds();
for (int i = r.y; i < r.y + r.height; i += tool.getHeight()) { ToolEffect eff = new ToolEffect(city, r.x, r.y);
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;
}
ToolResult checkZoneTool() for (int i = 0; i < r.height; i += tool.getHeight()) {
{ for (int j = 0; j < r.width; j += tool.getWidth()) {
Rectangle b = getBounds(); ToolResult tmp = apply1(
int cost = 0; new TranslatedToolEffect(eff, j, i)
int numPlaced = 0; );
if (tmp == ToolResult.SUCCESS) {
for (int i = b.y; i < b.y + b.height; i += tool.getHeight()) { tr = tmp;
for (int j = b.x; j < b.x + b.width; j += tool.getWidth()) { }
int x = j + (tool.getWidth() >= 3 ? 1 : 0); else if (tr == ToolResult.NONE) {
int y = i + (tool.getHeight() >= 3 ? 1 : 0); tr = tmp;
int c = costToPlaceZone(x, y);
if (c != Integer.MAX_VALUE) {
numPlaced++;
cost += c;
} }
} }
} }
return numPlaced == 0 ? ToolResult.NONE : ToolResult tmp = eff.apply();
cost <= city.budget.totalFunds ? ToolResult.SUCCESS : if (tmp != ToolResult.NONE) {
ToolResult.INSUFFICIENT_FUNDS; return tmp;
} }
else {
/** return tr;
* @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 apply1(int xpos, int ypos) ToolResult apply1(ToolEffectIfc eff)
{ {
ToolEffect eff = new ToolEffect(city, xpos, ypos);
ToolResult tr = ToolResult.SUCCESS; ToolResult tr = ToolResult.SUCCESS;
switch (tool) switch (tool)
@ -108,43 +71,43 @@ public class ToolStroke
break; break;
case RESIDENTIAL: case RESIDENTIAL:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, RESBASE); tr = applyZone(eff, 3, 3, RESBASE);
break; break;
case COMMERCIAL: case COMMERCIAL:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, COMBASE); tr = applyZone(eff, 3, 3, COMBASE);
break; break;
case INDUSTRIAL: case INDUSTRIAL:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, INDBASE); tr = applyZone(eff, 3, 3, INDBASE);
break; break;
case FIRE: case FIRE:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, FIRESTBASE); tr = applyZone(eff, 3, 3, FIRESTBASE);
break; break;
case POLICE: case POLICE:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 3, 3, POLICESTBASE); tr = applyZone(eff, 3, 3, POLICESTBASE);
break; break;
case POWERPLANT: case POWERPLANT:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, COALBASE); tr = applyZone(eff, 4, 4, COALBASE);
break; break;
case STADIUM: case STADIUM:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, STADIUMBASE); tr = applyZone(eff, 4, 4, STADIUMBASE);
break; break;
case SEAPORT: case SEAPORT:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, PORTBASE); tr = applyZone(eff, 4, 4, PORTBASE);
break; break;
case NUCLEAR: case NUCLEAR:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 4, 4, NUCLEARBASE); tr = applyZone(eff, 4, 4, NUCLEARBASE);
break; break;
case AIRPORT: case AIRPORT:
tr = applyZone(new TranslatedToolEffect(eff, -1, -1), 6, 6, AIRPORTBASE); tr = applyZone(eff, 6, 6, AIRPORTBASE);
break; break;
default: default:
@ -152,11 +115,7 @@ public class ToolStroke
throw new Error("unexpected tool: "+tool); throw new Error("unexpected tool: "+tool);
} }
if (tr != ToolResult.SUCCESS) { return tr;
return tr;
}
return eff.apply();
} }
public void dragTo(int xdest, int ydest) public void dragTo(int xdest, int ydest)
@ -196,38 +155,6 @@ public class ToolStroke
return r; 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) ToolResult applyZone(ToolEffectIfc eff, int width, int height, char tileBase)
{ {
int cost = tool.getToolCost(); int cost = tool.getToolCost();
@ -556,22 +483,6 @@ public class ToolStroke
return; 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) boolean isBigZone(int tile)
{ {
if (tile >= RESBASE && tile <= LASTZONE) if (tile >= RESBASE && tile <= LASTZONE)
@ -583,27 +494,4 @@ public class ToolStroke
else else
return false; 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;
}
}
} }

View file

@ -19,6 +19,12 @@ class TranslatedToolEffect implements ToolEffectIfc
return base.getTile(x+dx, y+dy); 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 //implements ToolEffectIfc
public void setTile(int x, int y, int tileValue) public void setTile(int x, int y, int tileValue)
{ {
@ -30,4 +36,10 @@ class TranslatedToolEffect implements ToolEffectIfc
{ {
base.spend(amount); base.spend(amount);
} }
//implements ToolEffectIfc
public void toolResult(ToolResult tr)
{
base.toolResult(tr);
}
} }