LibGDX: Урок 3. Создаем простую игру | Делаем android игры

Как сделать игру для андроид с 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. Добавляем в игру экран меню и счетчик прогресса>>

Коментарі: 12
  1. marsik
    marsik

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

  2. Сергей

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

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

  3. Егор

    Хелп!
    На десктопе игра работает отлично, но на андроиде моментально вылетает при запуске.
    код ошибки:
    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 в приложении то оно запускается (я закомментировал все относящееся к нему и вместо этого просто напрямую отрисовал картинку)

    1. Виталий Непочатов
      admin (автор)

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

  4. Sapfil

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

  5. Igor 2016

    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

  6. Павел

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

  7. UglukFearless

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

  8. Ivan

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

    1. Гулмира

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

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

Додати коментар