package gr.sullenart.games.fruitcatcher.screens;
import gr.sullenart.games.fruitcatcher.FruitCatcherGame;
import gr.sullenart.games.fruitcatcher.images.ImageProvider;
import gr.sullenart.games.fruitcatcher.models.FallingObjectType;
import gr.sullenart.games.fruitcatcher.models.GameModel;
import gr.sullenart.games.fruitcatcher.models.GameModelFactory;
import gr.sullenart.games.fruitcatcher.sound.SoundManager;
import gr.sullenart.games.fruitcatcher.state.State;
import gr.sullenart.games.fruitcatcher.view.AnalogueClock;
import gr.sullenart.games.fruitcatcher.view.Basket;
import gr.sullenart.games.fruitcatcher.view.Button;
import gr.sullenart.games.fruitcatcher.view.EndGameMessage;
import gr.sullenart.games.fruitcatcher.view.FallingObject;
import gr.sullenart.games.fruitcatcher.view.FallingObjectFactory;
import gr.sullenart.games.fruitcatcher.view.FallingObjectState;
import gr.sullenart.games.fruitcatcher.view.NumberBoard;
import gr.sullenart.games.fruitcatcher.view.StartGameMessage;
import gr.sullenart.games.fruitcatcher.view.TimesTwoAnimation;
import java.util.Iterator;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
public class GameScreen implements Screen, InputProcessor {
private SpriteBatch batch;
private OrthographicCamera camera;
private FruitCatcherGame game;
private ImageProvider imageProvider;
private SoundManager soundManager;
private TextureRegion basketRegion;
private Texture backgroundImage;
private FallingObjectFactory fallingObjectFactory;
private Array<FallingObject> fallingObjects;
private Array<TimesTwoAnimation> timesTwoAnimations;
private int gameDuration;
private Basket basket;
private AnalogueClock clock;
private NumberBoard numberBoard;
private StartGameMessage startGameMessage;
private EndGameMessage endGameMessage;
private Button backButton;
private boolean tictacSoundPlaying;
private boolean gameFinishedSoundPlaying;
private int fruitPeriod;
private int badObjectsPeriod;
private int bonusObjectsPeriod;
private TextureRegion pauseTexture;
private int pauseX;
private int pauseY;
private GameModel gameModel;
private int season;
private int level;
private int challenge;
private int goal;
private GameScreenState st;
public GameScreen(FruitCatcherGame game, GameScreenState state) {
if (state != null) {
st = state;
}
else {
st = new GameScreenState();
resetState();
}
this.game = game;
}
private void resetState() {
st.score = 0;
st.startGameTime = 0;
st.isStarted= false;
st.isPaused = false;
st.fallingObjectStates = new Array<FallingObjectState>();
st.basketX = -1;
}
@Override
public void show() {
imageProvider = game.getImageProvider();
soundManager = game.getSoundManager();
camera = new OrthographicCamera();
camera.setToOrtho(false, imageProvider.getScreenWidth(),
imageProvider.getScreenHeight());
batch = new SpriteBatch();
basketRegion = imageProvider.getBasket();
basket = new Basket(imageProvider.getScreenWidth(), st.basketX);
fallingObjectFactory = new FallingObjectFactory(imageProvider);
timesTwoAnimations = new Array<TimesTwoAnimation>();
clock = new AnalogueClock(imageProvider);
numberBoard = new NumberBoard(imageProvider);
backButton = new Button(imageProvider.getBack());
backButton.setPos(10, 10);
pauseTexture = imageProvider.getPause();
pauseX = (imageProvider.getScreenWidth() - pauseTexture.getRegionWidth())/2;
pauseY = (imageProvider.getScreenHeight() - pauseTexture.getRegionHeight())/2;
initGame();
Gdx.input.setInputProcessor(this);
Gdx.input.setCatchBackKey(true);
}
private void initGame() {
level = challenge = goal = 0;
tictacSoundPlaying = false;
gameFinishedSoundPlaying = false;
endGameMessage = null;
gameDuration = (game.getGameModel().getDuration())/1000;
if (game.getGameState().isKidsMode()) {
season = MathUtils.random(0, 3);
goal = 0;
level = 0;
}
else {
level = game.getGameState().getLevel();
challenge = game.getGameState().getChallenge();
season = challenge % 4;
gameModel = game.getModel(level, challenge);
goal = gameModel.getGoal();
startGameMessage = new StartGameMessage(imageProvider, level,
challenge, goal);
}
switch(season) {
case 0:
backgroundImage = imageProvider.getBackgroundSpring();
break;
case 1:
backgroundImage = imageProvider.getBackgroundSummer();
break;
case 2:
backgroundImage = imageProvider.getBackgroundAutumn();
break;
case 3:
backgroundImage = imageProvider.getBackgroundWinter();
break;
}
fallingObjectFactory.setSeason(season);
fallingObjects = new Array<FallingObject>();
for(FallingObjectState foState: st.fallingObjectStates) {
FallingObject obj = fallingObjectFactory.getObjectFromState(foState);
fallingObjects.add(obj);
}
fruitPeriod = game.getGameModel().getFruitPeriod();
badObjectsPeriod = game.getGameModel().getBadObjectsPeriod();
bonusObjectsPeriod = game.getGameModel().getBonusObjectsPeriod();
if (game.getGameState().isKidsMode()) {
st.isStarted = true;
startGame();
}
}
private void spawnFruit() {
fallingObjects.add(fallingObjectFactory.getFruit());
st.lastFruitTime = TimeUtils.millis();
}
private void spawnBadApple() {
fallingObjects.add(fallingObjectFactory.getBadObject());
st.lastBadObjectTime = TimeUtils.millis();
}
private void spawnBonusItem() {
fallingObjects.add(fallingObjectFactory.getStar());
st.lastBonusItemTime = TimeUtils.millis();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
if (st.isStarted && !st.isPaused) {
int secondsElapsed = (int) ((TimeUtils.millis() - st.startGameTime)/1000);
st.secondsRemaining = gameDuration - secondsElapsed;
if (st.secondsRemaining < 0 || st.isFinished) {
st.secondsRemaining = 0;
}
}
else if (!st.isPaused){
st.secondsRemaining = gameDuration;
}
batch.begin();
batch.draw(backgroundImage, 0, 0);
if (!st.isStarted) {
startGameMessage.draw(batch);
}
else if (st.secondsRemaining > 0) {
batch.draw(basketRegion, basket.getPosition().x,
basket.getPosition().y);
for(FallingObject fallingObject: fallingObjects) {
fallingObject.draw(batch);
}
for(TimesTwoAnimation ta: timesTwoAnimations) {
ta.draw(batch);
}
clock.setSeconds(st.secondsRemaining);
clock.draw(batch, 5, imageProvider.getScreenHeight() - 65);
numberBoard.draw(batch, imageProvider.getScreenWidth()-5,
imageProvider.getScreenHeight()-5, st.score);
}
if (st.secondsRemaining == 0){
st.isFinished = true;
fallingObjects.clear();
if (endGameMessage == null) {
int unlockedLevel = 0;
int totalScore = game.getTotalScore() + st.score;
if (st.score >= goal && challenge == GameModelFactory.CHALLENGE_COUNT - 1) {
if (!State.isLevelUnlocked(level+1)) {
State.unLockLevel(level + 1);
unlockedLevel = level + 1;
}
}
else if (st.score < goal) {
game.endGame(totalScore);
}
endGameMessage = new EndGameMessage(imageProvider, level,
challenge, goal, st.score, totalScore, unlockedLevel);
}
endGameMessage.draw(batch);
backButton.draw(batch);
}
if (st.isPaused) {
batch.draw(pauseTexture, pauseX, pauseY);
}
batch.end();
if (!st.isPaused) {
if (st.secondsRemaining == 5 && !tictacSoundPlaying) {
tictacSoundPlaying = true;
soundManager.playTicTacSound();
}
else if (st.secondsRemaining == 0 && !gameFinishedSoundPlaying ) {
gameFinishedSoundPlaying = true;
if (st.score >= goal) {
soundManager.playDingDongSound();
}
else {
soundManager.playBellSound();
}
}
}
processInput();
if (st.isPaused) {
return;
}
if(st.isStarted && st.secondsRemaining > 0) {
if (TimeUtils.millis() - st.lastFruitTime > fruitPeriod) {
spawnFruit();
}
if (TimeUtils.millis() - st.lastBadObjectTime > badObjectsPeriod) {
spawnBadApple();
}
if (TimeUtils.millis() - st.lastBonusItemTime > bonusObjectsPeriod) {
spawnBonusItem();
}
}
// Update screen objects
Iterator<FallingObject> iter = fallingObjects.iterator();
while(iter.hasNext()) {
FallingObject fo = iter.next();
fo.moveDown(Gdx.graphics.getDeltaTime());
if(fo.isBottomOfScreen()) {
iter.remove();
}
if(fo.isOverlapping(basket.getPosition())) {
if (fo.getPoints() > 0) {
soundManager.playCatchSound();
}
else {
soundManager.playMissSound();
}
iter.remove();
st.score+=fo.getPoints();
if (fo.getState().getType() == FallingObjectType.SeasonalFruit) {
float x = basket.getPosition().x;
float y = basket.getPosition().y + 48;
timesTwoAnimations.add(
new TimesTwoAnimation(imageProvider, x, y));
}
}
}
Iterator<TimesTwoAnimation> itanim = timesTwoAnimations.iterator();
while(itanim.hasNext()) {
TimesTwoAnimation ta = itanim.next();
if (ta.isFinished(delta)) {
itanim.remove();
}
}
}
private void processInput() {
if (st.isStarted && !st.isPaused && st.secondsRemaining > 0) {
float delta = Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Keys.LEFT)) {
basket.moveX(-1, delta);
}
if(Gdx.input.isKeyPressed(Keys.RIGHT)) {
basket.moveX(1, delta);
}
basket.moveX(Gdx.input.getAccelerometerY(), delta);
}
}
@Override
public void resize(int width, int height) {
//this.width = width;
//this.height = height;
}
@Override
public void hide() {
}
@Override
public void pause() {
if (!st.isPaused && st.isStarted && st.secondsRemaining >= 0) {
st.isPaused = st.secondsRemaining > 0;
long pausedTime = TimeUtils.millis();
st.startGameTime -= pausedTime;
st.lastBadObjectTime -= pausedTime;
st.lastBonusItemTime -= pausedTime;
st.lastFruitTime -= pausedTime;
st.fallingObjectStates = new Array<FallingObjectState>();
for(FallingObject fo: fallingObjects) {
st.fallingObjectStates.add(fo.getState());
}
st.basketX = (int) basket.getPosition().x;
}
game.persist(st);
}
@Override
public void resume() {
if (st.isPaused) {
st.isPaused = false;
long now = TimeUtils.millis();
st.startGameTime += now;
st.lastBadObjectTime += now;
st.lastBonusItemTime += now;
st.lastFruitTime += now;
}
}
@Override
public void dispose() {
if (batch != null) {
batch.dispose();
}
}
@Override
public boolean keyDown(int keycode) {
if(keycode == Keys.BACK || keycode == Keys.BACKSPACE){
game.endGame(0);
game.gotoMenuScreen();
}
if(keycode == Keys.P) {
pause();
}
return true;
}
@Override
public boolean keyUp(int keycode) {
return false;
}
@Override
public boolean keyTyped(char character) {
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if (st.isStarted && !st.isPaused) {
Vector3 touchPos = new Vector3();
touchPos.set(screenX, screenY, 0);
camera.unproject(touchPos);
if (st.isStarted && st.secondsRemaining > 0) {
basket.setPositionX(touchPos.x);
}
}
return true;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (st.isPaused) {
resume();
return true;
}
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
if (!st.isStarted) {
st.isStarted = startGameMessage.isStartPressed(touchPos);
if (st.isStarted) {
startGame();
}
}
else if (st.secondsRemaining == 0) {
if (backButton.isPressed(touchPos)) {
game.endGame(0);
game.gotoMenuScreen();
}
else if (endGameMessage.isPressed(touchPos)) {
if (st.score >= goal) {
int totalScore = game.getTotalScore() + st.score;
game.setTotalScore(totalScore);
game.gotoNextGame();
}
else {
game.restartLevel();
}
resetState();
initGame();
}
}
return true;
}
private void startGame() {
st.isFinished = false;
st.startGameTime = TimeUtils.millis();
st.lastBadObjectTime = st.startGameTime;
st.lastBonusItemTime = st.startGameTime;
spawnFruit();
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (st.isStarted && !st.isPaused) {
Vector3 touchPos = new Vector3();
touchPos.set(screenX, screenY, 0);
camera.unproject(touchPos);
if (st.secondsRemaining > 0) {
basket.setPositionX(touchPos.x);
}
}
return true;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
@Override
public boolean scrolled(int amount) {
return false;
}
}