Android Games: Skyfire

De Aulas

Links relacionados: Jogos Digitais

Videoaula

Youtube

Recursos

Background.java

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;

public class BackGround {
    MyGdxGame game;
    Texture texture;
    int ya, yb;
    int SPEED = 2;

    BackGround(Texture texture, MyGdxGame game) {
        this.game = game;
        this.texture = texture;
        ya = 0;
        yb = texture.getHeight();
    }

    void execute() {
        ya -= SPEED;
        yb -= SPEED;
        if (ya <= -texture.getHeight()) {
            ya = yb + texture.getHeight();
        }
        if (yb <= -texture.getHeight()) {
            yb = ya + texture.getHeight();
        }
    }

    void draw() {
        game.batch.draw(texture, 0, ya);
        game.batch.draw(texture, 0, yb);
    }

    void dispose() {
        texture.dispose();
    }
}

Actor.java

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Intersector;

public class Actor {
    MyGdxGame game;
    Sprite sprite;
    int SPEED = 10;
    boolean dead = false;

    Actor(float x, float y, Texture texture, MyGdxGame game) {
        this.game = game;
        this.sprite = new Sprite(texture);
        this.sprite.setPosition(x, y);
    }

    void execute() {
        // To implement
    }

    float clamp(float value, float min, float max) {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }

    boolean collide(Actor other) {
        if (this == other) return false;
        return Intersector.overlaps(
                sprite.getBoundingRectangle(),
                other.sprite.getBoundingRectangle()
        );
    }

    void explode() {
        dead = true;
        game.news.add(new Explosion(
                sprite.getX() + (sprite.getWidth() / 2f) - (game.texturesExplosion.get(0).getWidth() / 2f),
                sprite.getY() + (sprite.getHeight() / 2f) - (game.texturesExplosion.get(0).getWidth() / 2f),
                game.texturesExplosion, game));
    }

    void draw() {
        sprite.draw(game.batch);
    }
}

Colisão BoundingBox

Implementação da colisão de retângulos.

	private boolean spriteCollide(Sprite a, Sprite b) {
		float x = a.getX();
		float y = a.getY();
		float w = a.getWidth();
		float h = a.getHeight();
		return pointCollide(x, y, b) ||
				pointCollide(x + w, y, b) ||
				pointCollide(x, y + h, b) ||
				pointCollide(x + w, y + h, b);
	}

	private boolean pointCollide(float px, float py, Sprite s) {
		float x = s.getX();
		float y = s.getY();
		float w = s.getWidth();
		float h = s.getHeight();
		return (px > x && px < x + w && py > y && py < y + h);
	}

Enemy.java

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;

public class Enemy extends Actor {
    static final int RIGHT = 0;
    static final int LEFT = 1;
    int direction;

    Enemy(Texture texture, MyGdxGame game) {
        super(game.rand.nextInt(game.w - texture.getWidth()), game.h + 100, texture, game);
        direction = game.rand.nextInt(2);
    }

    @Override
    void execute() {
        sprite.translateY(-5);
        if (direction == RIGHT) {
            sprite.translateX(5);
            if (sprite.getX() + sprite.getWidth() > game.w) {
                direction = LEFT;
            }
        } else {
            sprite.translateX(-5);
            if (sprite.getX() < 0) {
                direction = RIGHT;
            }
        }
        if (sprite.getY() + sprite.getHeight() < 0) {
            dead = true;
        }
    }
}

Ship.java

package com.mygdx.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;

public class Ship extends Actor {
    Ship(float x, float y, Texture texture, MyGdxGame game) {
        super(x, y, texture, game);
    }

    @Override
    void execute() {
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            sprite.setX(clamp(sprite.getX() - SPEED, 0, game.w));
        } else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
            sprite.setX(clamp(sprite.getX() + SPEED, 0, game.w - sprite.getWidth()));
        }
        if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
            game.news.add(new Bomb(
                    sprite.getX() + (sprite.getWidth() / 2f) - (game.textureBomb.getWidth() / 2f),
                    sprite.getY() + sprite.getHeight(),
                    game.textureBomb, game));
            game.sndBomb.play();
        }
        for (Actor a : game.actor) {
            if (collide(a) && a instanceof Enemy) {
                a.explode();
                explode();
                game.gameOver = true;
                break;
            }
        }
    }
}

Bomb.java

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;

public class Bomb extends Actor {
    Bomb(float x, float y, Texture texture, MyGdxGame game) {
        super(x, y, texture, game);
    }

