package com.touchspin.td;
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;
/* ======================================================================================
* File: Hero.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 player.
*
* ======================================================================================
*/
public class Hero extends GameThing {
public OrthographicCamera camera;
public MoverInput heroMover = new MoverInput();
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 int frameCount = 0;
private Sprite heroSprite;
private Sprite fireEffect;
private Sprite smokeEffect;
public boolean flammable;
private float ballHeight;
private float ballWidth;
private float countTime;
public float mass;
public float radius;
private float ventRatio;
private Color baseColor = new Color();
// private float distancePerFrameX;
// private float distancePerFrameY;
// private int gravity = -10;
/**
* The constructor
*
* @param camera
* - the camera used in the game screen
* @param tiledMapWrapper
* - the wrapper class of the tiledMap
*/
public Hero(OrthographicCamera camera, TiledMapWrapper tiledMapWrapper) {
this.tiledMapWrapper = tiledMapWrapper;
this.camera = camera;
heroSprite = new Sprite();
loadBallType();
changeBall(g.i().currentBallType);
heroSprite.setBounds(0, 32, ballWidth * camera.zoom, ballHeight
* camera.zoom);
heroSprite.setOrigin(heroSprite.getWidth() / 2,
heroSprite.getHeight() / 2);
setHeight(heroSprite.getHeight() * camera.zoom);
setWidth(heroSprite.getWidth() * camera.zoom);
setX(10);
setY(100);
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, ballWidth * camera.zoom, ballHeight
* fireEffect.getHeight() / fireEffect.getWidth() * camera.zoom);
fireEffect.setOrigin(heroSprite.getWidth() / 2,
heroSprite.getHeight() / 2);
smokeEffect = new Sprite(currentSmokeFrame);
smokeEffect.setBounds(0, 32, ballWidth * camera.zoom, ballHeight
* smokeEffect.getHeight() / smokeEffect.getWidth()
* camera.zoom);
smokeEffect.setOrigin(heroSprite.getWidth() / 2,
heroSprite.getHeight() / 2);
for (int i = 0; i < g.i().mapObjects.size(); i++) {
if (g.i().mapObjects.get(i).getName().equalsIgnoreCase("enter1")) {
setPosition(g.i().mapObjects.get(i).getX(), g.i().mapObjects
.get(i).getY());
}
}
}
/**
* Draw the player
*/
@Override
public void draw(Batch batch, float alpha) {
batch.setProjectionMatrix(camera.combined);
if (frameCount == 60) {
heroSprite.setColor(Color.RED);
Gdx.input.vibrate(1000);
} else if (frameCount == 1) {
heroSprite.setColor(baseColor);
}
heroSprite.draw(batch);
if (g.i().fire) {
drawEffect(batch);
}
}
/**
* Draw 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);
}
/**
* Update method
*/
@Override
public void act(float delta) {
heroMover.move(this);
// Attack
if (frameCount > 1)
frameCount--;
// position
setSpritesPosition();
// Rotation
heroSprite.rotate(360 * (heroMover.previousX - getX())
/ ((float) Math.PI * heroSprite.getRegionHeight()));
setRotationAndScale();
// animation
stateTime += Gdx.graphics.getDeltaTime();
currentFireFrame = fireAnimation.getKeyFrame(stateTime, true);
fireEffect.setRegion(currentFireFrame);
currentSmokeFrame = smokeAnimation.getKeyFrame(stateTime, true);
smokeEffect.setRegion(currentSmokeFrame);
if (g.i().fire) {
countTime += Gdx.graphics.getDeltaTime();
if (countTime > 2) {
g.i().playerHealth -= 5;
getHurt();
countTime = 0;
}
}
if (g.i().playerHealth < 0) {
g.i().playerHealth = 0;
g.i().t.action("menu,gameOver");
}
}
/**
* tint player read for 60 frames if the player get hurt
*/
public void getHurt() {
frameCount = 60;
}
/**
* Change the ball type to the given type
*
* @param type
* - the ball type to change to
*/
public void changeBall(String type) {
switch (type) {
case Balls.BallPingPong:
g.i().playerFriction = 0.008f;
flammable = true;
ballWidth = 5.8f;
ballHeight = 5.8f;
ventRatio = 1f;
radius = 2.9f;
break;
case Balls.BallBowling:
g.i().playerFriction = 0.03f;
g.i().fire = false;
ballWidth = 30f;
ballHeight = 30f;
ventRatio = 0f;
radius = 15f;
flammable = false;
g.i().fire = false;
break;
case Balls.BallBasket:
g.i().playerFriction = 0.011f;
ballWidth = 30f;
ballHeight = 30f;
radius = 15f;
ventRatio = 0.3f;
flammable = true;
break;
case Balls.BallBase:
g.i().playerFriction = 0.008f;
ballWidth = 22.16f;
ballHeight = 22.16f;
radius = 11.08f;
ventRatio = 0.5f;
flammable = true;
break;
case Balls.BallTennis:
g.i().playerFriction = 0.008f;
ballWidth = 22.16f;
ballHeight = 22.16f;
radius = 11.08f;
ventRatio = 0.5f;
flammable = true;
break;
case Balls.BallBalloon:
g.i().playerFriction = 0.015f;
ballWidth = 30f;
ballHeight = 30f;
radius = 15f;
ventRatio = 1f;
flammable = true;
}
if (!g.i().fire) {
g.i().sound.fire(false);
}
heroSprite.setRegion(ballTypeMap.get(type));
g.i().currentBallType = type;
g.i().sound.setBounce();
baseColor = Color.WHITE;
heroSprite.setColor(Color.WHITE);
if (type.equalsIgnoreCase("Balloon")) {
randomTint();
}
setSpriteBounds();
calcualteDyInWater();
}
/**
* Ignited the ball or put out the fire
*
* @param fireOn
* - ignite the player if it is true put out the fire if it is
* false
*/
public void igniteBall(boolean fireOn) {
g.i().fire = fireOn;
if (!g.i().fire) {
g.i().sound.fire(false);
}
}
/**
* Change the ball's speed along x axis
*
* @param speed
* - the base speed
*/
public void changeBallX(float speed) {
if (ventRatio != 0)
heroMover.speedXPerSecond = speed * ventRatio;
}
/**
* Change the ball's speed along y axis
*
* @param speed
* - the base speed
*/
public void changeBallY(float speed) {
if (ventRatio != 0)
heroMover.speedYPerSecond = speed * ventRatio;
}
/**
* Get the current speed of the ball along y axis
*
* @return the current speed along y axis
*/
public float getYSpeed() {
return heroMover.speedYPerSecond;
}
/**
* Get the current speed of the ball along x axis
*
* @return the current speed along x axis
*/
public float getXSpeed() {
return heroMover.speedXPerSecond;
}
@Override
public void setPosition(float x, float y) {
setX(x);
setY(y);
camera.position.x = getX() + getWidth() / 2;
camera.position.y = getY() + getHeight() / 2;
if (camera.position.x - camera.viewportWidth / 2 < 0)
camera.position.x = camera.viewportWidth / 2;
else if (camera.position.x + camera.viewportWidth / 2 > tiledMapWrapper
.getPixelWidth())
camera.position.x = tiledMapWrapper.getPixelWidth()
- camera.viewportWidth / 2;
if (camera.position.x - camera.viewportWidth / 2 < 0)
camera.position.x = camera.viewportWidth / 2;
else if (camera.position.y + camera.viewportHeight > tiledMapWrapper
.getPixelHeight())
camera.position.y = tiledMapWrapper.getPixelHeight()
- camera.viewportHeight / 2;
}
/**
* return the center of the ball
*
* @return the center of the ball
*/
public Vector2 getCenter() {
Vector2 center = new Vector2(getX() + radius, getY() + radius);
return center;
}
// --------------Private helper
// method------------------------------------------
/**
* Set all sprites position based on actor's position
*/
private void setSpritesPosition() {
heroSprite.setX(getX());
heroSprite.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(Balls.BallBowling, tmp[0][0]);
ballTypeMap.put(Balls.BallBasket, tmp[1][0]);
ballTypeMap.put(Balls.BallPingPong, tmp[2][0]);
ballTypeMap.put(Balls.BallBase, tmp[4][0]);
ballTypeMap.put(Balls.BallBeach, tmp[5][0]);
ballTypeMap.put(Balls.BallMarble, tmp[6][0]);
ballTypeMap.put(Balls.BallSoccer, tmp[7][0]);
ballTypeMap.put(Balls.BallPool, tmp[8][0]);
ballTypeMap.put(Balls.BallTennis, tmp[9][0]);
ballTypeMap.put(Balls.BallGolf, tmp[10][0]);
ballTypeMap.put(Balls.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 (heroMover.speedXPerSecond == 0) {
if (heroMover.speedYPerSecond > 0)
fireEffect.setRotation((float) (-180));
else if (heroMover.speedYPerSecond < 0)
fireEffect.setRotation(0);
}
else if (heroMover.speedYPerSecond == 0) {
if (g.i().gameMode == 'R') {
if (heroMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (40 * Math
.atan(heroMover.speedXPerSecond / 200)));
else if (heroMover.speedXPerSecond < 0)
fireEffect.setRotation((float) (40 * Math
.atan(heroMover.speedXPerSecond / 200)));
} else {
if (heroMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90));
else if (heroMover.speedXPerSecond < 0)
fireEffect.setRotation((float) (-90));
}
}
else if (heroMover.speedXPerSecond * heroMover.speedYPerSecond > 0) {
if (heroMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90 + Math
.atan(heroMover.speedYPerSecond
/ heroMover.speedXPerSecond)
/ Math.PI * 180));
else
fireEffect.setRotation((float) (-(90 - Math
.atan(heroMover.speedYPerSecond
/ heroMover.speedXPerSecond)
/ Math.PI * 180)));
} else if (heroMover.speedXPerSecond * heroMover.speedYPerSecond < 0) {
if (heroMover.speedXPerSecond > 0)
fireEffect.setRotation((float) (90 + Math
.atan(heroMover.speedYPerSecond
/ heroMover.speedXPerSecond)
/ Math.PI * 180));
else
fireEffect.setRotation((float) (-90 + Math
.atan(heroMover.speedYPerSecond
/ heroMover.speedXPerSecond)
/ Math.PI * 180));
}
smokeEffect.setRotation(fireEffect.getRotation());
scaleFactor = Math.max((float) Math.hypot(heroMover.speedXPerSecond,
heroMover.speedYPerSecond) / 300, 1f);
fireEffect.setScale(1f, scaleFactor);
smokeEffect.setScale(1f, scaleFactor);
}
/**
* Set the bounds of the ball sprite
*/
private void setSpriteBounds() {
if (heroSprite != null) {
heroSprite.setBounds(0, 32, ballWidth * camera.zoom, ballHeight
* camera.zoom);
heroSprite.setOrigin(heroSprite.getWidth() / 2,
heroSprite.getHeight() / 2);
}
setHeight(heroSprite.getHeight() * camera.zoom);
setWidth(heroSprite.getWidth() * camera.zoom);
if (fireEffect != null) {
fireEffect.setBounds(0, 32, ballWidth * camera.zoom, ballHeight
* fireEffect.getHeight() / fireEffect.getWidth()
* camera.zoom);
fireEffect.setOrigin(heroSprite.getWidth() / 2,
heroSprite.getHeight() / 2);
}
if (smokeEffect != null) {
smokeEffect.setBounds(0, 32, ballWidth * camera.zoom, ballHeight
* smokeEffect.getHeight() / smokeEffect.getWidth()
* camera.zoom);
smokeEffect.setOrigin(heroSprite.getWidth() / 2,
heroSprite.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 (g.i().currentBallType) {
case Balls.BallPingPong:
mass = 0.0027f;
radius = 0.0200f;
break;
case Balls.BallBowling:
mass = 7.3000f;
radius = 0.0900f;
break;
case Balls.BallBasket:
mass = 2.6200f;
radius = 0.1210f;
break;
case Balls.BallBase:
mass = 0.1450f;
radius = 0.0382f;
break;
case Balls.BallTennis:
mass = 0.0600f;
radius = 0.0335f;
break;
case Balls.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;
g.i().playerdyInWater = dy;
}
/**
* Randomly tint the player.
*/
private void randomTint() {
baseColor = new Color(g.i().rnd.nextFloat(), g.i().rnd.nextFloat(),
g.i().rnd.nextFloat(), 1);
heroSprite.setColor(baseColor);
}
}