package com.shade.controls;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;
import com.shade.entities.Player;
import com.shade.entities.mushroom.Mushroom;
import com.shade.lighting.LuminousEntity;
import com.shade.states.MasterState;
/**
* A meter which can go from zero to a hundred. + The control should be notified
* whenever a mushroom is collected. + The control should + When the control
* reaches zero it will fire an event.
*
* @author aas11
*
*/
public class MeterControl implements ControlSlice, MushroomCounter {
public static final float BASE_DAMAGE = 0.02f;
public static final float BASE_EXPONENT = 1.0005f;
public static final float GOLD_SCORE_MULTIPLIER = 40;
public static final float SCORE_MULTIPLIER = 10;
public static final float HEALTH_MULTIPLIER = 1f;
public static final float BAR_MAX = 40f;
public static final float BASE_RECHARGE = BAR_MAX / 4000f; // max / 2 * sec
public static final float BONUS_SCALE = 1.5f;
private Player target;
private ControlListener listener;
private ScoreControl scorecard;
private float x, y;
private float value, totalAmountToAdd, rateOfChange;
private float totalDecrement;
private float totalTimeInSun;
private static Image front, back, danger, current;
private int timeInSun;
// bonus life
private float bonusMeter;
private int dangerTimer;
// metrics - we should get rid of these later
private float totalTimeInShade, totalTimeStanding, totalTimeRunning;
private int multiplier;
static {
try {
front = new Image("states/ingame/meter-front.png");
back = new Image("states/ingame/meter-back.png");
danger = new Image("states/ingame/meter-danger.png");
} catch (SlickException e) {
e.printStackTrace();
}
}
public MeterControl(float x, float y) throws SlickException {
this.x = x;
this.y = y;
value = 0;
totalAmountToAdd = 0;
rateOfChange = 1;
multiplier = 1;
initResources();
current = back;
}
private void initResources() throws SlickException {
}
public void track(LuminousEntity e) {
target = (Player) e;
}
public void register(ControlListener c) {
listener = c;
}
public void pass(ScoreControl card) {
scorecard = card;
}
public void render(StateBasedGame game, Graphics g) {
current.draw(x, y);
float w = front.getWidth();
float h = front.getHeight();
float adjustment = h - (h * (value / BAR_MAX));
front.draw(x, y + adjustment, x + w, y + h, 0, adjustment, w, h);
}
public void update(StateBasedGame game, int delta) {
if (bonusMeter > 0) {
scorecard.add(1);
bonusMeter--;
}
/**
* TODO: DELETE THIS LATER.
*
*/
if (!isMoving(target))
totalTimeStanding += delta;
else
totalTimeRunning += delta;
/*
if (target.isStunned()) {
if (value < BAR_MAX / 2) {
value += BASE_RECHARGE * delta;
}
totalAmountToAdd = 0;
timeInSun = 0;
return;
}*/
if (value == 0) {
// listener.fire(this);
target.stun();
totalAmountToAdd = BAR_MAX/2;
}
// System.out.println(value);
// if (value >= BAR_MAX&&bonusMeter<1) {
// // System.out.println("wowza");
// // not sure why this isn't player specific right now. It wil be form
// // now on.
// // TODO: if this shold go somewhere else tell me!
// target.setSpeed(Player.MAX_SPEED * BONUS_SCALE);
// target.sparkle();
// bonusMeter = BAR_MAX/35;
// } if(bonusMeter<1) {
// target.unsparkle();
// if (target.getSmokeCount() < timeInSun) {
// target.setSpeed((float) Math.max(0, value / BAR_MAX)
// * (Player.MAX_SPEED - Player.MIN_SPEED)
// + Player.MIN_SPEED);
// }
// }
// TODO: move this somwhere
// int scale = 60;
//System.out.println(target.getLuminosity());
if (target != null
&& target.getLuminosity() > MasterState.SHADOW_THRESHOLD*8) {
decrement(delta);
} else if (value < BAR_MAX / 2 && !isMoving(target)) {
timeInSun = 0;
totalTimeInShade += delta;
value += BASE_DAMAGE * 2;
// timeInSun = Math.max(timeInSun - delta, 0);
// if (target.getXVelocity() + target.getXVelocity() == 0)
// timeInSun *= 0.8;
}
if (totalAmountToAdd > 0) {
value += .1f * rateOfChange;
totalAmountToAdd -= .1f * rateOfChange;
} else {
rateOfChange = 1;
}
clamp();
target.setSpeed(Player.MIN_SPEED + (value / BAR_MAX)
* (Player.MAX_SPEED - Player.MIN_SPEED));
}
private boolean isMoving(Player p) {
return !(p.getXVelocity() == 0 && p.getYVelocity() == 0);
}
public void awardBonus() {
totalAmountToAdd += 20;
}
public void onCollect(Mushroom shroomie) {
if (target.isStunned()) {
return;
}
valueMushroom(shroomie);
if (totalAmountToAdd > 0) {
// rateOfChange++;
rateOfChange = 3;
}
}
private void clamp() {
if (value < 0) {
value = 0;
}
if ((int) value > BAR_MAX) {
bonusMeter += value - BAR_MAX;
value = BAR_MAX;
}
}
private void valueMushroom(Mushroom shroomie) {
totalAmountToAdd += shroomie.getValue() * HEALTH_MULTIPLIER
* multiplier;
if (shroomie.isGolden()) {
scorecard.add(shroomie.getValue() * GOLD_SCORE_MULTIPLIER * multiplier);
} else {
scorecard.add(shroomie.getValue() * SCORE_MULTIPLIER * multiplier);
}
multiplier = (shroomie.next == null) ? 1 : multiplier + 1;
}
private void decrement(int delta) {
totalTimeInSun += delta;
float damage = BASE_DAMAGE;
timeInSun += delta;
if (timeInSun > 3000) {
damage *= 7;
} else if (timeInSun > 1400) {
damage *= 2;
}
damage = damage*target.getLuminosity()/8;
bonusMeter -= damage;
if (bonusMeter < 1)
value -= damage;
clamp();
}
public float totalAmountLost() {
return totalDecrement;
}
public int totalTimeInSun() {
return ((int) totalTimeInSun / 1000);
}
/**
* test method TODO: DELETE
*/
// public String playerMetrics() {
// float totalTime = totalTimeInSun + totalTimeInShade;
// float totalruntime = totalTimeRunning + totalTimeStanding;
// return "Time in Sun: " + totalTimeInSun / totalTime
// + "\n Time in Shadow: " + totalTimeInShade / totalTime + "\n"
// + "Total time running " + totalTimeRunning / totalruntime
// + "\n Total time standing: " + totalTimeStanding / totalruntime;
// }
public void reset() {
value = BAR_MAX / 2;
totalAmountToAdd = 0;
rateOfChange = 1;
totalDecrement = 0;
totalTimeInSun = 0;
multiplier = 1;
// TODO: why is this so much casting?
// TODO: figure out how we SHOULD handle this issue. Mock players are
// the devil.
// try {
// Player p = (Player) target;
// p.setSmokeCount(0);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}