Продолжаем делать игру Flappy Bird для android. Для начала немного оптимизируем нашу игру, чтобы предотвратить утечки памяти. Затем добавим текстуру земли в нашу игру. Затем изменим код для корректного запуска игры на android устройстве.
Скачать графические ресурсы для игры
Исходный код измененных классов под видео:
package info.fandroid.game.states;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import info.fandroid.game.FlappyDemo;
import info.fandroid.game.sprites.Bird;
import info.fandroid.game.sprites.Tube;
/**
* Created by Vitaly on 06.11.2015.
*/
public class PlayState extends State {
private static final int TUBE_SPACING = 125;
private static final int TUBE_COUNT = 4;
private static final int GROUND_Y_OFFSET = -30;
private Bird bird;
private Texture bg;
private Texture ground;
private Vector2 groundPos1, groundPos2;
private Array<Tube> tubes;
public PlayState(GameStateManager gsm) {
super(gsm);
bird = new Bird(50, 300);
camera.setToOrtho(false, FlappyDemo.WIDTH / 2, FlappyDemo.HEIGHT / 2);
bg = new Texture("bg.png");
ground = new Texture("ground.png");
groundPos1 = new Vector2(camera.position.x - camera.viewportWidth / 2, GROUND_Y_OFFSET);
groundPos2 = new Vector2((camera.position.x - camera.viewportWidth / 2) + ground.getWidth(), GROUND_Y_OFFSET);
tubes = new Array<Tube>();
for (int i = 0; i < TUBE_COUNT; i++){
tubes.add(new Tube(i * (TUBE_SPACING + Tube.TUBE_WIDTH)));
}
}
@Override
protected void handleInput() {
if (Gdx.input.justTouched())
bird.jump();
}
@Override
public void update(float dt) {
handleInput();
updateGround();
bird.update(dt);
camera.position.x = bird.getPosition().x + 80;
for (int i = 0; i < tubes.size; i++){
Tube tube = tubes.get(i);
if (camera.position.x - (camera.viewportWidth / 2) > tube.getPosTopTube().x + tube.getTopTube().getWidth()){
tube.reposition(tube.getPosTopTube().x + ((Tube.TUBE_WIDTH + TUBE_SPACING) * TUBE_COUNT));
}
if (tube.collides(bird.getBounds()))
gsm.set(new PlayState(gsm));
}
camera.update();
}
@Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(camera.combined);
sb.begin();
sb.draw(bg, camera.position.x - (camera.viewportWidth / 2), 0);
sb.draw(bird.getBird(), bird.getPosition().x, bird.getPosition().y);
for (Tube tube : tubes) {
sb.draw(tube.getTopTube(), tube.getPosBotTube().x, tube.getPosTopTube().y);
sb.draw(tube.getBottomTube(), tube.getPosBotTube().x, tube.getPosBotTube().y);
}
sb.draw(ground, groundPos1.x, groundPos1.y);
sb.draw(ground, groundPos2.x, groundPos2.y);
sb.end();
}
@Override
public void dispose() {
bg.dispose();
bird.dispose();
ground.dispose();
for (Tube tube : tubes)
tube.dispose();
System.out.println("PlayState Disposed");
}
private void updateGround(){
if (camera.position.x - (camera.viewportWidth / 2) > groundPos1.x + ground.getWidth())
groundPos1.add(ground.getWidth() * 2, 0);
if (camera.position.x - (camera.viewportWidth / 2) > groundPos2.x + ground.getWidth())
groundPos2.add(ground.getWidth() * 2, 0);
}
}
package info.fandroid.game.states;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import info.fandroid.game.FlappyDemo;
/**
* Created by Vitaly on 28.10.2015.
*/
public class MenuState extends State {
private Texture background;
private Texture playBtn;
public MenuState(GameStateManager gsm) {
super(gsm);
camera.setToOrtho(false, FlappyDemo.WIDTH / 2, FlappyDemo.HEIGHT / 2);
background = new Texture("bg.png");
playBtn = new Texture("playbtn.png");
}
@Override
public void handleInput() {
if(Gdx.input.justTouched()){
gsm.set(new PlayState(gsm));
}
}
@Override
public void update(float dt) {
handleInput();
}
@Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(camera.combined);
sb.begin();
sb.draw(background, 0, 0);
sb.draw(playBtn, camera.position.x - playBtn.getWidth() / 2, camera.position.y);
sb.end();
}
@Override
public void dispose() {
background.dispose();
playBtn.dispose();
System.out.println("MenuState Disposed");
}
}
package info.fandroid.game.sprites;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import java.util.Random;
/**
* Created by Vitaly on 13.11.2015.
*/
public class Tube {
public static final int TUBE_WIDTH = 52;
private static final int FLUCTUATION = 130;
private static final int TUBE_GAP = 100;
private static final int LOWEST_OPENING = 120;
private Texture topTube, bottomTube;
private Vector2 posTopTube, posBotTube;
private Random rand;
private Rectangle boundsTop, boundsBot;
public Texture getTopTube() {
return topTube;
}
public Texture getBottomTube() {
return bottomTube;
}
public Vector2 getPosTopTube() {
return posTopTube;
}
public Vector2 getPosBotTube() {
return posBotTube;
}
public Tube(float x){
topTube = new Texture("toptube.png");
bottomTube = new Texture("bottomtube.png");
rand = new Random();
posTopTube = new Vector2(x, rand.nextInt(FLUCTUATION) + TUBE_GAP + LOWEST_OPENING);
posBotTube = new Vector2(x, posTopTube.y - TUBE_GAP - bottomTube.getHeight());
boundsTop = new Rectangle(posTopTube.x, posTopTube.y, topTube.getWidth(), topTube.getHeight());
boundsBot = new Rectangle(posBotTube.x, posBotTube.y, bottomTube.getWidth(), bottomTube.getHeight());
}
public void reposition(float x){
posTopTube.set(x, rand.nextInt(FLUCTUATION) + TUBE_GAP + LOWEST_OPENING);
posBotTube.set(x, posTopTube.y - TUBE_GAP - bottomTube.getHeight());
boundsTop.setPosition(posTopTube.x, posTopTube.y);
boundsBot.setPosition(posBotTube.x, posBotTube.y);
}
public boolean collides(Rectangle player){
return player.overlaps(boundsTop) || player.overlaps(boundsBot);
}
public void dispose() {
topTube.dispose();
bottomTube.dispose();
}
}
package info.fandroid.game.sprites;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
/**
* Created by Vitaly on 06.11.2015.
*/
public class Bird {
private static final int MOVEMENT = 100;
private static final int GRAVITY = -15;
private Vector3 position;
private Vector3 velosity;
private Rectangle bounds;
private Texture bird;
public Bird(int x, int y){
position = new Vector3(x, y, 0);
velosity = new Vector3(0, 0, 0);
bird = new Texture("bird.png");
bounds = new Rectangle(x, y, bird.getWidth(), bird.getHeight());
}
public Vector3 getPosition() {
return position;
}
public Texture getBird() {
return bird;
}
public void update(float dt){
if (position.y > 0)
velosity.add(0, GRAVITY, 0);
velosity.scl(dt);
position.add(MOVEMENT * dt, velosity.y, 0);
if (position.y < 0)
position.y = 0;
velosity.scl(1 / dt);
bounds.setPosition(position.x, position.y);
}
public void jump(){
velosity.y = 250;
}
public Rectangle getBounds(){
return bounds;
}
public void dispose() {
bird.dispose();
}
}
Больше уроков:
Уроки Android Studio: тут
Инструменты android разработчика: тут
Дизайн android приложений: тут
Уроки создания игр для android: тут
Основы программирования на JAVA: тут
Урок 11. Flappy Bird: добавляем анимацию в игру| Делаем android игры на LibGDX