app/src/main/java/de/dhbw/map/objects/tower/ATower.java
package de.dhbw.map.objects.tower;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TimerTask;
import java.util.UUID;
import java.util.stream.Collectors;
import java.lang.Math;
import de.dhbw.R;
import de.dhbw.activities.GameActivity;
import de.dhbw.game.ATimerUsage;
import de.dhbw.game.EnemyType;
import de.dhbw.map.matchfield.MatchField;
import de.dhbw.map.objects.enemy.AEnemy;
import de.dhbw.map.objects.enemy.Tank;
import de.dhbw.util.Position;
import de.dhbw.util.SortingUtil;
import de.dhbw.map.structure.Field;
public abstract class ATower extends ATimerUsage {
private UUID id;
private TowerType towerType;
private int level;
private int costs;
protected int damage;
private int range;
private int fireRate;
private ImageView baseImage;
protected Optional<ImageView> headImage = Optional.empty();
private ImageView starlvlTwo;
private ImageView starlvlThree;
private ImageView starlvlFour;
private int x;
private int y;
private Field field;
private TimerTask task;
protected AEnemy targetedEnemy;
protected GameActivity gameActivity;
/**
* Constructor
* @param id
* @param towerType
* @param level
* @param costs
* @param damage
* @param range
* @param fireRate
* @param field
* @param gameActivity
*/
public ATower(UUID id, TowerType towerType, int level, int costs, int damage, int range, int fireRate, Field field, GameActivity gameActivity) {
this.id = id;
this.towerType = towerType;
this.level = level;
this.costs = costs;
this.damage = damage;
this.range = range;
this.fireRate = fireRate;
this.field = field;
this.x = field.getSpawnPoint().getX();
this.y = field.getSpawnPoint().getY();
this.gameActivity = gameActivity;
switch (level) {
case 4:
starlvlFour = new ImageView(gameActivity);
starlvlFour.setImageResource(R.drawable.star);
starlvlFour.setX(field.getSpawnPoint().getX() + 100);
starlvlFour.setY(field.getSpawnPoint().getY());
starlvlFour.setLayoutParams(new LinearLayout.LayoutParams(50, 50));
case 3:
starlvlThree = new ImageView(gameActivity);
starlvlThree.setImageResource(R.drawable.star);
starlvlThree.setX(field.getSpawnPoint().getX() + 50);
starlvlThree.setY(field.getSpawnPoint().getY());
starlvlThree.setLayoutParams(new LinearLayout.LayoutParams(50, 50));
case 2:
starlvlTwo= new ImageView(gameActivity);
starlvlTwo.setImageResource(R.drawable.star);
starlvlTwo.setX(field.getSpawnPoint().getX());
starlvlTwo.setY(field.getSpawnPoint().getY());
starlvlTwo.setLayoutParams(new LinearLayout.LayoutParams(50, 50));
}
}
/**
* The tower shoots the nearest enemy if it is in range
* @param enemies
* @return true if there is an enemy to shoot at
*/
public boolean fire(List<AEnemy> enemies) {
List<AEnemy> enemiesInRange = enemies.stream().filter(enemy -> isEnemyInRange(enemy) && filterPlaneIfTowerCannotFocus(towerType, enemy)).collect(Collectors.toList());
AEnemy enemy = getNearestEnemy(getPosition(), enemiesInRange);
if (enemy != null) {
targetedEnemy = enemy;
return true;
}
return false;
}
public static boolean filterPlaneIfTowerCannotFocus(TowerType towerType, AEnemy enemy){
if(enemy.getType()==EnemyType.PLANE){
return towerType==TowerType.ARTILLERY || towerType == TowerType.FREEZER;
}else {
return true;
}
}
protected List<AEnemy> getFocusableEnemies(List<AEnemy> enemies){
return enemies.stream().filter(e -> filterPlaneIfTowerCannotFocus(towerType, e)).collect(Collectors.toList());
}
/**
* Checks if an enemy is in range of the tower.
* @param enemy
* @return true if the enemy is in range
*/
public boolean isEnemyInRange(AEnemy enemy) {
return MatchField.getDistance(enemy.getPositionX(), enemy.getPositionY(), x, y) < range;
}
/**
* Sets the base image of the tower.
* @param image
*/
public void setBaseImage(ImageView image){
this.baseImage=image;
}
/**
* Sets the head image of the tower.
* @param image
*/
public void setHeadImage(ImageView image){
this.headImage= Optional.of(image);
}
/**
*
* @return head image (if present)
*/
public Optional<ImageView> getHeadImage(){
return headImage;
}
/**
*
* @return base image
*/
public ImageView getBaseImage(){
return baseImage;
}
/**
*
* @return field on which the tower is located
*/
public Field getField() {
return field;
}
/**
*
* @return timertask of the tower
*/
public TimerTask getTask() {
return task;
}
/**
* Set the task for tower.
* @param task
*/
public void setTask(TimerTask task) {
this.task = task;
}
/**
* All enemies are saved in a map with their actual distance to the tower.
* The map is sorted by distance, so the nearest enemy is on the first place of the map. We don't have to care about enemies with the same distance.
* @param enemies
* @return
*/
public AEnemy getNearestEnemy(Position actualPosition, List<AEnemy> enemies) {
if (!enemies.isEmpty()) {
Map<AEnemy, Integer> distanceToEnemy = new HashMap<>();
for (AEnemy enemy : enemies) {
int distance = MatchField.getDistance(enemy.getPositionX(), enemy.getPositionY(), actualPosition.getX(), actualPosition.getY());
distanceToEnemy.put(enemy, distance);
}
List<AEnemy> sortedByDistance = SortingUtil.getSortedListBySortingMapByValue(distanceToEnemy);
for (AEnemy enemy : sortedByDistance) {
if (enemy.isAlive()) {
return enemy;
}
}
}
return null;
}
/**
* Returns the number necessary to rotate the tower image according to the targeted enemy
* @return
*/
public double rotateImage(List<AEnemy> enemies) {
double rotation = 0;
AEnemy enemy = getNearestEnemy(getPosition(), enemies);
if (enemy != null) {
double a = this.getPositionX() - enemy.getPositionX();
double b = this.getPositionY() - enemy.getPositionY();
rotation = Math.toDegrees(Math.atan2(b, a));
}
return rotation;
}
/**
*
* @return id of this tower
*/
public UUID getId() {
return id;
}
/**
*
* @return towertype
*/
public TowerType getTowerType() { return this.towerType; }
/**
*
* @return level of this tower
*/
public int getLevel() { return this.level; }
/**
*
* @return costs of this tower
*/
public int getCosts() {
return costs;
}
/**
*
* @return damage of this tower
*/
public int getDamage() {
return damage;
}
/**
*
* @return range in px of this tower
*/
public int getRange() {
return range;
}
/**
*
* @return firerate of this tower
*/
public int getFireRate() {
return fireRate;
}
public abstract int getCosts(int level);
public abstract int getDamage(int level);
public abstract int getRange(int level);
public abstract int getFireRate(int level);
/**
*
* @return x-position of this tower in px (midpoint)
*/
public int getPositionX() {
return x;
}
/**
*
* @return y-position of this tower in px (midpoint)
*/
public int getPositionY() {
return y;
}
/**
*
* @return position of this tower in px (midpoint)
*/
public Position getPosition() {
return new Position(x, y);
}
/**
*
* @return image of level-2-star
*/
public ImageView getStarlvlTwo() {
return starlvlTwo;
}
/**
*
* @return image of level-3-star
*/
public ImageView getStarlvlThree() {
return starlvlThree;
}
/**
*
* @return image of level-4-star
*/
public ImageView getStarlvlFour() {
return starlvlFour;
}
@Override
public void calculateDelay(long time){
setDelay(fireRate*1000 - (time-lastTimeActionMillis));
}
}