package com.zozotintin.dodgydot;
import java.util.ArrayDeque;
import java.util.Queue;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.EdgeShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
class GameScreen extends GameSample implements Configuration, ContactListener {
static final int GAME_READY_SETUP = 6;
static final int GAME_READY = 0;
static final int GAME_RUNNING = 1;
static final int GAME_PAUSED = 2;
static final int GAME_OVER = 3;
static final int GAME_OVER_SETUP = 4;
static final int BALL_DESTROYED = 5;
int state;
boolean gameOverSetup;
World world;
Stage stage;
final short CATEGORY_PLAYER = 0x0001;
final short CATEGORY_ENEMY = 0x0002;
final short CATEGORY_WALL = 0x0004;
final short MASK_PLAYER = ~CATEGORY_PLAYER;
final short MASK_ENEMY = ~CATEGORY_ENEMY & ~CATEGORY_WALL;
final short MASK_WALL = -1;
float timeGap = 0;
float playTime = 0;
DodgyDot game;
private static OrthographicCamera camera, cameraHUD;
private static Viewport viewport, viewportHUD;
//Logger logger = new Logger("DEBUG", Logger.INFO);
Vector3 point = new Vector3();
//Vector2 pos = new Vector2();
CircleShape ballShape;
PolygonShape squareShape;
Queue<Enemy> enemies = new ArrayDeque<Enemy>();
Body wall;
Player player;
Retry retry;
Background background;
LeftPrompt leftPrompt;
RightPrompt rightPrompt;
Label scoreLabel;
Label highScoreLabel;
public GameScreen (DodgyDot game) {
this.game = game;
world = new World(new Vector2(0, -GRAVITY), true);
camera = new OrthographicCamera();
viewport = new FitViewport(SCREEN_WIDTH, SCREEN_HEIGHT, camera);
camera.translate(new Vector2(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2));
//camera.zoom = 4f; camera.position.y = -10;
camera.update();
cameraHUD = new OrthographicCamera();
viewportHUD = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, cameraHUD);
stage = new Stage(viewportHUD, game.batch);
scoreLabel = new Label(Integer.toString((int) playTime), game.labelStyle);
stage.addActor(scoreLabel);
scoreLabel.setFontScale(1.5f);
scoreLabel.setPosition(VIRTUAL_WIDTH - scoreLabel.getWidth(), VIRTUAL_HEIGHT - scoreLabel.getHeight());
scoreLabel.setAlignment(Align.right);
state = GAME_READY_SETUP;
gameOverSetup = false;
squareShape = new PolygonShape();
squareShape.setAsBox(SQUARE_WIDTH / 2, SQUARE_WIDTH / 2);
background = new Background();
player = new Player(Assets.ball, RETRY_X , RETRY_Y);
leftPrompt = new LeftPrompt();
rightPrompt = new RightPrompt();
stage.addActor(background);
background.setZIndex(0);
stage.addActor(leftPrompt);
stage.addActor(rightPrompt);
stage.addActor(player);
player.setZIndex(40);
createWall();
Gdx.input.setInputProcessor(this);
world.setContactListener(this);
}
private void createWall () {
BodyDef wallD = new BodyDef();
wallD.type = BodyType.KinematicBody;
wall = world.createBody(wallD);
EdgeShape edge1 = new EdgeShape();
edge1.set(0.0f, -5.0f, 0.0f, SCREEN_HEIGHT);
EdgeShape edge2 = new EdgeShape();
edge2.set(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
EdgeShape edge3 = new EdgeShape();
edge3.set(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, -5.0f);
EdgeShape edge4 = new EdgeShape();
edge4.set(0.0f, -BALL_WIDTH, SCREEN_WIDTH, -BALL_WIDTH);
FixtureDef wallFD = new FixtureDef();
wallFD.shape = edge1;
wallFD.filter.categoryBits = CATEGORY_WALL;
wallFD.filter.maskBits = MASK_WALL;
wall.createFixture(wallFD);
edge1.dispose();
wallFD = new FixtureDef();
wallFD.restitution = 0.0f;
wallFD.shape = edge2;
wallFD.filter.categoryBits = CATEGORY_WALL;
wallFD.filter.maskBits = MASK_WALL;
wall.createFixture(wallFD);
edge2.dispose();
wallFD = new FixtureDef();
wallFD.shape = edge3;
wallFD.filter.categoryBits = CATEGORY_WALL;
wallFD.filter.maskBits = MASK_WALL;
wall.createFixture(wallFD);
edge3.dispose();
wallFD = new FixtureDef();
wallFD.shape = edge4;
wallFD.isSensor = true;
wallFD.filter.categoryBits = CATEGORY_WALL;
wallFD.filter.maskBits = MASK_WALL;
wall.createFixture(wallFD);
edge4.dispose();
}
public abstract class GameObject extends Actor {
protected Body body;
protected TextureRegion texture;
public GameObject () {
}
public Body getBody () {
return body;
}
@Override
public abstract void draw(Batch batch, float parentAlpha);
}
private class Retry extends Actor {
public Retry () {
setPosition(RETRY_X * 100, SCREEN_HEIGHT * 100);
setWidth(RETRY_WIDTH * 100);
setHeight(RETRY_WIDTH * 100);
}
@Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(Assets.retry, getX() - getWidth() / 2, getY() - getHeight() / 2, getOriginX(), getOriginY(), getWidth(), getHeight(),
getScaleX(), getScaleY(), getRotation());
}
}
private class Background extends Actor {
@Override
public void draw(Batch batch, float parentAlpha){
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
//batch.draw(Assets.background, 0, 0);
batch.draw (Assets.background, 0, 0, 0, 0, VIRTUAL_WIDTH, VIRTUAL_HEIGHT, 2,
2, 0);
}
}
private class LeftPrompt extends Actor {
public LeftPrompt () {
setPosition(540 - 100 - 1456 / 4, 500);
setWidth(1456f / 4);
setHeight(859f / 4);
}
public void draw(Batch batch, float parentAlpha){
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw (Assets.prompt[0], getX(), getY(), 0, 0, getWidth(), getHeight(), 1,
1, 0);
}
}
private class RightPrompt extends Actor {
public RightPrompt () {
setPosition(540 + 85 , 500);
setWidth(1372f / 4);
setHeight(859f / 4);
}
public void draw(Batch batch, float parentAlpha){
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw (Assets.prompt[1], getX(), getY(), 0, 0, getWidth(), getHeight(), 1,
1, 0);
}
}
private class Player extends GameObject {
public Player (TextureRegion texture, float x, float y) {
this.texture = texture;
BodyDef ballD = new BodyDef();
ballD.position.set(x, y);
ballD.type = BodyType.DynamicBody;
body = world.createBody(ballD);
FixtureDef ballFD = new FixtureDef();
ballShape = new CircleShape();
ballShape.setRadius(BALL_WIDTH / 2);
ballFD.shape = ballShape;
ballFD.density = 1;
ballFD.friction = 0;
ballFD.restitution = 1;
ballFD.filter.categoryBits = CATEGORY_PLAYER;
ballFD.filter.maskBits = MASK_PLAYER;
body.createFixture(ballFD);
ballShape.dispose();
}
@Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(
texture,
(body.getPosition().x - (BALL_WIDTH * .5f)) * 100, (body.getPosition().y - (BALL_WIDTH * .5f)) * 100,
BALL_WIDTH * 100, BALL_WIDTH * 100);
}
}
private class Enemy extends GameObject {
Enemy (TextureRegion texture) {
this.texture = texture;
BodyDef squareD = new BodyDef();
squareD.type = BodyType.KinematicBody;
squareD.position.set((float) Math.random() * SCREEN_WIDTH, SCREEN_HEIGHT + 3.0f);
//squareD.linearVelocity.set(0.0f, -((float) Math.random() * (SQUARE_MAX_SPEED - SQUARE_MIN_SPEED)) + SQUARE_MIN_SPEED);
//squareD.angularVelocity = (SQUARE_MAX_SPEED + squareD.linearVelocity.y) * (Math.random() >= 0.5f ? 1 : -1);
squareD.gravityScale = 0;
body = world.createBody(squareD);
FixtureDef squareFD = new FixtureDef();
squareFD.shape = squareShape;
//squareFD.density = 99999999;
squareFD.friction = 0;
squareFD.restitution = 1;
squareFD.filter.categoryBits = CATEGORY_ENEMY;
squareFD.filter.maskBits = MASK_ENEMY;
body.createFixture(squareFD);
}
public Body getBody() {
return body;
}
@Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
/*batch.draw(texture, (body.getPosition().x - (SQUARE_WIDTH * .5f)) * 100, (body.getPosition().y - (SQUARE_WIDTH * .5f)) * 100,
SQUARE_WIDTH * 100 / 2, SQUARE_WIDTH * 100 / 2, SQUARE_WIDTH * 100, SQUARE_WIDTH * 100, 1, 1, (float) Math.toDegrees(body.getAngle()),
0, 0, this.texture.getRegionWidth(), this.texture.getRegionHeight(), false, false);*/
batch.draw(texture, (body.getPosition().x - (SQUARE_WIDTH * .5f)) * 100, (body.getPosition().y - (SQUARE_WIDTH * .5f)) * 100,
SQUARE_WIDTH * 100 / 2, SQUARE_WIDTH * 100 / 2,
SQUARE_WIDTH * 100, SQUARE_WIDTH * 100,
1, 1, (float) Math.toDegrees(body.getAngle()));
}
}
private void createEnemy () {
Enemy enemy = new Enemy(Assets.enemies[(int) (Math.random() * 3)]);
enemy.getBody().setLinearVelocity(0.0f, -(((float) Math.random() * (SQUARE_MAX_SPEED - SQUARE_MIN_SPEED)) + SQUARE_MIN_SPEED));
enemy.getBody().setAngularVelocity((SQUARE_MAX_SPEED + enemy.getBody().getLinearVelocity().y) * (Math.random() >= 0.5f ? 1 : -1));
enemies.add(enemy);
stage.addActor(enemy);
enemy.setZIndex(10);
scoreLabel.toFront();
//logger.info("enemy z:".concat(Integer.toString(enemy.getZIndex())));
//logger.info("label z:" + Integer.toString(scoreLabel.getZIndex()));
//logger.info("back z: " + Integer.toString(background.getZIndex()));
if (state == GAME_OVER && gameOverSetup == true) {
retry.toFront();
highScoreLabel.toFront();
game.highScoreWordsLabel.toFront();
//logger.info("retry z:".concat(Integer.toString(retry.getZIndex())));
//logger.info(Integer.toString(world.getBodyCount()));
}
for (int i = 0; i < 2; i++) {
if (enemies.peek() != null && enemies.peek().getBody().getPosition().y < -SCREEN_HEIGHT / 4) {
world.destroyBody(enemies.peek().getBody());
enemies.peek().remove();
enemies.poll();
}
}
}
private void drawEnemy () {
for (Enemy enemy : enemies) {
//enemy.draw(game.batch);
}
}
public void updateReady (float delta) {
}
public void renderReady () {
//player.draw(game.batch);
}
public void updateRunning (float delta) {
world.step(delta, 6, 2);
timeGap += delta;
playTime += delta;
if (timeGap >= SQUARE_FALL_INTERVAL) {
createEnemy();
timeGap -= SQUARE_FALL_INTERVAL;
}
if (state == GAME_RUNNING) {
//scoreLabel.addAction(Actions.moveTo(540, 990, 1f));
scoreLabel.setText((Integer.toString((int) playTime)));
//scoreLabel.setPosition(0, 0);
scoreLabel.setPosition(VIRTUAL_WIDTH - scoreLabel.getWidth(), VIRTUAL_HEIGHT - scoreLabel.getHeight());
scoreLabel.setAlignment(Align.right);
//scoreLabel.setVisible(true);
//stage.addActor(scoreLabel);
//logger.info("scoreLabel text: ".concat(scoreLabel.getText().toString()));
//logger.info("score: ".concat((Integer.toString((int) (playTime)))));
}
}
public void renderRunning () {
//drawEnemy();
//player.draw(game.batch);
}
public void udpateBallDestroyed () {
player.getBody().setActive(false);
world.destroyBody(player.getBody());
player.remove();
}
public void gameOverSetup () {
retry = new Retry();
retry.getColor().a = 0;
retry.addAction(Actions.parallel(Actions.fadeIn(1f),Actions.moveTo(RETRY_X * 100, RETRY_Y * 100, 1f, Interpolation.bounceOut)));
stage.addActor(retry);
retry.setZIndex(50);
if ((int) playTime > game.highScore) {
game.highScore = (int) playTime;
game.pref.putInteger("Score", game.highScore);
game.pref.flush();
}
highScoreLabel = new Label(Integer.toString(game.highScore), game.labelStyle);
highScoreLabel.setFontScale(1.5f);
highScoreLabel.setPosition(VIRTUAL_WIDTH - highScoreLabel.getWidth(), VIRTUAL_HEIGHT - highScoreLabel.getHeight() - 300);
highScoreLabel.setAlignment(Align.right);
stage.addActor(highScoreLabel);
stage.addActor(game.highScoreWordsLabel);
highScoreLabel.getColor().a = game.highScoreWordsLabel.getColor().a = 0;
highScoreLabel.setZIndex(50);
game.highScoreWordsLabel.setZIndex(50);
highScoreLabel.addAction(Actions.fadeIn(0.25f));
game.highScoreWordsLabel.addAction(Actions.fadeIn(0.25f));
}
public void gameReadySetup () {
//stage.addActor(new LeftPrompt());
//stage.addActor(new RightPrompt());
for (Actor actor : stage.getActors()) {
actor.getColor().a = 0;
actor.addAction(Actions.fadeIn(0.25f));
}
//stage.addAction(Actions.fadeIn(0.5f));
}
@Override
public void render (float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
/*game.batch.begin();
game.batch.setProjectionMatrix(viewport.getCamera().combined);
game.batch.draw(Assets.background, 0, 0);
game.batch.end();
*/
switch (state) {
case GAME_READY_SETUP:
gameReadySetup();
state = GAME_READY;
break;
case GAME_READY:
updateReady(delta);
//renderRunning();
break;
case GAME_RUNNING:
updateRunning(delta);
//renderRunning();
break;
case GAME_OVER_SETUP:
updateRunning(delta);
if (gameOverSetup == false) {
gameOverSetup();
gameOverSetup = true;
}
state = GAME_OVER;
//renderRunning();
break;
case GAME_OVER:
updateRunning(delta);
break;
case BALL_DESTROYED:
updateRunning(delta);
udpateBallDestroyed();
state = GAME_OVER_SETUP;
break;
}
stage.act(delta);
stage.draw();
//game.debugRenderer.render(world, viewport.getCamera().combined);
}
@Override
public void resize(int width, int height) {
viewport.update(width, height);
}
@Override
public boolean touchDown (int screenX, int screenY, int pointer, int button) {
point.set(screenX, screenY, 0);
viewport.unproject(point);
//if ((0 <= point.x && point.x < SCREEN_WIDTH) && (0 <= point.y && point.y < SCREEN_HEIGHT)) {
switch (state) {
case GAME_READY:
leftPrompt.addAction(Actions.fadeOut(FADE_INTERVAL));
rightPrompt.addAction(Actions.fadeOut(FADE_INTERVAL));
state = GAME_RUNNING;
//break;
case GAME_RUNNING:
if (point.x < SCREEN_WIDTH / 2) {
player.getBody().setLinearVelocity(new Vector2(-BALL_JUMP_X, BALL_JUMP_Y));
}
if (point.x >= SCREEN_WIDTH / 2) {
player.getBody().setLinearVelocity(new Vector2(BALL_JUMP_X, BALL_JUMP_Y));
}
break;
case GAME_OVER:
if (point.dst(RETRY_X, RETRY_Y, 0) <= RETRY_WIDTH / 2) {
stage.addAction(Actions.sequence(Actions.fadeOut(0.25f), new Action() {
public boolean act(float delta) {
game.setScreen(new GameScreen(game));
return true;
}
}));
}
break;
}
//}
return true;
}
@Override
public boolean keyDown (int keycode) {
switch (state) {
case GAME_READY:
if (keycode == Keys.LEFT || keycode == Keys.RIGHT) {
leftPrompt.addAction(Actions.fadeOut(FADE_INTERVAL));
rightPrompt.addAction(Actions.fadeOut(FADE_INTERVAL));
state = GAME_RUNNING;
}
//break;
case GAME_RUNNING:
if (keycode == Keys.LEFT) {
player.getBody().setLinearVelocity(new Vector2(-BALL_JUMP_X, BALL_JUMP_Y));
}
if (keycode == Keys.RIGHT) {
player.getBody().setLinearVelocity(new Vector2(BALL_JUMP_X, BALL_JUMP_Y));
}
break;
case GAME_OVER:
if (keycode == Keys.SPACE) {
stage.addAction(Actions.sequence(Actions.fadeOut(0.25f), new Action() {
public boolean act(float delta) {
game.setScreen(new GameScreen(game));
return true;
}
}));
}
break;
}
return true;
}
@Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
Fixture fixtureA = contact.getFixtureA();
Fixture fixtureB = contact.getFixtureB();
//logger.info("contact");
if (state == GAME_RUNNING) {
if (fixtureA.getFilterData().categoryBits == CATEGORY_PLAYER &&
fixtureB.getFilterData().categoryBits == CATEGORY_ENEMY) {
//fixtureA.getFilterData().maskBits = 0;
state = GAME_OVER_SETUP;
}
else if (fixtureA.getFilterData().categoryBits == CATEGORY_ENEMY &&
fixtureB.getFilterData().categoryBits == CATEGORY_PLAYER) {
//fixtureB.getFilterData().maskBits = 0;
state = GAME_OVER_SETUP;
}
}
if ((fixtureA.isSensor() == true && fixtureB.getFilterData().categoryBits == CATEGORY_PLAYER)
|| (fixtureB.isSensor() == true && fixtureA.getFilterData().categoryBits == CATEGORY_PLAYER)) {
state = BALL_DESTROYED;
}
}
@Override
public void endContact(Contact contact) {
//logger.info("contact");
}
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
// TODO Auto-generated method stub
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
// TODO Auto-generated method stub
}
}