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
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;
}
}
}

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
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 ||

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}