package com.gebauz.bauzoid.game;
import java.util.Random;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.gebauz.bauzoid.app.BauzoidApp;
import com.gebauz.bauzoid.app.Consts;
import com.gebauz.bauzoid.app.CustomServices;
import com.gebauz.bauzoid.app.Settings;
import com.gebauz.bauzoid.audio.Audio;
import com.gebauz.bauzoid.gamestates.GameStateManager;
import com.gebauz.bauzoid.graphics.Font;
import com.gebauz.bauzoid.graphics.FontCollection;
import com.gebauz.bauzoid.graphics.Graphics;
import com.gebauz.bauzoid.graphics.spritex.AtlasDefinition;
import com.gebauz.bauzoid.graphics.spritex.AtlasSpriteAsyncLoader;
import com.gebauz.bauzoid.graphics.sprite.SpriteRegionDefinition;
import com.gebauz.bauzoid.graphics.sprite.SpriteRegionAsyncLoader;
import com.gebauz.bauzoid.input.Input;
/** Root object for the game. Manages game-global objects, acts as the root of the game graph, and kicks off update and render calls.
*
* This is the parent class for the following subsystems:
* - GameStateManager: Root object for game states.
* - Graphics: Root object for all graphics objects
* - Audio: Root object for all audio objects
* - ..
*
* It also offers convenient access to the Android application's Context
*
* It is implemented as a Generic, with T being the concrete implementation fo the CustomServices class for the app.
*/
public class Game
{
// Embedded Types=======================================================================================
/** Toggles debug mode and stepping mode - however, the client app must implement these functionalities. */
public class BauzoidInputProcessor
extends InputAdapter
{
@
Override
public boolean keyDown
(int keycode
)
{
/* switch (keycode)
{
case com.badlogic.gdx.Input.Keys.BACK:
case com.badlogic.gdx.Input.Keys.D:
// toggle debug info
mEnableDebugInfo = !mEnableDebugInfo;
break;
case com.badlogic.gdx.Input.Keys.P:
// toggle debug pause mode
mEnableDebugStepperMode = !mEnableDebugStepperMode;
break;
case com.badlogic.gdx.Input.Keys.S:
// allow one step
mAllowStep = true;
break;
}*/
return false;
}
}
/** Interface to allow client apps to override aspects of the game. */
public static interface IGameFactory
{
public abstract Input createInput
(Game game
);
public abstract Graphics createGraphics
(Game game
);
public abstract Audio createAudio
(Game game
);
public abstract FontCollection createFontCollection
(Game game
);
}
public static class DefaultGameFactory
implements IGameFactory
{
@
Override
public Input createInput
(Game game
)
{
return new Input
(game
);
}
@
Override
public Graphics createGraphics
(Game game
)
{
return new Graphics(game
);
}
@
Override
public Audio createAudio
(Game game
)
{
return new Audio
(game
);
}
@
Override
public FontCollection createFontCollection
(Game game
)
{
return new FontCollection
(game
);
}
}
// Fields===============================================================================================
private BauzoidApp mApp =
null;
private String mGameTitle =
"BauzoidGame";
private boolean mAdsEnabled =
false;
private GameStateManager mGameStateManager =
null;
private Graphics mGraphics =
null;
private Audio mAudio =
null;
private Input mInput =
null;
private FontCollection mFonts =
null;
private final long mRandomSeed =
System.
currentTimeMillis();
//private final long mRandomSeed = 1367274339256L;
private Random mRandomizer =
new Random(mRandomSeed
);
private AssetManager mAssetManager =
null;
private Settings mSettings =
null;
private CustomServices mCustomServices =
null;
/** When true, allows game components to display debug information. */
private boolean mEnableDebugInfo =
false;
private boolean mEnableDebugStepperMode =
false;
private boolean mAllowStep =
false;
private long mPreviousTime =
0;
private int mFrameCount =
0;
private float mFps = 0.0f
;
private float mRunTime = 0.0f
;
private float mDeltaTime = 0.0f
;
private IGameFactory mGameFactory =
new DefaultGameFactory
();
// Methods==============================================================================================
/** Constructor. */
public Game
(BauzoidApp app,
String title,
boolean adsEnabled, IGameFactory gameFactory
)
{
Gdx.
app.
log(Consts.
LOG_TAG,
"Seed Used: " + mRandomSeed
);
mApp = app
;
// Set the context to use for engine exceptions
mGameTitle = title
;
mAdsEnabled = adsEnabled
;
mGameStateManager =
new GameStateManager
(this);
if (gameFactory
!=
null)
mGameFactory = gameFactory
;
mGraphics = mGameFactory.
createGraphics(this);
mAudio = mGameFactory.
createAudio(this);
mInput = mGameFactory.
createInput(this);
mFonts = mGameFactory.
createFontCollection(this);
mSettings =
new Settings
();
mAssetManager =
new AssetManager
();
mPreviousTime = mApp.
getSystemTimeMs();
Gdx.
input.
setCatchBackKey(true);
// install asynchronous loaders
mAssetManager.
setLoader(AtlasDefinition.
class,
new AtlasSpriteAsyncLoader
(new InternalFileHandleResolver
()));
mAssetManager.
setLoader(SpriteRegionDefinition.
class,
new SpriteRegionAsyncLoader
(new InternalFileHandleResolver
()));
}
/** Called for game-global initialization. */
public void init
()
{
mGraphics.
init();
mAudio.
init();
mInput.
init();
mFonts.
init();
mGameStateManager.
init();
mSettings.
loadSettings(Gdx.
files.
internal("data/config.txt"));
Gdx.
input.
setInputProcessor(new BauzoidInputProcessor
());
}
/** Called for game-global destruction. */
public void exit
()
{
mGameStateManager.
exit();
mFonts.
exit();
mInput.
exit();
mAudio.
exit();
mGraphics.
exit();
if (mCustomServices
!=
null)
{
mCustomServices.
exit();
mCustomServices =
null;
}
if (mAssetManager
!=
null)
{
mAssetManager.
dispose();
mAssetManager =
null;
}
}
/** Update game logic state. */
public void update
(float deltaTime
)
{
mDeltaTime = deltaTime
;
mRunTime += deltaTime
;
if (mCustomServices
!=
null)
{
mCustomServices.
update(deltaTime
);
}
mGameStateManager.
update(deltaTime
);
mAudio.
update(deltaTime
);
mInput.
update(deltaTime
);
updateFps
(deltaTime
);
mAllowStep =
false;
}
/** Update the internal timer so that the next deltaTime won't be too large. This is used for instance during GameState initialization when init() could take a long time. */
public void updateInternalTimer
()
{
mDeltaTime = mApp.
updateInternalTimer();
mRunTime += mDeltaTime
;
}
public void updateFps
(float deltaTime
)
{
long currentTime = getCurrentTimeMs
();
long timeInterval = currentTime - mPreviousTime
;
if(timeInterval
> 1000)
{
// calculate the number of frames per second
mFps = mFrameCount /
(timeInterval / 1000.0f
);
mPreviousTime = currentTime
;
mFrameCount =
0;
}
}
/** Render game. */
public void render
()
{
if (mCustomServices
!=
null)
{
mCustomServices.
render();
}
mGameStateManager.
render();
mAudio.
render();
mInput.
render();
mFrameCount++
;
}
/** Called when the surface dimensions have changed. */
public void resize
(int w,
int h
)
{
mGraphics.
updateSurfaceDimensions(w, h
);
mInput.
updateSurfaceDimensions(w, h
);
mGameStateManager.
onSurfaceChanged(w, h
);
}
/** Called when the OpenGL Context is about to be destroyed. */
public void pause
()
{
mGraphics.
onSurfaceLost();
mAudio.
onPause();
mInput.
onPause();
mGameStateManager.
onPause();
}
/** Called when the OpenGL Context has been recreated after onSurfaceLost(). */
public void resume
()
{
mGraphics.
onSurfaceRecreated();
mAudio.
onResume();
mInput.
onResume();
mGameStateManager.
onResume();
}
/** Install an app specific custom services. */
public final void setCustomServices
(CustomServices customServices
)
{
if (mCustomServices
!=
null)
mCustomServices.
exit();
mCustomServices = customServices
;
if (mCustomServices
!=
null)
mCustomServices.
init();
}
public float getRandomFloat
(float min,
float max
)
{
return min + mRandomizer.
nextFloat() * (max-min
);
}
public int getRandomInt
(int min,
int max
)
{
return min + mRandomizer.
nextInt(max-min+
1);
}
/** Returns -1 or 1 with a 50:50 chance. */
public int getRandomSign
()
{
int n = getRandomInt
(0,
1);
if (n ==
1)
return -
1;
return 1;
}
public void showAds
(boolean visible
)
{
mApp.
showAds(visible
);
}
// Getters/Setters==================================================================================
/** Get the main graphics object. */
public final Graphics getGraphics
() { return mGraphics
; }
/** Get the main audio object. */
public final Audio getAudio
() { return mAudio
; }
/** Get the main input object. */
public final Input getInput
() { return mInput
; }
/** Get the font collection. */
public final FontCollection getFonts
() { return mFonts
; }
/** Get a specific font. */
public final Font getFont
(String name
) { return mFonts.
getFont(name
); }
/** Get the app specific custom services. */
public final CustomServices getCustomServices
() { return mCustomServices
; }
/** Get the GameStateManager. */
public final GameStateManager getGameStateManager
() { return mGameStateManager
; }
/** Get the Randomizer. */
public Random getRandomizer
() { return mRandomizer
; }
/** Get the AssetManager. */
public AssetManager getAssetManager
() { return mAssetManager
; }
/** Get the Game Title. */
public final String getGameTitle
() { return mGameTitle
; }
/** Check if ads are enabled. */
public final boolean areAdsEnabled
() { return mAdsEnabled
; }
/** Set a settings object. */
public final void setSettings
(Settings settings
) { mSettings = settings
; }
/** Get the settings object. */
public final Settings getSettings
() { return mSettings
; }
/** Get the current system time in milliseconds. */
public final long getCurrentTimeMs
() { return mApp.
getSystemTimeMs(); }
/** Get the time the game has run in seconds. Useful for sine/cosine stuffs and animating. */
public final float getTime
() { return mRunTime
; }
/** Get the frames per second. */
public final float getFps
() { return mFps
; }
/** Get seconds per frame. */
public final float getFrameTime
()
{
if (mFps == 0.0f
)
return 0.0f
;
return (1/mFps
);
}
/** Get the last frame's delta time. */
public final float getDeltaTime
() { return mDeltaTime
; }
public boolean isDebugInfoEnabled
() { return mEnableDebugInfo
; }
public void enableDebugInfo
(boolean enableDebugInfo
) { mEnableDebugInfo = enableDebugInfo
; }
public boolean isDebugStepperModeEnabled
() { return mEnableDebugStepperMode
; }
public boolean stepNextFrame
() { return mAllowStep
; }
}