/**
*
*/
package com.androiddefense.engine;
import java.util.ArrayList;
import java.util.List;
import com.androiddefense.engine.coordinate.Coord;
import com.androiddefense.engine.enemy.Enemy_I;
import com.androiddefense.engine.enemy.PlainEnemy;
import com.androiddefense.engine.tile.PlainTile;
import com.androiddefense.engine.tile.Tile_I;
import com.androiddefense.engine.tower.PlainTower;
import com.androiddefense.engine.tower.Projectile_I;
import com.androiddefense.engine.tower.Tower_I;
import com.androiddefense.main.R;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
/**
* GameModel class
*
* @author Steven Christou
*
*/
public class GameModel implements GameModel_I {
Tile_I[][] myGrid;
ArrayList<Enemy_I> queuedEnemies = new ArrayList<Enemy_I> ();
ArrayList<Enemy_I> myEnemies = new ArrayList<Enemy_I> ();
ArrayList<Tower_I> myTowers = new ArrayList<Tower_I> ();
Paint myBorderPaint;
Rect myBorderRect;
final Coord startSpot = new Coord(0, 1);
private ArrayList<Projectile_I> myProjectiles = new ArrayList<Projectile_I>();
public Bitmap scaledImage(Resources res, float px, int image) {
Bitmap img = BitmapFactory.decodeResource(res, image);
int w = img.getWidth();
int h = img.getHeight();
Matrix m = new Matrix();
m.setScale(px / w, px / h);
return Bitmap.createBitmap(img, 0, 0, w, h, m, true);
}
public GameModel(int width, int height, Resources res) {
if (width < 2 || height < 2) {
throw new IllegalArgumentException("You should make a larger Tower grid: " + width + ", " + height);
}
Bitmap projectileImg = scaledImage(res, 5.0f, R.drawable.bullet);
myGrid = new Tile_I[width][height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
myGrid[x][y] = new PlainTile(x, y, res);
if (x % 3 == 0 && y % 3 == 0) {
try {
addTower(
new PlainTower(
new Coord(x * GameModel_I.TILE_SIZE, y * GameModel_I.TILE_SIZE), projectileImg),
new Coord(x, y));
} catch (Exception e) {
Log.i("GameModel", "adding bad tower type at: " + x + ", " + y);
}
}
}
}
Bitmap enemyImg = scaledImage(res, (float)GameModel_I.TILE_SIZE, R.drawable.enemy);
for (int e = 0; e < 10; e++) {
queuedEnemies.add(new PlainEnemy(enemyImg, startSpot, startSpot));
}
myBorderPaint = new Paint();
myBorderPaint.setARGB(255, 155, 155, 155);
myBorderPaint.setStyle(Paint.Style.STROKE);
myBorderRect = new Rect(0, 0, width * GameModel_I.TILE_SIZE, height * GameModel_I.TILE_SIZE);
myGrid[width - 1][height - 1].setEnemyDest();
calculateDistances();
}
private void calculateDistances() {
for (int x = 0; x < myGrid[0].length; x++) {
for (int y = 0; y < myGrid.length; y++) {
if (myGrid[x][y].getDist() == 0) {
setNeighborsDist(x, y, 0);
}
}
}
}
private boolean inBounds(int x, int y) {
return x < myGrid[0].length && x >= 0 &&
y < myGrid.length && y >= 0;
}
private void setNeighborsDist(int x, int y, int iters) {
if (iters > 20) {
return;
}
int[][] myCoords = new int[][]{
{x - 1, y - 1},
{x - 1, y },
{x - 1, y + 1},
{x, y - 1},
{x, y + 1},
{x + 1, y - 1},
{x + 1, y},
{x + 1, y + 1},
};
int curDist = myGrid[x][y].getDist();
for (int[] c : myCoords) {
int myX = c[0];
int myY = c[1];
if (inBounds(myX, myY) &&
myGrid[myX][myY].getTower() == null &&
(myGrid[myX][myY].getDist() == -1 ||
curDist + 1 < myGrid[myX][myY].getDist()))
{
myGrid[myX][myY].setDist(curDist + 1);
// Log.i("GameModel","setNeighborsDist " + x + ", " + y + ", " + (curDist + 1));
setNeighborsDist(myX, myY, iters + 1);
}
}
}
public Coord getNextSmallestDist(Coord origCoord) {
final int x = origCoord.x;
final int y = origCoord.y;
final Coord[] myCoords = new Coord[] {
// new Coord(x - 1, y - 1),
new Coord(x - 1, y),
// new Coord(x - 1, y + 1),
new Coord(x, y - 1),
new Coord(x, y + 1),
// new Coord(x + 1, y - 1),
new Coord(x + 1, y),
// new Coord(x + 1, y + 1),
};
int currentDist = myGrid[x][y].getDist();
Coord minCoord = null;
for (Coord c : myCoords) {
if (inBounds(c.x, c.y) &&
myGrid[c.x][c.y].getDist() != -1 &&
myGrid[c.x][c.y].getDist() <= currentDist)
{
currentDist = myGrid[c.x][c.y].getDist();
minCoord = new Coord(c.x, c.y);
}
}
Log.i("GameModel","next smallest from " + origCoord + " is " + minCoord);
return minCoord;
}
public void addTower(Tower_I t, final Coord coord) throws Exception {
if (myGrid[coord.x][coord.y].accepts(t))
{
myGrid[coord.x][coord.y].setTower(t);
myTowers.add(t);
}
else {
throw new Exception("tile doesn't accept that kind of tower: " + coord + ", " + t);
}
}
private boolean enemyInStartSpot() {
for (Enemy_I e : myEnemies) {
if (e.currentlyAt(startSpot)) {
Log.i("GameModel","startSpot: " + startSpot + ", enemy at startSpot: " + e);
return true;
}
}
return false;
}
public List<Enemy_I> getWithinRange(List<Enemy_I> myEnemies, int dist, Coord loc) {
ArrayList<Enemy_I> ret = new ArrayList<Enemy_I>();
for (Enemy_I e : myEnemies) {
if (e.getScreenLoc().isWithin(dist, loc)) {
ret.add(e);
}
}
return ret;
}
public void stepForward() {
Log.i("GameModel", "stepForward starting, queuedEnemies: " + queuedEnemies.size() +
", myEnemies: " + myEnemies.size());
if (!enemyInStartSpot() && queuedEnemies.size() > 0) {
Log.i("GameModel", "adding enemy to grid: " + queuedEnemies.get(0));
myEnemies.add(queuedEnemies.remove(0));
}
for (Tower_I t : myTowers) {
Projectile_I p = t.fireAt(getWithinRange(myEnemies, GameModel_I.TILE_SIZE, t.getScreenLoc()));
if (p != null) {
myProjectiles.add(p);
}
}
ArrayList<Projectile_I> newPs = new ArrayList<Projectile_I>();
for (Projectile_I p : myProjectiles) {
p.moveForward();
if (!p.atTarget()) {
newPs.add(p);
}
}
myProjectiles = newPs;
for (Enemy_I e : myEnemies) {
e.moveForward(this);
}
}
public void draw(Canvas canvas) {
Log.i("GameModel", "draw starting");
for (int x = 0; x < myGrid[0].length; x++) {
for (int y = 0; y < myGrid.length; y++) {
if (myGrid[x][y] != null) {
myGrid[x][y].draw(canvas);
}
}
}
for (Enemy_I e : myEnemies) {
e.draw(canvas);
}
for (Projectile_I p : myProjectiles) {
p.draw(canvas);
}
canvas.drawRect(myBorderRect, myBorderPaint);
}
}
|