LIBGDX TUTORIAL - игра в стиле "RUNNING GAME" с libGDX - Часть 1

Я всегда любил 2D игры в стиле running. Когда получил свой первый Android смартфон, я играл в iRunner 4 часа и в тот момент я серьёзно хотел создать игру как эта. Много времени прошло с этого момента, но в итоге я сделал простую, игру в стиле “running” используя libGDX. Последняя версия, основанная на этом руководстве доступно в Google Play.
LibGDX – это один из лучших проектов за которыми я следил в последние несколько лет и когда я начал искать разницу в фреймворках для создания игр, он определенно обеспечивал лучшие возможности и лучшие характеристики для моего телефона. Если у Вас есть время, я рекомендую прочитать этот пост создателя о выпуске версии 1.0.

Я создал эту игру, как учебное задание, используя libGDX scene2d и box2d библиотеки в моё свободное время. Код не идеально, но я надеюсь это поможет Вам выбрать правильный путь, если Вы собираетесь создать следующую «Превосходную игру». И так, хотя libGDX – это кросс-платформенный фреймворк, Я планировал только Android-версию, как конечную платформу для релиза и также я собирался сделать desktop – версию для тестов.

Примечание: Я не хочумного описывать libGDX или box2d, так как они уже имеют превосходную документацию. Я только направлю Вас через мою собственную реализацию игры используя эти инструменты. Если Вы не поняли почему я использовал определенные лкассы или что физика тела я настойчиво предлагаю поискать в libGDX’s wiki перед тем, как двигаться дальше.

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

Martian RUN!
Это придурковатая история, которую я придумал: Вы пришелец и гигантские насекомые атакуют твой город! Ваша цель, бежать столько, сколько сможете избегая насекомых.

Управление
Здесь только один путь избежать насекомых: перепрыгивать или уклоняться. Кнопка прыжка будет справа экрана, а кнопка уклонения будет слева экрана.

С нашим превосходным дизайном закончено. Давайте приступим к созданию игры!

Создание проекта
Так выглядят необходимые настройки:
Когда вы кликните «Generate” Gradle clean task будет запущен и все библиотеки будут загружены. Вы должны увидеть вывод как:
Generating app in /Users/wilmor24/Downloads/martianrun
Executing '/Users/wilmor24/Downloads/martianrun/gradlew clean --no-daemon'
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: http://gradle.org/docs/2.2/userguide/gradle_daemon.html.
Parallel execution with configuration on demand is an incubating feature.
:android:clean
:desktop:clean
:core:clean UP-TO-DATE
:desktop:clean UP-TO-DATE
:android:clean UP-TO-DATE

BUILD SUCCESSFUL

Total time: 12.395 secs
Done!
To import in Eclipse: File -> Import -> Gradle -> Gradle Project
To import to Intellij IDEA: File -> Import -> build.gradle
To import to NetBeans: File -> Open Project...


Я не буду импортировать проект в IDE, так как это часть настройки проекта libGDX и Вы можете установить, какую IDE использовать. (Если интересно, я использую Intellij IDEA 14 во время написания этого руководства).

После успешного созданий проекта на desktop и Android, я обычно убираю шаблонный код установленный libGDX. Это означает удаление изображения badlogic.jpg, которое добавляется в папку assets folder, а также очищаю мой game класс, как ниже:

package com.gamestudio24.martianrun;

import com.badlogic.gdx.ApplicationAdapter;

public class MartianRun extends ApplicationAdapter {

    @Override
    public void create() {

    }

    @Override
    public void render() {

    }
}


Приступим к работе
Первая вещь, которую мы будем делать – это сделаем наш game класс наследующийся от Game, так мы сможем поддерживать многоэкранность. Мы не будем использовать многоэкранность для этой игры, но я рекомендую сделать это в случае, если вы хотите добавить многоэкранность в будущем, например заставка, экран меню, доска лидеров и.т.д.
Моё game класс теперь выглядит так:
package com.gamestudio24.martianrun;

import com.badlogic.gdx.Game;

public class MartianRun extends Game {

    @Override
    public void create() {

    }

}


Теперь создадим GameScreen класс внутри только что созданного пакета:
Примечание: Предположим все классы/пакеты были добавлены/изменены внутри нашего основного модуля, если не указано иное

package com.gamestudio24.martianrun.screens;

import com.badlogic.gdx.Screen;

public class GameScreen implements Screen {

    @Override
    public void render(float delta) {

    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void show() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void dispose() {

    }

}


После создания нам нужно установить в нашем game классе наш GameScreen на запуск.

package com.gamestudio24.martianrun;

import com.badlogic.gdx.Game;
import com.gamestudio24.martianrun.screens.GameScreen;

public class MartianRun extends Game {

    @Override
    public void create() {
        setScreen(new GameScreen());
    }

}

Последняя вещь, которую нам нужно сделать для нашей настройки – это установить ширину и высоту нашей игры. Мы сделать игру 480x800. Давайте установим эти значения в Constants классе внутри пакета utils.

package com.gamestudio24.martianrun.utils;

public class Constants {

    public static final int APP_WIDTH = 800;
    public static final int APP_HEIGHT = 480;

}

В конце, сформируем DesktopLauncher, так, чтобы это использовало корректные измерения:

package com.gamestudio24.martianrun.desktop;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.gamestudio24.martianrun.MartianRun;
import com.gamestudio24.martianrun.utils.Constants;

public class DesktopLauncher {
    public static void main (String[] arg) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.width = Constants.APP_WIDTH;
        config.height = Constants.APP_HEIGHT;
        new LwjglApplication(new MartianRun(), config);
 }
}

Отправимся дальше и запустим проект. До этого, мы установили игру с экраном запускаемым 480x800 окном.

Страница для физики мира

