воскресенье, 30 января 2011 г.

[Slick] Статья номер 3. Игра, основанная на состояниях.

В этой статье рассмотрим способ построения игры из набора состояний.

На основе класса BasicGame можно создавать вполне успешные простые игры. Однако, в том случае, когда игра становится достаточно сложной, полезно разбивать её на отдельные части, поместив эти части в различные классы, разделив также логику и графику. Эти части называются состояниями игры.



Реализация этой концепции в библиотеке Slick находится к классе StateBasedGame. Состояния создаются с помощью реализации интерфейса GameState. Для удобства реализации этого интерфейса доступен класс BaseGameState (аналогично классу BasicGame для простых игр).

Интерфейс GameState обеспечивает простейший игровой интерфейс, а именно, имеет методы init, render и update. При этом, игры, основанные на состояниях могут иметь несколько различных реализаций состояний, между которыми есть возможность переключаться. Поэтому, логика и отрисовка, связанные с каждой частью игры могут быть оформлены разными классами, что упрощает разработку и отладку готовой программы.

Интересной особенностью данной реализации состояний является наличие различных визуальных эффектов, которые можно применять при переключении между состояниями. Эти визуальные эффекты объявлены и реализованы с помощью интерфейса Transitions.

 Зачем?

Каждая игра обычно состоит из несколько раздельных частей.  Каждый, кто когда-либо играл в компьютерные игры, знает, что после исчезновения заставки игры на экране появится приветствие или главное меню. Далее, если игрок нажимает кнопку "Играть" в главном меню, он знает, что после этого начнётся непосредственно сама игра.

Поэтому, по мере усложнения механизма игры, необходимо использовать механизм игровых состояний. Например, среднестатистическая игра содержит: заставку, игровое меню, меню настроек, введение, собственно сама игра, экран лучших результатов, и, наконец, экран или заставка, информирующая об окончании игры.

Если кто-либо попробует создать все эти состояния использую только класс BasicGame, ему придётся реализовывать эти состояния в методах update и render, что приведёт к чрезмерному разрастанию кода этих методов. Использование игровых состояний решает данную проблему путём деления игры на логические части. То есть, класс MainMenuState будет отвечать только за работу с меню, а класс GamePlayState будет содержать только игровую логику и будет рисовать на экране только игровое поле.

Или вот, например, в игре может содержаться внутренне меню для оперативного изменения настроек. При этом действие в игре должно быть приостановлено и на экране должно отобразиться меню настроек. Без использования состояний это бы пришлось делать в классе основной игры. А при использовании состояний игра просто передаёт управление другому состоянию (назовём его OptionsMenuState) которое содержит код и ресурсы, необходимые для реализации такого меню настроек. При этом пункт главного меню "Настройки" также будет ссылаться на это состояние.

Или, например, игры, где есть два разных игровых процесса (уровень с платформами и некоторый необычный бонусный уровень). Без использования состояний пришлось бы в одном классе совмещать логику двух, совершенно разных по виду игр. А с использованием состояний это легко сделать, создав два разных класса, которые реализуют состояния: PlatformGameplayState и BonusLevelGamePlayState.

В заключении, приведу пример простейшей реализации игровых состояний. Здесь использованы тестовые классы, реализующие три разных состояния:

package slicktemplate;
 
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.tests.states.TestState1;
import org.newdawn.slick.tests.states.TestState2;
import org.newdawn.slick.tests.states.TestState3;
 
public class Game extends StateBasedGame {
 
    static int height = 600;
    static int width = 800;
    static boolean fullscreen = false;
    static boolean showFPS = true;
    static String title = "Slick State Based Game Example";
    static int fpslimit = 60;
 
    public Game(String title) {
        super(title);
    }
 
    @Override
    public void initStatesList(GameContainer gc) throws SlickException {
        addState(new TestState1());
        addState(new TestState2());
        addState(new TestState3());
    }
 
    public static void main(String[] args) throws SlickException {
        try {
            AppGameContainer container = new AppGameContainer(new Game(title));
            container.setDisplayMode(width, height, fullscreen);
            container.start();
        } catch (SlickException e) {
            e.printStackTrace();
        }
    }
}
 

Источник: сайт Wiki-документации проекта Slick: http://slick.cokeandcode.com/wiki/doku.php?id=state_based_games

Комментариев нет:

Отправить комментарий