    @Override
    void execute() {
        sprite.translateY(5);
        if (sprite.getY() > game.h) dead = true;
        for (Actor a : game.actor) {
            if (collide(a) && a instanceof Enemy) {
                a.explode();
                dead = true;
                game.score++;
                break;
            }
        }
    }
}

Explosion.java

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;

import java.util.List;

class Explosion extends Actor {
    List<Texture> textures;
    int count = 0;
    int maxCount = 3;
    int position = 0;

    Explosion(float x, float y, List<Texture> textures, MyGdxGame game) {
        super(x, y, textures.get(0), game);
        this.textures = textures;
        game.sndExplosion.play();
    }

    @Override
    void execute() {
        count++;
        if (count > maxCount) {
            count = 0;
            position++;
        }
        if (position >= textures.size()) dead = true;
        else sprite.setTexture(textures.get(position));
    }
}

MyGdxGame.java

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MyGdxGame extends ApplicationAdapter {
    SpriteBatch batch;
    Texture textureShip;
    Texture textureEnemy;
    Texture textureBomb;
    Texture textureGameOver;
    List<Texture> texturesExplosion = new ArrayList<>();
    int w, h;
    BackGround background;
    BitmapFont font;
    List<Actor> actor = new ArrayList<>();
    List<Actor> news = new ArrayList<>();
    Random rand = new Random();
    Sound sndBomb;
    Sound sndExplosion;
    Music music;
    boolean gameOver = false;
    int score = 0;
    int countEnemy = 0;
    int maxCountEnemy = 100;

    @Override
    public void create() {
        w = Gdx.graphics.getWidth();
        h = Gdx.graphics.getHeight();
        batch = new SpriteBatch();
        background = new BackGround(new Texture("background.png"), this);
        textureShip = new Texture("ship.png");
        textureEnemy = new Texture("enemy.png");
        textureBomb = new Texture("bomb.png");
        textureGameOver = new Texture("gameover.png");
        texturesExplosion.add(new Texture("explosion_0.png"));
        texturesExplosion.add(new Texture("explosion_1.png"));
        texturesExplosion.add(new Texture("explosion_2.png"));
        texturesExplosion.add(new Texture("explosion_1.png"));
        texturesExplosion.add(new Texture("explosion_0.png"));
        sndBomb = Gdx.audio.newSound(Gdx.files.internal("bomb.wav"));
        sndExplosion = Gdx.audio.newSound(Gdx.files.internal("explosion.wav"));
        music = Gdx.audio.newMusic(Gdx.files.internal("music.ogg"));
        music.setLooping(true);
        music.setVolume(0.7f);
        music.play();
        font = new BitmapFont(
                Gdx.files.internal("verdana.fnt"),
                Gdx.files.internal("verdana.png"), false);
        font.setColor(Color.BLACK);
        start();
    }

    private void start() {
        gameOver = false;
        score = 0;
        actor.clear();
        news.clear();
        actor.add(new Ship((w / 2f) - (textureShip.getWidth() / 2f),
                10, textureShip, this));
    }

    private void execute() {
        if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) {
            Gdx.app.exit();
        }
        if (gameOver) {
            if (Gdx.input.isKeyJustPressed(Input.Keys.ENTER)) {
                start();
            }
        }
        for (Actor a : actor) a.execute();
        background.execute();
        stagehandWork();
    }

    private void enemyGenerator() {
        countEnemy++;
        if (countEnemy > maxCountEnemy) {
            actor.add(new Enemy(textureEnemy, this));
            countEnemy = 0;
            maxCountEnemy = 20 + rand.nextInt(50);
        }
    }

    private void stagehandWork() {
        enemyGenerator();
        List<Actor> aux = actor;
        actor = new ArrayList<>();
        for (Actor a : aux) if (!a.dead) actor.add(a);
        actor.addAll(news);
        news.clear();
    }

    @Override
    public void render() {
        execute();
        batch.begin();
        background.draw();
        for (Actor a : actor) a.draw();
        font.draw(batch, "SCORE: " + score, 1, h);
        if (gameOver) {
            batch.draw(textureGameOver, (w / 2f) - (textureGameOver.getWidth() / 2f), 200);
        }
        batch.end();
    }

    @Override
    public void dispose() {
        batch.dispose();
        background.dispose();
        textureEnemy.dispose();
        textureShip.dispose();
        textureBomb.dispose();
        font.dispose();
    }
}