package com.igorcrevar.goingunder.scenes;
import java.util.ArrayList;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.igorcrevar.goingunder.GameData;
import com.igorcrevar.goingunder.GameManager;
import com.igorcrevar.goingunder.IActivityRequestHandler;
import com.igorcrevar.goingunder.ISceneManager;
import com.igorcrevar.goingunder.collision.CollisionResolver;
import com.igorcrevar.goingunder.objects.EndGameButtons;
import com.igorcrevar.goingunder.objects.IGameObject;
import com.igorcrevar.goingunder.objects.ParticleEffect;
import com.igorcrevar.goingunder.objects.PauseButtonObject;
import com.igorcrevar.goingunder.objects.Player;
import com.igorcrevar.goingunder.objects.obstacles.IObstaclePool;
import com.igorcrevar.goingunder.objects.obstacles.ObstacleObject;
import com.igorcrevar.goingunder.objects.obstacles.ObstaclePool;
import com.igorcrevar.goingunder.statemachine.IMyRandom;
import com.igorcrevar.goingunder.utils.GameHelper;
import com.igorcrevar.goingunder.utils.Mathf;
import com.igorcrevar.goingunder.utils.MyFontDrawer;
import com.igorcrevar.goingunder.utils.MyFontDrawerBatch;
import com.igorcrevar.goingunder.utils.MyFontDrawerDefaultFont;
public class GameScene implements IScene {
private Player player;
private GameData gameData = GameData.createDefault();
private IGameObject background;
private ParticleEffect particles;
private SpriteBatch spriteBatch = new SpriteBatch();
private ShapeRenderer shapeRenderer = new ShapeRenderer();
private IMyRandom myRandom;
private IObstaclePool obstaclePool;
private float additionalTimer;
private GameManager gameManager;
private CollisionResolver collisionResolver = new CollisionResolver();
// my font
private MyFontDrawerBatch myFontDrawerBatch = new MyFontDrawerBatch(new MyFontDrawerDefaultFont());
private MyFontDrawer myFontDrawer;
private IActivityRequestHandler activityRequestHandler;
// buttons
private EndGameButtons endGameButtons;
// this is just hack because we dont want to call saving of score/etc imediatelly when player dies
private boolean playerScoreUpdated;
// previous position of camera when obstacle is generated
private float prevCameraYWhenObstacleIsGenerated;
//
private PauseButtonObject pauseButton = new PauseButtonObject();
public GameScene(IMyRandom myRandom, IActivityRequestHandler activityRequestHandler) {
this.myRandom = myRandom;
this.activityRequestHandler = activityRequestHandler;
this.obstaclePool = new ObstaclePool(gameData);
}
@Override
public void create(ISceneManager sceneManager) {
this.gameManager = sceneManager.getGameManager();
player = gameManager.getPlayer();
background = gameManager.getBackground();
particles = new ParticleEffect(gameManager, player, gameData);
// my font
myFontDrawer = myFontDrawerBatch.addNew("Game Over",
gameManager.getTextureAtlas("game").findRegion("titlebubble"), 0, 0, 20, 40, 20, 0.00001f);
// buttons
endGameButtons = new EndGameButtons(sceneManager, activityRequestHandler, gameManager);
}
@Override
public void init(ISceneManager sceneManager) {
activityRequestHandler.showAds(false);
gameData.init(myRandom);
player.init(gameData);
background.init(gameData);
obstaclePool.init(gameData);
particles.init(gameData);
additionalTimer = 0.0f;
myRandom.reset();
gameManager.startGame();
playerScoreUpdated = false;
if (gameManager.getTotalScoreSum() <= 5) {
prevCameraYWhenObstacleIsGenerated = gameData.CameraYPosition - gameData.ObstacleGeneratorDistance * 0.1f;
}
else {
prevCameraYWhenObstacleIsGenerated = gameData.CameraYPosition + gameData.ObstacleGeneratorDistance * 0.8f;
}
pauseButton.init(gameManager);
}
@Override
public void update(ISceneManager sceneManager, float deltaTime) {
GameHelper.clearScreen();
if (gameManager.isGameActive()) {
if (pauseButton.isGameActive()) {
// update
update(deltaTime);
// obstacles generation
obstacleGeneration(deltaTime);
// detect collision
if (gameData.DieOnCollision && collisionResolver.detect(player, obstaclePool.getAllVisibles())) {
gameManager.finishGame();
}
}
else {
pauseButton.update(deltaTime);
}
}
else {
if (additionalTimer == 0.0f) {
gameManager.playDieSound();
activityRequestHandler.showAds(true);
}
// save score, call
if (additionalTimer > 0.8f && !playerScoreUpdated) {
playerScoreUpdated = true;
sceneManager.finishGame();
}
particles.setIsEnabled(false);
player.updateDie(additionalTimer, deltaTime);
additionalTimer += deltaTime;
}
// draw
draw(deltaTime);
}
@Override
public void leave(ISceneManager sceneManager) {
}
private void update(float deltaTime) {
background.update(deltaTime);
player.update(deltaTime);
particles.update(deltaTime);
ArrayList<ObstacleObject> obstacles = obstaclePool.getAllVisibles();
for (int i = obstacles.size() - 1; i >= 0; --i) {
ObstacleObject oo = obstacles.get(i);
float bottom = oo.getBottom();
// check if obstacle is passed by player (for the first time)
if (!oo.isPassed() && player.getY() < bottom) {
gameManager.addScore(1);
oo.markAsPassed();
// update level if needed
gameData.update(gameManager.getCurrentScore(), myRandom);
}
// obstacle is not on the screen anymore, mark it as free to use
if (bottom > gameData.getCameraTop()) {
oo.setIsEnabled(false);
}
}
// update camera pos also
gameData.CameraYPosition += deltaTime * gameData.VelocityY;
}
private void draw(float deltaTime) {
gameData.setProjectionMatrix(spriteBatch.getProjectionMatrix());
spriteBatch.begin();
// draw background
background.draw(spriteBatch);
// draw particles
particles.draw(spriteBatch);
// draw obstacles
ArrayList<ObstacleObject> obstacles = obstaclePool.getAllVisibles();
for (int i = obstacles.size() - 1; i >= 0; --i) {
obstacles.get(i).draw(spriteBatch);
}
// draw player
player.draw(spriteBatch);
spriteBatch.end();
// draw game over
if (!gameManager.isGameActive()) {
float initialY = 1920 + 400;
float endY = 860;
float cr = Mathf.lerp(initialY, endY, additionalTimer / 2.5f);
myFontDrawer.translate(50, cr + 400);
myFontDrawerBatch.draw();
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, 1080, 1920);
spriteBatch.begin();
BitmapFont font = gameManager.getBitmapFont();
font.setScale(1.0f);
cr += 50.0f;
font.setColor(Color.BLACK);
font.draw(spriteBatch, "Score", 455f, cr - 10.0f);
font.draw(spriteBatch, "Best", 505f, cr - 180.0f);
font.setColor(Color.ORANGE);
font.draw(spriteBatch, "Score", 450, cr);
font.draw(spriteBatch, "Best", 500, cr - 170);
String score = Integer.toString(gameManager.getCurrentScore());
String best = Integer.toString(gameManager.getTopScore());
float pos1X = 660 - font.getBounds(score).width;
float pos2X = 660 - font.getBounds(best).width;
font.setColor(Color.BLACK);
font.draw(spriteBatch, score, pos1X + 5.0f, cr - 95f);
font.draw(spriteBatch, best, pos2X + 5.0f, cr - 265f);
font.setColor(Color.WHITE);
font.draw(spriteBatch, score, pos1X, cr - 85f);
font.draw(spriteBatch, best, pos2X, cr - 255f);
spriteBatch.end();
// draw score
drawScore();
// draw buttons
if (additionalTimer >= gameData.getAdsPause(gameManager.getCurrentScore())) {
endGameButtons.draw(spriteBatch);
}
}
else {
drawScore();
gameData.setProjectionMatrix(shapeRenderer.getProjectionMatrix(), gameData.CameraYPosition);
// draw lights
player.drawLights(shapeRenderer, gameData);
// draw collision
if (gameData.DrawCollision) {
shapeRenderer.begin(ShapeType.Line);
collisionResolver.draw(shapeRenderer, gameData);
shapeRenderer.end();
}
}
}
private void drawScore() {
// draw text
float screenWidth = 1 / GameData.AspectRatio * 1920.0f;
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, screenWidth, 1920);
spriteBatch.begin();
BitmapFont font = gameManager.getBitmapFont();
// draw pause button and fonts (counting)
pauseButton.draw(font, spriteBatch);
// draw score
String score = Integer.toString(gameManager.getCurrentScore());
font.setScale(1.0f);
font.setColor(Color.BLACK);
float middlePos = screenWidth / 2.0f - font.getBounds(score).width / 2.0f;
font.draw(spriteBatch, score, middlePos + 5.0f, 1895);
font.setColor(Color.WHITE);
font.draw(spriteBatch, score, middlePos, 1905);
if (gameData.DrawFPS) {
font.draw(spriteBatch, "fps:" + Gdx.graphics.getFramesPerSecond(), 26, 65);
}
spriteBatch.end();
}
private void obstacleGeneration(float delta) {
// generate obstacles
if (-gameData.CameraYPosition + prevCameraYWhenObstacleIsGenerated >= gameData.ObstacleGeneratorDistance) {
obstaclePool.getOne(myRandom.getNext(), gameData, gameManager);
prevCameraYWhenObstacleIsGenerated = gameData.CameraYPosition;
}
}
@Override
public void processTouchDown(ISceneManager sceneManager, int x, int y) {
if (gameManager.isGameActive()) {
// first check if pause button is pressed and exit if it is
if (pauseButton.isTouched(gameData, x, y) || !pauseButton.isGameActive()) {
return;
}
gameManager.playMoveSound();
if (x > Gdx.graphics.getWidth() / 2) {
player.addVelocity(-gameData.VelocityX);
}
else {
player.addVelocity(gameData.VelocityX);
}
particles.addNew();
}
}
@Override
public void processTouchUp(ISceneManager sceneManager, int x, int y) {
if (additionalTimer >= gameData.getAdsPause(gameManager.getCurrentScore())) {
endGameButtons.check(gameData, x, y);
}
}
@Override
public void dispose(ISceneManager sceneManager) {
spriteBatch.dispose();
shapeRenderer.dispose();
myFontDrawerBatch.dispose();
}
}