Продолжаем делать игру Flappy Bird для 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.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 Bird bird; private Texture bg; 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"); 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(); bird.update(dt); camera.position.x = bird.getPosition().x + 80; for (Tube tube : tubes){ 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.end(); } @Override public void dispose() { } }
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); } }
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; } }
Больше уроков:
Уроки Android Studio: тут
Инструменты android разработчика: тут
Дизайн android приложений: тут
Уроки создания игр для android: тут
Основы программирования на JAVA: тут
<<Урок 8. Flappy Bird: добавляем движущиеся трубы | Делаем android игры на LibGDX
Урок 10. Flappy Bird: добавляем текстуру земли и оптимизируем код для запуска игры на Android >>
Вот ссылка на скрин https://cloud.mail.ru/public/7QcY/jvRv1dsD6
Заранее Спасибо
Здравствуйте Виталий, у меня при написании
boundsTop = new Rectangle(posTopTube.x, posTopTube.y, topTube.getWidth(), topTube.getHeight());
выводит ошибку. И в подсказке показывает какой-то floatЯ новичок в этом деле буду благодарен за ваш отклик