net.noviden.towerdefense.UnitFactory.Unit.java Source code

Java tutorial

Introduction

Here is the source code for net.noviden.towerdefense.UnitFactory.Unit.java

Source

/**
 Infinite Paths : Infinite Tower Defense Game With User Created Maps
 Copyright (C) 2015 Tristan Kernan
    
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.noviden.towerdefense.UnitFactory;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;

import net.noviden.towerdefense.MissileFactory.Missile;
import net.noviden.towerdefense.Path;
import net.noviden.towerdefense.Point;

public class Unit {

    protected static final Color BASE_UNIT_COLOR = Color.BLUE;
    protected static final Color BASE_UNIT_DAMAGED_COLOR = Color.RED;

    private static final float BASE_RADIUS = 10.0f;
    private static final int BASE_WORTH = 20;

    protected float health, maxHealth;
    private float damage;
    public Point location;
    public float radius;

    protected Path path;
    protected int currentDestinationIndex;
    private float xVelocity, yVelocity;
    private float percentSlowed, timeSlowed;
    protected float speed;

    private int worth;

    protected float rotation;

    protected Point[] points;
    protected Point[] rotatedPoints;
    protected Vector2 rotationVector;

    public Unit() {
    }

    public Unit(float health, float damage, float speed, Path path) {
        this.health = this.maxHealth = health;
        this.damage = damage;
        this.path = path;

        // initial location is equal to 1st position in path set, and destination the 2nd in set
        this.location = path.set.get(0).clone();
        this.currentDestinationIndex = 1;
        this.radius = BASE_RADIUS;
        this.worth = BASE_WORTH;
        this.speed = speed;

        this.rotation = 0.0f;

        setUpBoundaries();

        // set initial xVel and yVel based on destination
        Point destination = path.set.get(currentDestinationIndex);

        float distanceBetween = (float) Math
                .sqrt(Math.pow(location.x - destination.x, 2) + Math.pow(location.y - destination.y, 2));

        this.xVelocity = (destination.x - location.x) / distanceBetween;
        this.yVelocity = (destination.y - location.y) / distanceBetween;
    }

    public Unit(float health, float damage, float speed, Path path, Point initialLocation,
            int currentDestinationIndex) {
        this(health, damage, speed, path);

        this.location = initialLocation.clone();
        this.currentDestinationIndex = currentDestinationIndex;

        // set initial xVel and yVel based on destination
        if (currentDestinationIndex >= path.set.size()) {
            // set to last destination in path
            this.currentDestinationIndex = path.set.size() - 1;
        }

        Point destination = path.set.get(this.currentDestinationIndex);

        float distanceBetween = (float) Math
                .sqrt(Math.pow(location.x - destination.x, 2) + Math.pow(location.y - destination.y, 2));

        this.xVelocity = (destination.x - location.x) / distanceBetween;
        this.yVelocity = (destination.y - location.y) / distanceBetween;
    }

    public void act(float deltaTime) {
        // move along line from by currentLocation -> currentDestination until arrive at
        // destination, then set new destination

        // set the rotation factor for our little guys
        rotation += deltaTime * 108.0f;
        if (rotation > 360.0f) {
            rotation = 0.0f;
        }

        // count down slow timer
        if (timeSlowed >= 0.0f) {
            timeSlowed -= deltaTime;

            if (timeSlowed <= 0.0f) {
                percentSlowed = 0.0f;
            }
        }

        // check for boundaries
        if (location.x < 0 || location.x > Gdx.graphics.getWidth() || location.y < 0
                || location.y > Gdx.graphics.getHeight()) {

            // set unit to be removed
            this.health = (-1.0f);

            return;
        }

        Point destination = path.set.get(currentDestinationIndex);

        // base case: time to find a new destination
        if (Math.abs(location.x - destination.x) < 2.5f && Math.abs(location.y - destination.y) < 2.5f) {
            // close enough! on to the next destination
            currentDestinationIndex++;

            // check for end of the line
            if (currentDestinationIndex >= path.set.size()) {
                this.health = -1.0f;
            } else {
                // recalculate xVel and yVel
                destination = path.set.get(currentDestinationIndex);

                float distanceBetween = (float) Math
                        .sqrt(Math.pow(location.x - destination.x, 2) + Math.pow(location.y - destination.y, 2));

                this.xVelocity = (destination.x - location.x) / distanceBetween;
                this.yVelocity = (destination.y - location.y) / distanceBetween;
            }
        } else {
            // recalculate velocities to current destination
            // TODO this is only necessary if map transformations are turned ON

            // recalculate xVel and yVel
            destination = path.set.get(currentDestinationIndex);

            float distanceBetween = (float) Math
                    .sqrt(Math.pow(location.x - destination.x, 2) + Math.pow(location.y - destination.y, 2));

            this.xVelocity = (destination.x - location.x) / distanceBetween;
            this.yVelocity = (destination.y - location.y) / distanceBetween;
        }

        location.x += xVelocity * deltaTime * speed * (1.0f - percentSlowed);
        location.y += yVelocity * deltaTime * speed * (1.0f - percentSlowed);
    }

    public void draw(ShapeRenderer shapeRenderer) {
        // draw each unit's health as a percent of its circle
        float percentHealthMissing = (1.0f - this.health / this.maxHealth);
        float degrees = percentHealthMissing * 360.0f;

        shapeRenderer.setColor(BASE_UNIT_COLOR);
        shapeRenderer.circle(location.x, location.y, BASE_RADIUS);

        if (percentHealthMissing > 0.0f) {
            shapeRenderer.setColor(BASE_UNIT_DAMAGED_COLOR);
            shapeRenderer.arc(location.x, location.y, BASE_RADIUS, rotation, degrees);
        }
    }

    protected void setUpBoundaries() {
        // circle unit has circle boundaries
    }

    public void updatePath(Path pNewPath) {
        this.path = pNewPath;
    }

    public boolean collidesWith(Missile missile) {
        float distanceBetween = (float) Math.sqrt(Math.pow(this.location.x - missile.location.x, 2)
                + Math.pow(this.location.y - missile.location.y, 2));

        if (distanceBetween < (missile.radius + this.radius)) {
            return true;
        }

        return false;
    }

    public Unit getNextUnitToSpawn() {
        return null;
    }

    public float getDamage() {
        return this.damage;
    }

    public void takeDamage(float amount) {
        this.health -= amount;
    }

    public void slowDown(float timeSlowed, float percentSlowed) {
        this.timeSlowed = timeSlowed;

        // always slow unit by higher factor, never decrease
        if (this.percentSlowed < percentSlowed) {
            this.percentSlowed = percentSlowed;
        }
    }

    public boolean isDead() {
        return (health < 0.0f);
    }

    public int getWorth() {
        return this.worth;
    }

    public float getSpeed() {
        return this.speed;
    }

    public boolean reachedEndOfPath() {
        return (currentDestinationIndex >= path.set.size());
    }
}