package com.touchspin.td;
/* ======================================================================================
* File: Balls.java
* Authors: Brian Adams - b.adams5736@edmail.edcc.edu
* Russell Brendel - russell.brendel.2925@edmail.edcc.edu
* Damian Forrester - dforrester777@gmail.com
* Wendi Tang - w.tang2404@myedmail.edcc.edu
*
* Organization: Edmonds Community College
* Term: Spring 2014
* Class: CS 185 - Game Project Developement
* Instructor: Tim Hunt - thunt@edcc.edu
*
* Project: Ollie
* --------------------------------------------------------------------------------------
*
* This class holds information for a ball type object
*
* ======================================================================================
*/
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
public class Balls extends GameThing {
public OrthographicCamera camera;
public MoverBall ballMover;
private Map<String, TextureRegion> ballTypeMap = new HashMap<String, TextureRegion>();
private Animation fireAnimation;
private Animation smokeAnimation;
private TextureRegion currentFireFrame;
private TextureRegion currentSmokeFrame;
private float scaleFactor;
private float ventRatio = 1;
private int frameCount = 0;
private Sprite ballSprite;
private Sprite fireEffect;
private Sprite smokeEffect;
public boolean flammable;
public boolean fireOn;
public float radius;
private float countTime;
public String ballType;
private boolean active;
public float dyInWater;
public float mass;
public float friction;
public int health;
private float MaxDistance = 500;
private Vector2 myPosition = new Vector2();
public static final String BallBalloon = "Balloon";
public static final String BallPingPong = "PingPong";
public static final String BallBowling = "Bowling";
public static final String BallBasket = "Basket";
public static final String BallBase = "Base";
public static final String BallTennis = "Tennis";
public static final String BallBeach = "Beach";
public static final String BallMarble = "Marble";
public static final String BallSoccer = "Soccer";
public static final String BallPool = "Pool";
public static final String BallGolf = "Golf";
public static final String BallBearing = "BearingSteel";
/**
* The constructor.
*
* @param ballType
* - the type of the ball
* @param x
* - the start position x
* @param y
* - the start position y
* @param camera
* - the camera used in the game screen
* @param tiledMapWrapper
* - the tiledMapWrapper used in the game screen
*/
public Balls(String ballType, float x, float y, OrthographicCamera camera,
TiledMapWrapper tiledMapWrapper) {
active = true;
this.camera = camera;
this.tiledMapWrapper = tiledMapWrapper;
health = 100;
ballMover = new MoverBall(this);
ballSprite = new Sprite();
loadBallType();
this.ballType = ballType;
changeBall(ballType);
ballSprite.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* camera.zoom);
ballSprite.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
setHeight(ballSprite.getHeight() * camera.zoom);
setWidth(ballSprite.getWidth() * camera.zoom);
setX(x);
setY(y);
scaleFactor = 1f;
// read in file animation
loadFireAnimation();
stateTime = 0f;
currentFireFrame = fireAnimation.getKeyFrame(stateTime, true);
loadSmokeAnimation();
currentSmokeFrame = smokeAnimation.getKeyFrame(stateTime, true);
fireEffect = new Sprite(currentFireFrame);
fireEffect.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* fireEffect.getHeight() / fireEffect.getWidth() * camera.zoom);
fireEffect.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
smokeEffect = new Sprite(currentSmokeFrame);
smokeEffect.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* smokeEffect.getHeight() / smokeEffect.getWidth()
* camera.zoom);
smokeEffect.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
if (ballType.equalsIgnoreCase(BallBalloon)) {
randomTint();
}
}
/**
* The draw method of this object
*/
@Override
public void draw(Batch batch, float alpha) {
if (myPosition.dst(g.i().hero.getX(), g.i().hero.getY()) < MaxDistance
|| g.i().controls != 'A') {
if (active) {
batch.setProjectionMatrix(camera.combined);
if (frameCount == 60) {
ballSprite.setColor(Color.RED);
} else if (frameCount == 1) {
ballSprite.setColor(Color.WHITE);
}
ballSprite.draw(batch);
if (fireOn) {
drawEffect(batch);
}
}
}
}
/**
* Draw fire effect
*
* @param batch
*/
private void drawEffect(Batch batch) {
// batch.draw(currentFrame,getX(),getY(),32f,currentFrame.getRegionHeight()*32/currentFrame.getRegionWidth());
smokeEffect.draw(batch);
fireEffect.draw(batch);
}
/**
* The update method
*/
@Override
public void act(float delta) {
if (myPosition.dst(g.i().hero.getX(), g.i().hero.getY()) < MaxDistance
|| g.i().controls != 'A') {
if (active) {
g.i().currentBall = this;
ballMover.move(this);
// Attack
if (frameCount > 1)
frameCount--;
// position
setSpritesPosition();
// Rotation
ballSprite.rotate(360 * (ballMover.previousX - getX())
/ ((float) Math.PI * ballSprite.getRegionHeight()));
setRotationAndScale();
// animation
stateTime += Gdx.graphics.getDeltaTime();
currentFireFrame = fireAnimation.getKeyFrame(stateTime, true);
fireEffect.setRegion(currentFireFrame);
currentSmokeFrame = smokeAnimation.getKeyFrame(stateTime, true);
smokeEffect.setRegion(currentSmokeFrame);
if (fireOn) {
countTime += Gdx.graphics.getDeltaTime();
if (countTime > 2) {
health -= 5;
countTime = 0;
}
}
if (health < 0) {
active = false;
}
g.i().currentBall = null;
}
}
myPosition.set(getX(), getY());
}
/**
* Change the ball to the specific ball type
*
* @param type
* - the ball type the player will be change to
*/
public void changeBall(String type) {
switch (type) {
case BallPingPong:
friction = 0.008f;
flammable = true;
radius = 2.9f;
break;
case BallBowling:
friction = 0.03f;
flammable = false;
radius = 15f;
fireOn = false;
break;
case BallBasket:
friction = 0.011f;
flammable = true;
radius = 15f;
break;
case BallBase:
friction = 0.008f;
flammable = true;
radius = 11.08f;
break;
case BallTennis:
friction = 0.008f;
flammable = true;
radius = 11.08f;
break;
case BallBalloon:
friction = 0.008f;
flammable = true;
radius = 15f;
break;
}
ballType = type;
ballSprite.setRegion(ballTypeMap.get(type));
if (ballType.equalsIgnoreCase(BallBalloon)) {
randomTint();
} else {
ballSprite.setColor(Color.WHITE);
}
setSpriteBounds();
calcualteDyInWater();
}
/**
* ignite the ball or put out fire
*
* @param fireOn
* - ignite the ball if true put out the fire if false
*/
public void igniteBall(boolean fireOn) {
this.fireOn = fireOn;
}
/**
* Change the ball's speed along x axis
*
* @param speed
* - the base speed
*/
public void changeBallX(float speed) {
ballMover.speedXPerSecond = speed * ventRatio;
}
/**
* Change the ball's speed along y axis
*
* @param speed
* - the base speed
*/
public void changeBallY(float speed) {
ballMover.speedYPerSecond = speed * ventRatio;
}
/**
* Get the current speed of the ball along y axis
*
* @return the current speed along y axis
*/
public float getYSpeed() {
return ballMover.speedYPerSecond;
}
/**
* Get the current speed of the ball along x axis
*
* @return the current speed along x axis
*/
public float getXSpeed() {
return ballMover.speedXPerSecond;
}
/**
* return the center of the ball
*
* @return the center of the ball
*/
public Vector2 getCenter() {
Vector2 center = new Vector2(getX() + getWidth() / 2, getY()
+ getHeight() / 2);
return center;
}
// --------------Private helper
// method------------------------------------------
/**
* Set all sprites position based on actor's position
*/
private void setSpritesPosition() {
ballSprite.setX(getX());
ballSprite.setY(getY());
fireEffect.setX(getX());
fireEffect.setY(getY());
smokeEffect.setX(getX());
smokeEffect.setY(getY());
}
/**
* load ball texture regions based on ball type
*/
private void loadBallType() {
Texture appearance = new Texture("img/spritesheet/BallSquish.png");
TextureRegion[][] tmp = TextureRegion.split(appearance,
appearance.getWidth() / 6, appearance.getHeight() / 12);
ballTypeMap.put(BallBowling, tmp[0][0]);
ballTypeMap.put(BallBasket, tmp[1][0]);
ballTypeMap.put(BallPingPong, tmp[2][0]);
ballTypeMap.put(BallBase, tmp[4][0]);
ballTypeMap.put(BallBeach, tmp[5][0]);
ballTypeMap.put(BallMarble, tmp[6][0]);
ballTypeMap.put(BallSoccer, tmp[7][0]);
ballTypeMap.put(BallPool, tmp[8][0]);
ballTypeMap.put(BallTennis, tmp[9][0]);
ballTypeMap.put(BallGolf, tmp[10][0]);
ballTypeMap.put(BallBalloon, tmp[11][0]);
}
/**
* Load in the fire animation
*/
private void loadFireAnimation() {
Texture fire = new Texture(
Gdx.files.internal("img/spritesheet/Fireball.png"));
TextureRegion[][] tmp = TextureRegion.split(fire, fire.getWidth() / 12,
fire.getHeight() / 4);
TextureRegion[] fireFrames = new TextureRegion[12 * 4];
int index = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 12; j++) {
fireFrames[index++] = tmp[i][j];
}
}
fireAnimation = new Animation(0.025f, fireFrames);
}
/**
* Load in the smoke animation
*/
private void loadSmokeAnimation() {
Texture fire = new Texture(
Gdx.files.internal("img/spritesheet/Smoke.png"));
TextureRegion[][] tmp = TextureRegion.split(fire, fire.getWidth() / 15,
fire.getHeight() / 6);
TextureRegion[] smokeFrames = new TextureRegion[15 * 6 - 4];
int index = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 15; j++) {
smokeFrames[index++] = tmp[i][j];
if (index == smokeFrames.length)
break;
}
}
smokeAnimation = new Animation(0.025f, smokeFrames);
}
/**
* Set the rotation and scale of each ball properly
*/
private void setRotationAndScale() {
if (ballMover.speedXPerSecond == 0) {
if (ballMover.speedYPerSecond > 0)
fireEffect.setRotation((float) (-180));
else if (ballMover.speedYPerSecond < 0)
fireEffect.setRotation(0);
}
else if (ballMover.speedYPerSecond == 0) {
if (g.i().gameMode == 'R') {
if (ballMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (40 * Math
.atan(ballMover.speedXPerSecond / 200)));
else if (ballMover.speedXPerSecond < 0)
fireEffect.setRotation((float) (40 * Math
.atan(ballMover.speedXPerSecond / 200)));
} else {
if (ballMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90));
else if (ballMover.speedXPerSecond < 0)
fireEffect.setRotation((float) (-90));
}
}
else if (ballMover.speedXPerSecond * ballMover.speedYPerSecond > 0) {
if (ballMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90 + Math
.atan(ballMover.speedYPerSecond
/ ballMover.speedXPerSecond)
/ Math.PI * 180));
else
fireEffect.setRotation((float) (-(90 - Math
.atan(ballMover.speedYPerSecond
/ ballMover.speedXPerSecond)
/ Math.PI * 180)));
} else if (ballMover.speedXPerSecond * ballMover.speedYPerSecond < 0) {
if (ballMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90 + Math
.atan(ballMover.speedYPerSecond
/ ballMover.speedXPerSecond)
/ Math.PI * 180));
else
fireEffect.setRotation((float) (-90 + Math
.atan(ballMover.speedYPerSecond
/ ballMover.speedXPerSecond)
/ Math.PI * 180));
}
smokeEffect.setRotation(fireEffect.getRotation());
scaleFactor = Math.max((float) Math.hypot(ballMover.speedXPerSecond,
ballMover.speedYPerSecond) / 300, 1f);
fireEffect.setScale(1f, scaleFactor);
smokeEffect.setScale(1f, scaleFactor);
}
/**
* Set the bounds of the ball sprite
*/
private void setSpriteBounds() {
if (ballSprite != null) {
ballSprite.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* camera.zoom);
ballSprite.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
}
setHeight(ballSprite.getHeight() * camera.zoom);
setWidth(ballSprite.getWidth() * camera.zoom);
if (fireEffect != null) {
fireEffect.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* fireEffect.getHeight() / fireEffect.getWidth()
* camera.zoom);
fireEffect.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
}
if (smokeEffect != null) {
smokeEffect.setBounds(0, 32, radius * 2 * camera.zoom, radius * 2
* smokeEffect.getHeight() / smokeEffect.getWidth()
* camera.zoom);
smokeEffect.setOrigin(ballSprite.getWidth() / 2,
ballSprite.getHeight() / 2);
}
}
/**
* Calculate the ball's acceleration along y axis in water
*/
private void calcualteDyInWater() {
float radius = 0;
float floatforce = 0;
int inWaterdyFactor = 1;
switch (ballType) {
case BallPingPong:
mass = 0.0027f;
radius = 0.0200f;
break;
case BallBowling:
mass = 7.3000f;
radius = 0.0900f;
break;
case BallBasket:
mass = 2.6200f;
radius = 0.1210f;
break;
case BallBase:
mass = 0.1450f;
radius = 0.0382f;
break;
case BallTennis:
mass = 0.0600f;
radius = 0.0335f;
break;
case BallBalloon:
mass = 0.0020f;
radius = 0.1210f;
break;
}
floatforce = (float) (1000 * 9.8f * 4 / 3 * Math.PI * Math.pow(radius,
3));
float force = (floatforce + (-9.8f * mass)) * inWaterdyFactor;
float dy = force / mass;
dyInWater = dy;
}
/**
* Randomly tint the ball.
*/
private void randomTint() {
ballSprite.setColor(new Color(g.i().rnd.nextFloat(), g.i().rnd
.nextFloat(), g.i().rnd.nextFloat(), 1));
}
}