Как сделать игру для андроид с 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. Добавляем в игру экран меню и счетчик прогресса>>
А как запустить html вариант?
В видео уроке не увидел когда добавили эту строчку
for (Rectangle raindrop: raindrops){
batch.draw(dropImage, raindrop.x, raindrop.y);
}
Хелп!
На десктопе игра работает отлично, но на андроиде моментально вылетает при запуске.
код ошибки:
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 в приложении то оно запускается (я закомментировал все относящееся к нему и вместо этого просто напрямую отрисовал картинку)
Запуск на android настраиваем в последних уроках.
Спасибо автору. Строго следовал инструкции. Все запускается на десктопе и на “китайфоне”
.
Давно планировал перетащить свой проект с мёртвого AndEngine на живой движок.
Как я понял – у движка нет альтернативы методам attachChild(IEntity) и т.п. как в AndEngine.
Если же все-таки это как-то реализовано – буду рад подсказке.
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
Виталий, спасибо за статью и видео. Это то, чего мне не хватало для того, чтобы начать программировать под Android.
Может быть знаете почему в desktop приложении звука нет, а на устройстве с android есть.
Ребят, вы бы хоть код ошибки выложили. Может быть у вас версия API эмулятора не подходит?
По какой причине данный код прекрасно работает при проверке на десктопе, но выдаёт ошибку при загрузке на эмуляторе? В чём может быть подвох?
Иван, Вы решили свою проблему? У меня та же самая проблема. При проверке на desktop-е работает, а на эмуляторе – нет.
спасибо, Виталий! выдаете полезный и интересный контент!