blob: 4e0243bc3170346465d2c67f29be1db6c21ba863 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.replica.replicaisland;
/**
* A very simple manager for orthographic in-game UI elements.
* TODO: This should probably manage a number of hud objects in keeping with the component-centric
* architecture of this engine. The current code is monolithic and should be refactored.
*/
public class HudSystem extends BaseObject {
private static final int FUEL_BAR_EDGE_PADDING = 15;
private static final float FUEL_DECREASE_BAR_SPEED = 0.75f;
private static final float FUEL_INCREASE_BAR_SPEED = 2.0f;
private static final float FLY_BUTTON_X = -12.0f;
private static final float FLY_BUTTON_Y = -5.0f;
private static final float STOMP_BUTTON_X = 85.0f;
private static final float STOMP_BUTTON_Y = -10.0f;
private static final float STOMP_BUTTON_SCALE = 0.65f;
private static final int COLLECTABLE_EDGE_PADDING = 8;
private static final int MAX_DIGITS = 4;
private static final float MOVEMENT_SLIDER_BASE_X = 20.0f;
private static final float MOVEMENT_SLIDER_BASE_Y = 32.0f;
private static final float MOVEMENT_SLIDER_BUTTON_X = MOVEMENT_SLIDER_BASE_X + 32.0f;
private static final float MOVEMENT_SLIDER_BUTTON_Y = MOVEMENT_SLIDER_BASE_Y - 16.0f;
private static final float FLY_BUTTON_WIDTH = 128;
private static final float STOMP_BUTTON_WIDTH = FLY_BUTTON_WIDTH * STOMP_BUTTON_SCALE;
private static final float MOVEMENT_SLIDER_WIDTH = 128;
private DrawableBitmap mFuelDrawable;
private DrawableBitmap mFuelBackgroundDrawable;
private float mFuelPercent;
private float mFuelTargetPercent;
private Texture mFadeTexture;
private float mFadeStartTime;
private float mFadeDuration;
private boolean mFadeIn;
private boolean mFading;
private int mFadePendingEventType;
private int mFadePendingEventIndex;
private DrawableBitmap mFlyButtonEnabledDrawable;
private DrawableBitmap mFlyButtonDisabledDrawable;
private DrawableBitmap mFlyButtonDepressedDrawable;
private DrawableBitmap mStompButtonEnabledDrawable;
private DrawableBitmap mStompButtonDepressedDrawable;
private DrawableBitmap mMovementSliderBaseDrawable;
private DrawableBitmap mMovementSliderButtonDrawable;
private DrawableBitmap mMovementSliderButtonDepressedDrawable;
private Vector2 mFlyButtonLocation;
private boolean mFlyButtonActive;
private boolean mFlyButtonPressed;
private Vector2 mStompButtonLocation;
private boolean mStompButtonPressed;
private Vector2 mMovementSliderBaseLocation;
private Vector2 mMovementSliderButtonLocation;
private boolean mMovementSliderMode;
private boolean mMovementSliderButtonPressed;
private DrawableBitmap mRubyDrawable;
private DrawableBitmap mCoinDrawable;
private int mCoinCount;
private int mRubyCount;
private Vector2 mCoinLocation;
private Vector2 mRubyLocation;
private int[] mCoinDigits;
private int[] mRubyDigits;
private boolean mCoinDigitsChanged;
private boolean mRubyDigitsChanged;
private int mFPS;
private Vector2 mFPSLocation;
private int[] mFPSDigits;
private boolean mFPSDigitsChanged;
private boolean mShowFPS;
private DrawableBitmap[] mDigitDrawables;
private DrawableBitmap mXDrawable;
public HudSystem() {
super();
mFlyButtonLocation = new Vector2();
mStompButtonLocation = new Vector2();
mCoinLocation = new Vector2();
mRubyLocation = new Vector2();
mFPSLocation = new Vector2();
mDigitDrawables = new DrawableBitmap[10];
mCoinDigits = new int[MAX_DIGITS];
mRubyDigits = new int[MAX_DIGITS];
mFPSDigits = new int[MAX_DIGITS];
mMovementSliderBaseLocation = new Vector2();
mMovementSliderButtonLocation = new Vector2();
reset();
}
@Override
public void reset() {
mFuelDrawable = null;
mFadeTexture = null;
mFuelPercent = 1.0f;
mFuelTargetPercent = 1.0f;
mFading = false;
mFlyButtonDisabledDrawable = null;
mFlyButtonEnabledDrawable = null;
mFlyButtonDepressedDrawable = null;
mFlyButtonLocation.set(FLY_BUTTON_X, FLY_BUTTON_Y);
mFlyButtonActive = true;
mFlyButtonPressed = false;
mStompButtonEnabledDrawable = null;
mStompButtonDepressedDrawable = null;
mStompButtonLocation.set(STOMP_BUTTON_X, STOMP_BUTTON_Y);
mStompButtonPressed = false;
mCoinCount = 0;
mRubyCount = 0;
mCoinDigits[0] = 0;
mCoinDigits[1] = -1;
mRubyDigits[0] = 0;
mRubyDigits[1] = -1;
mCoinDigitsChanged = true;
mRubyDigitsChanged = true;
mFPS = 0;
mFPSDigits[0] = 0;
mFPSDigits[1] = -1;
mFPSDigitsChanged = true;
mShowFPS = false;
for (int x = 0; x < mDigitDrawables.length; x++) {
mDigitDrawables[x] = null;
}
mXDrawable = null;
mFadePendingEventType = GameFlowEvent.EVENT_INVALID;
mFadePendingEventIndex = 0;
mMovementSliderBaseDrawable = null;
mMovementSliderButtonDrawable = null;
mMovementSliderButtonDepressedDrawable = null;
mMovementSliderBaseLocation.set(MOVEMENT_SLIDER_BASE_X, MOVEMENT_SLIDER_BASE_Y);
mMovementSliderButtonLocation.set(MOVEMENT_SLIDER_BUTTON_X, MOVEMENT_SLIDER_BUTTON_Y);
mMovementSliderMode = false;
mMovementSliderButtonPressed = false;
}
public void setFuelPercent(float percent) {
mFuelTargetPercent = percent;
}
public void setFuelDrawable(DrawableBitmap fuel, DrawableBitmap background) {
mFuelDrawable = fuel;
mFuelBackgroundDrawable = background;
}
public void setFadeTexture(Texture texture) {
mFadeTexture = texture;
}
public void setButtonDrawables(DrawableBitmap disabled, DrawableBitmap enabled, DrawableBitmap depressed,
DrawableBitmap stompEnabled, DrawableBitmap stompDepressed,
DrawableBitmap sliderBase, DrawableBitmap sliderButton, DrawableBitmap sliderDepressed) {
mFlyButtonDisabledDrawable = disabled;
mFlyButtonEnabledDrawable = enabled;
mFlyButtonDepressedDrawable = depressed;
mStompButtonEnabledDrawable = stompEnabled;
mStompButtonDepressedDrawable = stompDepressed;
mMovementSliderBaseDrawable = sliderBase;
mMovementSliderButtonDrawable = sliderButton;
mMovementSliderButtonDepressedDrawable = sliderDepressed;
}
public void setDigitDrawables(DrawableBitmap[] digits, DrawableBitmap xMark) {
mXDrawable = xMark;
for (int x = 0; x < mDigitDrawables.length && x < digits.length; x++) {
mDigitDrawables[x] = digits[x];
}
}
public void setCollectableDrawables(DrawableBitmap coin, DrawableBitmap ruby) {
mCoinDrawable = coin;
mRubyDrawable = ruby;
}
public void setButtonState(boolean pressed, boolean attackPressed, boolean sliderPressed) {
mFlyButtonPressed = pressed;
mStompButtonPressed = attackPressed;
mMovementSliderButtonPressed = sliderPressed;
}
public void startFade(boolean in, float duration) {
mFadeStartTime = sSystemRegistry.timeSystem.getRealTime();
mFadeDuration = duration;
mFadeIn = in;
mFading = true;
}
public void clearFade() {
mFading = false;
}
public boolean isFading() {
return mFading;
}
public void updateInventory(InventoryComponent.UpdateRecord newInventory) {
mCoinDigitsChanged = (mCoinCount != newInventory.coinCount);
mRubyDigitsChanged = (mRubyCount != newInventory.rubyCount);
mCoinCount = newInventory.coinCount;
mRubyCount = newInventory.rubyCount;
}
public void setFPS(int fps) {
mFPSDigitsChanged = (fps != mFPS);
mFPS = fps;
}
public void setShowFPS(boolean show) {
mShowFPS = show;
}
public void setMovementSliderMode(boolean sliderOn) {
mMovementSliderMode = sliderOn;
if (sliderOn) {
ContextParameters params = sSystemRegistry.contextParameters;
mFlyButtonLocation.set(params.gameWidth - FLY_BUTTON_WIDTH - FLY_BUTTON_X, FLY_BUTTON_Y);
mStompButtonLocation.set(params.gameWidth - STOMP_BUTTON_WIDTH - STOMP_BUTTON_X, STOMP_BUTTON_Y);
} else {
mFlyButtonLocation.set(FLY_BUTTON_X, FLY_BUTTON_Y);
mStompButtonLocation.set(STOMP_BUTTON_X, STOMP_BUTTON_Y);
}
}
public void setMovementSliderOffset(float offset) {
mMovementSliderButtonLocation.set(MOVEMENT_SLIDER_BUTTON_X + (offset * (MOVEMENT_SLIDER_WIDTH / 2.0f)), MOVEMENT_SLIDER_BUTTON_Y);
}
@Override
public void update(float timeDelta, BaseObject parent) {
final RenderSystem render = sSystemRegistry.renderSystem;
final VectorPool pool = sSystemRegistry.vectorPool;
final ContextParameters params = sSystemRegistry.contextParameters;
final DrawableFactory factory = sSystemRegistry.drawableFactory;
final GameObjectManager manager = sSystemRegistry.gameObjectManager;
if (manager != null && manager.getPlayer() != null) {
// Only draw player-specific HUD elements when there's a player.
if (mFuelDrawable != null && mFuelBackgroundDrawable != null
&& render != null && pool != null && factory != null && params != null) {
if (mFuelPercent < mFuelTargetPercent) {
mFuelPercent += (FUEL_INCREASE_BAR_SPEED * timeDelta);
if (mFuelPercent > mFuelTargetPercent) {
mFuelPercent = mFuelTargetPercent;
}
} else if (mFuelPercent > mFuelTargetPercent) {
mFuelPercent -= (FUEL_DECREASE_BAR_SPEED * timeDelta);
if (mFuelPercent < mFuelTargetPercent) {
mFuelPercent = mFuelTargetPercent;
}
}
if (mFuelBackgroundDrawable.getWidth() == 0) {
// first time init
Texture tex = mFuelDrawable.getTexture();
mFuelDrawable.resize(tex.width, tex.height);
Texture backgroundTex = mFuelBackgroundDrawable.getTexture();
mFuelBackgroundDrawable.resize(backgroundTex.width, backgroundTex.height);
}
final int height = mFuelDrawable.getHeight();
Vector2 location = pool.allocate();
location.set(FUEL_BAR_EDGE_PADDING,
params.gameHeight - height - FUEL_BAR_EDGE_PADDING);
render.scheduleForDraw(mFuelBackgroundDrawable, location, SortConstants.HUD, false);
location.x += 2;
location.y += 2;
final int barWidth = (int)((100 - 4) * mFuelPercent);
if (barWidth >= 1) {
DrawableBitmap bitmap = factory.allocateDrawableBitmap();
if (bitmap != null) {
bitmap.resize(barWidth, mFuelDrawable.getHeight());
bitmap.setTexture(mFuelDrawable.getTexture());
render.scheduleForDraw(bitmap, location, SortConstants.HUD + 1, false);
}
}
pool.release(location);
}
if (mFlyButtonDisabledDrawable != null && mFlyButtonEnabledDrawable != null
&& mFlyButtonDepressedDrawable != null) {
DrawableBitmap bitmap = mFlyButtonEnabledDrawable;
if (mFlyButtonActive && mFlyButtonPressed) {
bitmap = mFlyButtonDepressedDrawable;
} else if (!mFlyButtonActive) {
bitmap = mFlyButtonDisabledDrawable;
}
if (bitmap.getWidth() == 0) {
// first time init
Texture tex = bitmap.getTexture();
bitmap.resize(tex.width, tex.height);
}
render.scheduleForDraw(bitmap, mFlyButtonLocation, SortConstants.HUD, false);
}
if (mStompButtonEnabledDrawable != null && mStompButtonDepressedDrawable != null) {
DrawableBitmap bitmap = mStompButtonEnabledDrawable;
if (mStompButtonPressed) {
bitmap = mStompButtonDepressedDrawable;
}
if (bitmap.getWidth() == 0) {
// first time init
Texture tex = bitmap.getTexture();
bitmap.resize(tex.width, tex.height);
bitmap.setWidth((int)(tex.width * STOMP_BUTTON_SCALE));
bitmap.setHeight((int)(tex.height * STOMP_BUTTON_SCALE));
}
render.scheduleForDraw(bitmap, mStompButtonLocation, SortConstants.HUD, false);
}
if (mMovementSliderMode &&
mMovementSliderBaseDrawable != null && mMovementSliderButtonDrawable != null) {
if (mMovementSliderBaseDrawable.getWidth() == 0) {
// first time init
Texture tex = mMovementSliderBaseDrawable.getTexture();
mMovementSliderBaseDrawable.resize(tex.width, tex.height);
}
if (mMovementSliderButtonDrawable.getWidth() == 0) {
// first time init
Texture tex = mMovementSliderButtonDrawable.getTexture();
mMovementSliderButtonDrawable.resize(tex.width, tex.height);
}
if (mMovementSliderButtonDepressedDrawable.getWidth() == 0) {
// first time init
Texture tex = mMovementSliderButtonDepressedDrawable.getTexture();
mMovementSliderButtonDepressedDrawable.resize(tex.width, tex.height);
}
DrawableBitmap bitmap = mMovementSliderButtonDrawable;
if (mMovementSliderButtonPressed) {
bitmap = mMovementSliderButtonDepressedDrawable;
}
render.scheduleForDraw(mMovementSliderBaseDrawable, mMovementSliderBaseLocation, SortConstants.HUD, false);
render.scheduleForDraw(bitmap, mMovementSliderButtonLocation, SortConstants.HUD + 1, false);
}
if (mCoinDrawable != null) {
if (mCoinDrawable.getWidth() == 0) {
// first time init
Texture tex = mCoinDrawable.getTexture();
mCoinDrawable.resize(tex.width, tex.height);
mCoinLocation.x = (params.gameWidth / 2.0f) - tex.width / 2.0f;
mCoinLocation.y = params.gameHeight - tex.height - COLLECTABLE_EDGE_PADDING;
}
render.scheduleForDraw(mCoinDrawable, mCoinLocation, SortConstants.HUD, false);
if (mCoinDigitsChanged) {
intToDigitArray(mCoinCount, mCoinDigits);
mCoinDigitsChanged = false;
}
final float offset = mCoinDrawable.getWidth() * 0.75f;
mCoinLocation.x += offset;
drawNumber(mCoinLocation, mCoinDigits, true);
mCoinLocation.x -= offset;
}
if (mRubyDrawable != null) {
if (mRubyDrawable.getWidth() == 0) {
// first time init
Texture tex = mRubyDrawable.getTexture();
mRubyDrawable.resize(tex.width, tex.height);
mRubyLocation.x = (params.gameWidth / 2.0f) + 100.0f;
mRubyLocation.y = params.gameHeight - tex.height - COLLECTABLE_EDGE_PADDING;
}
render.scheduleForDraw(mRubyDrawable, mRubyLocation, SortConstants.HUD, false);
if (mRubyDigitsChanged) {
intToDigitArray(mRubyCount, mRubyDigits);
mRubyDigitsChanged = false;
}
final float offset = mRubyDrawable.getWidth() * 0.75f;
mRubyLocation.x += offset;
drawNumber(mRubyLocation, mRubyDigits, true);
mRubyLocation.x -= offset;
}
}
if (mShowFPS) {
if (mFPSDigitsChanged) {
int count = intToDigitArray(mFPS, mFPSDigits);
mFPSDigitsChanged = false;
mFPSLocation.set(params.gameWidth - 10.0f - ((count + 1) * (mDigitDrawables[0].getWidth() / 2.0f)), 10.0f);
}
drawNumber(mFPSLocation, mFPSDigits, false);
}
if (mFading && factory != null) {
final float time = sSystemRegistry.timeSystem.getRealTime();
final float fadeDelta = (time - mFadeStartTime);
float percentComplete = 1.0f;
if (fadeDelta < mFadeDuration) {
percentComplete = fadeDelta / mFadeDuration;
} else if (mFadeIn) {
// We've faded in. Turn fading off.
mFading = false;
}
if (percentComplete < 1.0f || !mFadeIn) {
float opacityValue = percentComplete;
if (mFadeIn) {
opacityValue = 1.0f - percentComplete;
}
DrawableBitmap bitmap = factory.allocateDrawableBitmap();
if (bitmap != null) {
bitmap.setWidth(params.gameWidth);
bitmap.setHeight(params.gameHeight);
bitmap.setTexture(mFadeTexture);
bitmap.setCrop(0, mFadeTexture.height, mFadeTexture.width, mFadeTexture.height);
bitmap.setOpacity(opacityValue);
render.scheduleForDraw(bitmap, Vector2.ZERO, SortConstants.FADE, false);
}
}
if (percentComplete >= 1.0f && mFadePendingEventType != GameFlowEvent.EVENT_INVALID) {
LevelSystem level = sSystemRegistry.levelSystem;
if (level != null) {
level.sendGameEvent(mFadePendingEventType, mFadePendingEventIndex, false);
mFadePendingEventType = GameFlowEvent.EVENT_INVALID;
mFadePendingEventIndex = 0;
}
}
}
}
private void drawNumber(Vector2 location, int[] digits, boolean drawX) {
final RenderSystem render = sSystemRegistry.renderSystem;
if (mDigitDrawables[0].getWidth() == 0) {
// first time init
for (int x = 0; x < mDigitDrawables.length; x++) {
Texture tex = mDigitDrawables[x].getTexture();
mDigitDrawables[x].resize(tex.width, tex.height);
}
}
if (mXDrawable.getWidth() == 0) {
// first time init
Texture tex = mXDrawable.getTexture();
mXDrawable.resize(tex.width, tex.height);
}
final float characterWidth = mDigitDrawables[0].getWidth() / 2.0f;
float offset = 0.0f;
if (mXDrawable != null && drawX) {
render.scheduleForDraw(mXDrawable, location, SortConstants.HUD, false);
location.x += characterWidth;
offset += characterWidth;
}
for (int x = 0; x < digits.length && digits[x] != -1; x++) {
int index = digits[x];
DrawableBitmap digit = mDigitDrawables[index];
if (digit != null) {
render.scheduleForDraw(digit, location, SortConstants.HUD, false);
location.x += characterWidth;
offset += characterWidth;
}
}
location.x -= offset;
}
public int intToDigitArray(int value, int[] digits) {
int characterCount = 1;
if (value >= 1000) {
characterCount = 4;
} else if (value >= 100) {
characterCount = 3;
} else if (value >= 10) {
characterCount = 2;
}
int remainingValue = value;
int count = 0;
do {
int index = remainingValue != 0 ? remainingValue % 10 : 0;
remainingValue /= 10;
digits[characterCount - 1 - count] = index;
count++;
} while (remainingValue > 0 && count < digits.length);
if (count < digits.length) {
digits[count] = -1;
}
return characterCount;
}
public void sendGameEventOnFadeComplete(int eventType, int eventIndex) {
mFadePendingEventType = eventType;
mFadePendingEventIndex = eventIndex;
}
}