Как сделать игру для андроид с LibGDX — мультиплатформенным фреймворком для создания игр, мы покажем в этом уроке на примере создания простой игры.
Ссылки:
Звуки, текстуры из этой игры: ссылка
Ортографическая камера в LibGDX: ссылка
Управление памятью в LibGDX: ссылка

Полный код игры:

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.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.math.Rectangle;
import java.util.Iterator;

public class Drop extends ApplicationAdapter {
   OrthographicCamera camera;
   SpriteBatch batch;
   Texture dropImage;
   Texture bucketImage;
   Sound dropSound;
   Music rainMusic;
   Rectangle bucket;
   Vector3 touchPos;
   Array<Rectangle> raindrops;
   long lastDropTime;

   @Override
   public void create () {

      camera = new OrthographicCamera();
      camera.setToOrtho(false, 800, 480);

      batch = new SpriteBatch();

      touchPos = new Vector3();

      dropImage = new Texture("droplet.png");
      bucketImage = new Texture("bucket.png");

      dropSound = Gdx.audio.newSound(Gdx.files.internal("waterdrop.wav"));
      rainMusic = Gdx.audio.newMusic(Gdx.files.internal("undertreeinrain.mp3"));

      rainMusic.setLooping(true);
      rainMusic.play();

      bucket = new Rectangle();
      bucket.x = 800 / 2 - 64 / 2;
      bucket.y = 20;
      bucket.width = 64;
      bucket.height = 64;

      raindrops = new Array<Rectangle>();
      spawnRaindrop();

   }

   private void spawnRaindrop(){
      Rectangle raindrop = new Rectangle();
      raindrop.x = MathUtils.random(0, 800-64);
      raindrop.y = 480;
      raindrop.width = 64;
      raindrop.height = 64;
      raindrops.add(raindrop);
      lastDropTime = TimeUtils.nanoTime();
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(0, 0, 0.2f, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

      camera.update();

      batch.setProjectionMatrix(camera.combined);
      batch.begin();
      batch.draw(bucketImage, bucket.x, bucket.y);
      for (Rectangle raindrop: raindrops){
         batch.draw(dropImage, raindrop.x, raindrop.y);
      }
      batch.end();

      if(Gdx.input.isTouched()){
         touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
         camera.unproject(touchPos);
         bucket.x = (int) (touchPos.x -64 / 2);
      }

      if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
      if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();

      if (bucket.x < 0) bucket.x = 0;
      if (bucket.x > 800 - 64) bucket.x = 800 - 64;

      if (TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();

      Iterator<Rectangle> iter = raindrops.iterator();
      while (iter.hasNext()){
         Rectangle raindrop = iter.next();
         raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
         if (raindrop.y + 64 < 0) iter.remove();
         if (raindrop.overlaps(bucket)){
            dropSound.play();
            iter.remove();
         }
      }
   }

   @Override
   public void dispose() {
      super.dispose();
      dropImage.dispose();
      bucketImage.dispose();
      dropSound.dispose();
      rainMusic.dispose();
      batch.dispose();
   }
}

Больше уроков:

Уроки Android Studio: тут
Инструменты android разработчика: тут
Дизайн android приложений: тут
Уроки создания игр для android: тут
Основы программирования на JAVA: тут

<<LibGDX: Урок 2. Немного теории | Делаем android игры

LibGDX: Урок 4. Добавляем в игру экран меню и счетчик прогресса>>


admin

Обучающие видео-уроки по разработке приложений для операционной системы Android. Мы поможем любому новичку стать продвинутым разработчиком андроид-приложений!

12 комментариев

Максим Владимирович · 09.10.2015 в 21:43

спасибо, Виталий! выдаете полезный и интересный контент!

Ivan · 03.11.2015 в 18:34

По какой причине данный код прекрасно работает при проверке на десктопе, но выдаёт ошибку при загрузке на эмуляторе? В чём может быть подвох?

    Гулмира · 26.12.2015 в 17:36

    Иван, Вы решили свою проблему? У меня та же самая проблема. При проверке на desktop-е работает, а на эмуляторе — нет.

UglukFearless · 17.03.2016 в 07:35

Ребят, вы бы хоть код ошибки выложили. Может быть у вас версия API эмулятора не подходит?

Павел · 25.03.2016 в 00:25

Виталий, спасибо за статью и видео. Это то, чего мне не хватало для того, чтобы начать программировать под Android.
Может быть знаете почему в desktop приложении звука нет, а на устройстве с android есть.

Igor 2016 · 01.09.2016 в 13:08

Exception in thread «LWJGL Application» com.badlogic.gdx.utils.GdxRuntimeException: Error creating sound com.badlogic.gdx.backends.lwjgl.audio.Wav$Sound for file: waterdrop.wav
at com.badlogic.gdx.backends.lwjgl.audio.OpenALAudio.newSound(OpenALAudio.java:119)
at com.badlogic.gdx.backends.lwjgl.audio.OpenALAudio.newSound(OpenALAudio.java:41)
at ua.org.amt.Drop.create(Drop.java:44)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.badlogic.gdx.backends.lwjgl.audio.OpenALAudio.newSound(OpenALAudio.java:117)
… 4 more
Caused by: com.badlogic.gdx.utils.GdxRuntimeException: Error reading WAV file: waterdrop.wav
at com.badlogic.gdx.backends.lwjgl.audio.Wav$WavInputStream.(Wav.java:109)
at com.badlogic.gdx.backends.lwjgl.audio.Wav$Sound.(Wav.java:63)
… 9 more
Caused by: com.badlogic.gdx.utils.GdxRuntimeException: WAV files must have 16 bits per sample: 8
at com.badlogic.gdx.backends.lwjgl.audio.Wav$WavInputStream.(Wav.java:102)
… 10 more

Sapfil · 15.09.2016 в 20:31

Спасибо автору. Строго следовал инструкции. Все запускается на десктопе и на «китайфоне»
.
Давно планировал перетащить свой проект с мёртвого AndEngine на живой движок.
Как я понял — у движка нет альтернативы методам attachChild(IEntity) и т.п. как в AndEngine.
Если же все-таки это как-то реализовано — буду рад подсказке.

Егор · 18.09.2016 в 23:54

Хелп!
На десктопе игра работает отлично, но на андроиде моментально вылетает при запуске.
код ошибки:
09-18 23:49:15.064 6353-6390/info.fandroid.drop E/AndroidRuntime: FATAL EXCEPTION: GLThread 1439
Process: info.fandroid.drop, PID: 6353
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Rectangle;
at info.fandroid.drop.Drop.create(Drop.java:40)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:275)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1564)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286)
Caused by: java.lang.ClassNotFoundException: Didn’t find class «java.awt.Rectangle» on path: DexPathList[[zip file «/data/app/info.fandroid.drop-2/base.apk»],nativeLibraryDirectories=[/data/app/info.fandroid.drop-2/lib/arm64, /vendor/lib64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at info.fandroid.drop.Drop.create(Drop.java:40) 
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:275) 
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1564) 
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286) 
Suppressed: java.lang.ClassNotFoundException: java.awt.Rectangle
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
… 5 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

Если не использовать класс Rectangle в приложении то оно запускается (я закомментировал все относящееся к нему и вместо этого просто напрямую отрисовал картинку)

    admin · 20.09.2016 в 09:09

    Запуск на android настраиваем в последних уроках.

Сергей · 01.11.2016 в 15:24

В видео уроке не увидел когда добавили эту строчку

for (Rectangle raindrop: raindrops){
batch.draw(dropImage, raindrop.x, raindrop.y);
}

marsik · 24.11.2017 в 08:27

А как запустить html вариант?

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.