Теперь мы начнём создавать физику нашего мира. Он состоит из земли, бегуна и врагов. Хотя наш бегун будет бежать через город, мы вообще-то не будем двигать тело нашего бегуна вдоль оси x-координат, но сделаем врагов движущихся к бегуну. Это будет создавать иллюзию его движения вперёд с sprite – анимацией.
Box2d делает это простым контроль тел и контроль их физики, как прыжки, движение, столкновения и.т.д. Если Вы не знает box2d, я рекомендую взглянуть на документацию.
Наши тела будут созданы, как следующие:
1. Ground. Статичное тело
2. Runner. Динамичное тело.
3. Enemies. Кинематичные тела
Давайте сделаем класс, который позаботиться о создании наших тел. Создайте WorldUtils класс внутри нашего utils пакета и создайте функцию установки ground.

package com.gamestudio24.martianrun.utils;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;

public class WorldUtils {

    public static World createWorld() {
        return new World(Constants.WORLD_GRAVITY, true);
    }

    public static Body createGround(World world) {
        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set(new Vector2(Constants.GROUND_X, Constants.GROUND_Y));
        Body body = world.createBody(bodyDef);
        PolygonShape shape = new PolygonShape();
        shape.setAsBox(Constants.GROUND_WIDTH / 2, Constants.GROUND_HEIGHT / 2);
        body.createFixture(shape, Constants.GROUND_DENSITY);
        shape.dispose();
        return body;
    }

}

Новая константа добавлена в наш Constants класс следующим образом:

package com.gamestudio24.martianrun.utils;

import com.badlogic.gdx.math.Vector2;

public class Constants {

    public static final int APP_WIDTH = 800;
    public static final int APP_HEIGHT = 480;

    public static final Vector2 WORLD_GRAVITY = new Vector2(0, -10);

    public static final float GROUND_X = 0;
    public static final float GROUND_Y = 0;
    public static final float GROUND_WIDTH = 50f;
    public static final float GROUND_HEIGHT = 2f;
    public static final float GROUND_DENSITY = 0f;

}

Давайте взглянем на то, что мы только что сделали. Мы определили утилиту класс WordUtils, который будет заботиться о создании компонентов нашего мира. Сейчас мы будем только создавать землю и сам мир. Землю создается как статическое тело с длинной 25 метров и шириной 2 метра и это создаётся как коробка. На самом деле, все наши тела будут коробками различных форм.
Мир создан с графитацией -10 m/s^2. Box2d работает отлично, когда используются реальные физические значение. На самом деле документация о багах, если использовать преувеличенные мировые значения.
И так, мы имеем эти функции создания мира и земли, но где мы можем использовать их? Мы могли бы использовать их внутри нашего GameScreen; вместо, мы будем добавлять их в Stage, который будет добавлен в GameScreen. Stage – это часть scene2d и процессор ввода, который может хранить много Actor объектов и обрабатывать их изображения и входящие события
Мы будем добавлять Actors позже, но лучше установить Stage сейчас, так чтобы не переносить код из GameScreen позже.
Создайте GameStage внутри stages пакета. Этот класс будет создавать расширенный libGDX Stage класс. В конструктора мы будем использовать наш WorldUtils класс для создания мира и земли. На этой точке мы будем использовать Box2DDebugRender для отображения, того, что мы создали до сих пор. Мы будем использовать sprites позже, когда мы, будем уметь комфортно работать с физикой. Код следующий:
package com.gamestudio24.martianrun.stages;


import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.gamestudio24.martianrun.utils.WorldUtils;

public class GameStage extends Stage {

    // This will be our viewport measurements while working with the debug renderer
    private static final int VIEWPORT_WIDTH = 20;
    private static final int VIEWPORT_HEIGHT = 13;

    private World world;
    private Body ground;

    private final float TIME_STEP = 1 / 300f;
    private float accumulator = 0f;

    private OrthographicCamera camera;
    private Box2DDebugRenderer renderer;

    public GameStage() {
        world = WorldUtils.createWorld();
        ground = WorldUtils.createGround(world);
        renderer = new Box2DDebugRenderer();
        setupCamera();
    }

    private void setupCamera() {
        camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0f);
        camera.update();
    }

    @Override
    public void act(float delta) {
        super.act(delta);

        // Fixed timestep
        accumulator += delta;

        while (accumulator >= delta) {
            world.step(TIME_STEP, 6, 2);
            accumulator -= TIME_STEP;
        }

        //TODO: Implement interpolation

    }

    @Override
    public void draw() {
        super.draw();
        renderer.render(world, camera.combined);
    }

}

Вы вероятно заметили Fixed timestep комментарий внутри функции render.
Как libGDX box2d документация говорит, моделирование – это отдельная тема. Я следую этой статье для реализации моей версии фиксированного timestep. Мы наверное должны реализовать интерполяцию, но я оставил это, как сейчас.
В конце, давайте запустим GameStage внури нашего GameScreen. Мы будем вызывать act и draw внутри функции render.


package com.gamestudio24.martianrun.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.gamestudio24.martianrun.stages.GameStage;

public class GameScreen implements Screen {

    private GameStage stage;

    public GameScreen() {
        stage = new GameStage();
    }

    @Override
    public void render(float delta) {
        //Clear the screen
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        //Update the stage
        stage.draw();
        stage.act(delta);
    }

    //Rest of the code
    ...

}

Запустим игру и Вы увидите зеленую линию внизу, которая является контуром коробки, которую мы добавили в наш мир(the ground). Ваша игра должна выглядеть как это изображение:


Оригинал: williammora.com/a-running-game-with-libgdx-part-1/
Перевод: eger.
eger / 1 июня 2015, 22:29
1

1 комментарий
admin - 1 июня 2015, 23:56
Отличное начало! Так держать!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.