Здравствуйте, сегодня создадим простую Android игру с помощью бесплатного фреймворка LibGDX и Android Studio.
Суть игры: помочь пони собрать как можно больше яблок за 60 секунд.
Изменения кода игры от 01.07.16
Скачать исходники для статьи можно ниже
Также рекомендую изучить видео-инструкцию для новичков по созданию простой android игры, на основе её и была создана нижеуказанная игра:
Урок 1: “youtu.be/e75He5HE9iE”
Урок 2: “youtu.be/C34m2XN4gzo”
Урок 3: “youtu.be/oRgBRm60jXY”
Урок 4: “youtu.be/F2h7E2VpY0Y”
Скачать apk данной игры можно по следующей ссылке:
Скачать Android игру “Собери яблоки”
Первое, создаём проект в бесплатном фреймворке – LibGDX, указываем:
Name: PonyGame3
Package: ru.mnogoblog
Game class: PonyGame3
Отмечаем галочкой:
– Desktop и Android;
– Freetype (так как будем подключать русские шрифты).
Для игры “Собери яблоки” вам понадобится создать 4 класса:
– Drop
– GameOverScreen
– MainMenuScreen
– PonyGame3
Скачать данные файлы можно по следующей ссылке – скачать файлы классов к игре “Собери яблоки” – их можно открыть с помощью редактора кода, например: NotePad++ или с помощью обычного – Блокнота (Windows).
Код данных классов приведу ниже!
Содержимое папки assets, где лежат все картинки, шрифты и музыка для игры можно скачать по следующей ссылке:
Скачать папку assets для игры “Собери яблоки”.
Главным классом игры – будет класс Drop, поэтому в файле AndroidLauncher пропишем ссылку на него:
package ru.mnogoblog; import android.os.Bundle; import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; public class AndroidLauncher extends AndroidApplication { @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); initialize(new Drop(), config); } }
Аналогично с DesktopLauncher – если вы создаёте desctop версию игры:
Код файла DesktopLauncher:
package ru.mnogoblog.desktop; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import ru.mnogoblog.Drop; public class DesktopLauncher { public static void main (String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); new LwjglApplication(new Drop(), config); } }
Теперь приведу код классов.
Код класса Drop:
package ru.mnogoblog; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; import java.util.Locale; public class Drop extends Game { SpriteBatch batch; BitmapFont font; BitmapFont myfont; @Override public void create() { batch = new SpriteBatch(); font = new BitmapFont(); myfont = new BitmapFont(); final String FONT_CHARS = "абвгдежзийклмнопрстуфхцчшщъыьэюяabcdefghijklmnopqrstuvwxyzАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789][_!$%#@|\\\\/?-+=()*&.;:,{}\\\"´`'<>"; final String FONT_PATH = "fonts/Imperial Web.ttf"; FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal(FONT_PATH)); FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter(); parameter.characters = FONT_CHARS; parameter.size = 17; parameter.color = Color.BROWN; myfont = generator.generateFont(parameter); generator.dispose(); this.setScreen(new MainMenuScreen(this)); font.setColor(1f, 0f, 0f, 1f); } @Override public void render() { super.render(); } @Override public void dispose() { super.dispose(); batch.dispose(); font.dispose(); } }
Код класса PonyGame3:
package ru.mnogoblog; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.Screen; 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.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.TimeUtils; import java.util.Iterator; public class PonyGame3 implements Screen { final Drop game; OrthographicCamera camera; Texture dropImage; Texture myPony; Texture bucketImage; Sound dropSound; Music rainMusic; Rectangle bucket; Vector3 touchPos; Array<Rectangle> raindrops; long lastDropTime; static int dropsGatchered; static int dropsGatchered2; String dropString; public static Texture backgroundTexture; float timer = 0f; int time = 0; public PonyGame3 (final Drop gam) { this.game = gam; camera = new OrthographicCamera(); camera.setToOrtho(false, 800, 480); touchPos = new Vector3(); dropImage = new Texture("apple.png"); myPony = new Texture("pony.png"); bucketImage = new Texture("bucket2.png"); backgroundTexture = new Texture("bg.png"); dropSound = Gdx.audio.newSound(Gdx.files.internal("mpput.mp3")); rainMusic = Gdx.audio.newMusic(Gdx.files.internal("ponyfongame.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 (float delta) { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); game.batch.setProjectionMatrix(camera.combined); game.batch.begin(); game.batch.draw(backgroundTexture, 0, 0, 800, 480); game.batch.draw(dropImage, 0,440,64,64); game.myfont.draw(game.batch, "Время:" + (6100-time)/100, 350, 460); game.myfont.draw(game.batch, ": " + dropsGatchered, 60, 460); game.batch.draw(bucketImage, bucket.x, bucket.y); for (Rectangle raindrop: raindrops){ game.batch.draw(dropImage, raindrop.x, raindrop.y); } game.batch.draw(myPony, 0,0,200,100); game.batch.end(); timer = delta; if (timer >= 0) { time++; } if (time>6000) { game.setScreen(new GameOverScreen(game)); dropsGatchered2=dropsGatchered; dropsGatchered=0; dispose(); } if(Gdx.input.isTouched()){ touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0); if (touchPos.x<400) bucket.x -= 200 * Gdx.graphics.getDeltaTime(); if(touchPos.x>400) bucket.x += 200 * Gdx.graphics.getDeltaTime(); } 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)){ dropsGatchered++; dropSound.play(); iter.remove(); } } } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } @Override public void hide() { } @Override public void dispose() { dropImage.dispose(); bucketImage.dispose(); dropSound.dispose(); rainMusic.dispose(); } @Override public void show() { rainMusic.play(); } }
Код класса MainMenuScreen:
package ru.mnogoblog; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Vector3; import java.util.Locale; public class MainMenuScreen implements Screen { Vector3 touchPos; final Drop game; OrthographicCamera camera; public static Texture backgroundTexture1; Texture btnStart; Texture ponyMain; public MainMenuScreen(final Drop gam) { game = gam; touchPos = new Vector3(); camera = new OrthographicCamera(); camera.setToOrtho(false, 800, 480); backgroundTexture1 = new Texture("bg.png"); btnStart = new Texture("btnStart.png"); ponyMain = new Texture("ponymain.png"); } @Override public void show() { } @Override public void render(float delta) { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); game.batch.setProjectionMatrix(camera.combined); game.batch.begin(); game.batch.draw(backgroundTexture1, 0, 0, 800, 480); game.batch.draw(ponyMain, 10, 0, 780, 309); game.batch.draw (btnStart, 275, 205, 250, 70); game.myfont.draw(game.batch, "Помоги пони собрать яблоки!", 240, 450); game.batch.end(); if (Gdx.input.isTouched()){ game.setScreen(new PonyGame3(game)); dispose(); } } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } @Override public void hide() { } @Override public void dispose() { } }
Код класса GameOverScreen:
package ru.mnogoblog; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Vector3; /** * Created by Константин on 09.06.16. */ public class GameOverScreen implements Screen { final Drop game; OrthographicCamera camera; public static Texture backgroundTexture1; Texture btnReload; Texture korzina; Vector3 touchPos; public GameOverScreen(final Drop gam2) { game = gam2; camera = new OrthographicCamera(); camera.setToOrtho(false, 800, 480); backgroundTexture1 = new Texture("bg.png"); btnReload = new Texture("btnReload.png"); korzina = new Texture("bucket3.png"); touchPos = new Vector3(); } @Override public void show() { } @Override public void render(float delta) { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); game.batch.setProjectionMatrix(camera.combined); game.batch.begin(); game.batch.draw(backgroundTexture1, 0, 0, 800, 480); game.batch.draw(btnReload, 350, 190, 110, 100); game.batch.draw(korzina, 275, 10, 250, 160); game.myfont.draw(game.batch, "Количество набранных яблок: " + PonyGame3.dropsGatchered2, 235, 450); game.batch.end(); if (Gdx.input.isTouched()){ game.setScreen(new PonyGame3(game)); dispose(); } } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } @Override public void hide() { } @Override public void dispose() { } }
На этом всё – игра готова!