[Перевод] Разработка HTML5-игр в Intel XDK. Часть 7. Оформление игры

21b4e4f80e884771bc6508cb0f5b6dbe.png
Часть 1 » Часть 2 » Часть 3 » Часть 4 » Часть 5 » Часть 6 » Часть 7 // Конец)
21b4e4f80e884771bc6508cb0f5b6dbe.png

В прошлый раз у нас получилась почти готовая игра. Теперь осталось лишь навести красоту. А именно: сделать систему подсчёта очков, экраны меню и завершения игры, поработать над сложностью. Всем этим сегодня и займёмся.

129e943afa644431b02dc6b0c9a5a0d5.jpg


Система подсчёта очков


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

1. Необязательный шаг. Создайте новый файл «score.js» и дополните соответствующим образом файл project.json.

"jsList" : [
    "src/resource.js",
    "src/biscuit.js",
    "src/score.js",
    "src/game.js"
]


2. Добавьте следующий код в файл score.js, или, если вы решили обойтись без него — в game.js.

var ScoreLayer = cc.Layer.extend({
    score: 0,
    labelScore: null,
    ctor: function() {
        /* Вызываем конструктор суперкласса */
        this._super();
        /* Инициализация */
        this.init();
    },
    init: function() {
        /* Создаём текст для вывода сведений об очках */
        this.labelScore = cc.LabelTTF.create("Score: 0");
        this.labelScore.setColor(cc.color(255, 255, 255, 255));
        this.labelScore.setPosition(cc.p(240, 700));
        this.addChild(this.labelScore);
        
    },
    scoreIncrease: function() {
        /* Увеличиваем набранные очки и обновляем текст */
        this.score += 1;
        this.labelScore.setString("Score: " + this.score);
    }
});


Слой этот устроен довольно просто. У него имеется спрайт, который отвечает за вывод сведений о набранных очках на экран, и метод, который увеличивает число набранных очков на единицу каждый раз, когда его вызывают. Теперь свяжем слой, ответственный за очки, с игрой.

1. Создайте экземпляр ScoreLayer в классе GameScene.

var GameScene = cc.Scene.extend({
    snake_layer: {},
        
score_layer: {},
    onEnter:function () {
        this._super();
        // Добавьте в код строку, расположенную ниже
        this.score_layer = new ScoreLayer();
        this.snake_layer = new SnakeLayer();
        // Добавьте в код строку, расположенную ниже
        this.addChild(this.score_layer, 1);
        this.addChild(this.snake_layer, 0);        
    }
});


2. Настройте SnakeLayer так, чтобы метод scoreIncrease вызывался каждый раз, когда змея съедает печенье. Для этого внесите следующие изменения в метод checkCollision, а именно — туда, где находится проверка на столкновение змеи с печеньем.

checkCollision: function() {
      ...  
      /* Проверка на столкновение с печеньем */
      if (head.x == this.biscuit.x && head.y == this.biscuit.y) {
            /* Увеличиваем число набранных очков */
            this.parent.score_layer.scoreIncrease();
            /* Обновляем позицию печенья */
            this.updateBiscuit();
            /* Увеличиваем длину змеи */
            this.addPart();
      }
      ...        
},


Мы получаем доступ к слою, ответственному за очки, через слой, на котором расположена змея, посредством общего родителя — GameScene, после чего вызываем метод scoreIncrease.

После того, как выполнены вышеописанные изменения игровой экран должен выглядеть так, как показано ниже.

dfed9e38fc18f59c4868cfecabae1605.png


Сведения о набранных очках на игровом экране

Теперь, как только змея съедает очередное печенье, увеличивается число набранных очков.

Экран меню


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

1. Необязательный шаг. Создайте новый файл и назовите его «menu.js». Добавьте его в список файлов в project.json так, как показано ниже.

"jsList" : [
    "src/resource.js",
    "src/biscuit.js",
    "src/score.js",
    "src/menu.js",
    "src/game.js"
]


2. Добавьте следующий код в menu.js, или, если вы решили этот файл не создавать, в game.js.

var MenuScene = cc.Scene.extend({
    titleSprite: {},
    subTitleSprite: {},
    onEnter: function() {
        this._super();
        /* Получим размер окна */
        var winSize = cc.view.getDesignResolutionSize();
        
        /* Создадим заголовок */
        this.titleSprite = cc.LabelTTF.create("Snake.", "Arial", 50);
        this.titleSprite.x = winSize.width / 2;
        this.titleSprite.y = winSize.height / 2;
        this.addChild(this.titleSprite);
        
        /* Создаём подзаголовок */
        this.subTitleSprite = cc.LabelTTF.create("Click anywhere to play", "Arial", 20);
        this.subTitleSprite.x = winSize.width / 2;
        this.subTitleSprite.y = winSize.height / 2 - 80;
        this.addChild(this.subTitleSprite);
        
        /* Добавляем прослушиватель события касания для запуска игры */
        cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            onTouchBegan: function (touches, event) {                
                cc.director.runScene(new GameScene());          
            },
        }, this);
     
    },    
});


При входе в эту сцену мы создаём два текстовых спрайта и добавляем прослушиватель, который ожидает касания экрана (или другого события ввода) для начала игры, то есть — для запуска GameScene.

3. В файле main.js настройте управляющий объект так, чтобы он запускал сцену MenuScene вместо GameScene. Для этого отредактируйте нижеприведённую строку:

cc.director.runScene(new GameScene());


Она должна выглядеть так:

cc.director.runScene(new MenuScene());


Если запустить теперь игру в эмуляторе, то вместо игрового экрана появится экран меню.

dc728064224ed47abe27021e1410fb23.png


Экран меню с предложением начать игру

Экран завершения игры


Последний экран, который мы собираемся создать — это тот, который пользователь видит после завершения игры. Он очень похож на экран главного меню. На нём будут три текстовых спрайта. Один будет содержать текст «Game Over». Второй — отображать набранные в текущем сеансе игры очки, а третий предложит сыграть снова.

1. Необязательный шаг. Создайте новый файл, «gameOver.js». Добавьте его описание в project.json:

"jsList" : [
    "src/resource.js",
    "src/biscuit.js",
    "src/score.js",
    "src/gameOver.js",
    "src/menu.js",
    "src/game.js"
]


2. Вставьте следующий код в файл gameOver.js, или, если на предыдущем шаге вы его не создавали — в game.js.

var GameOverScene = cc.Scene.extend({
    finalScore: 0,
    labelGameOver: {},
    labelScore: {},
    labelPrompt: {},
    ctor: function(score) {
        this._super();
        this.finalScore = score;
        
        /* Прослушиватель события касания, запускает экран меню */
        cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            onTouchBegan: function(touch, event) {
                cc.director.runScene(new MenuScene());
            }
        }, this);
        
    },
    onEnter: function() {
        this._super();
        /* размер окна */
        var winSize = cc.view.getDesignResolutionSize();
        
        /* Надписи для сцены GameOver */
        this.labelGameOver = new cc.LabelTTF("Game Over", "Arial", 60);    
        this.labelGameOver.x = winSize.width * 0.50;
        this.labelGameOver.y = winSize.height * 0.50;
        this.addChild(this.labelGameOver);
        
        /* Надпись, содержащая сведения о набранных очках */        
        this.labelScore = new cc.LabelTTF("Score: " + this.finalScore, "Arial", 30);
        this.labelScore.x = winSize.width * 0.50;
        this.labelScore.y = winSize.height * 0.43;
        this.addChild(this.labelScore);
        
        /* Предложение сыграть снова */
        this.labelPrompt = new cc.LabelTTF("Click or Tap To Try Again");
        this.labelPrompt.x = winSize.width * 0.50;
        this.labelPrompt.y = winSize.height * 0.39;
        this.addChild(this.labelPrompt);
    },
});


Обратите внимание на то, что в конструктор сцены передаётся параметр, содержащий сведения о набранных очках. Если этого не сделать, сцена не сможет правильно выполнять свои функции.

1. Добавьте обращение к управляющему объекту для того, чтобы запустить сцену GameOverScene, передав конструктору сведения о набранных очках. Сделать это нужно после того, как произойдёт столкновение головы змеи с одним из фрагментов её тела.

var SnakeLayer = cc.Layer.extend({
...
    checkCollision: function() {
        
...
        /* Проверка на столкновение с собственным фрагментом */
        for (var part = 1; part < body.length; part++) {
            if (head.x == body[part].x && head.y == body[part].y) {
                /* Запуск сцены GameOver */
                //this.snakeParts = null;
               // Добавьте эту строку ниже
                cc.director.runScene(
                new GameOverScene
                  (this.parent.score_layer.score)
                );
            }
        }    
        ...
    },
        
...
});


Теперь, в случае проигрыша, появится такой экран.

pqouOOkSP2Ox7zK8lLIuZScGOAY4iuziC_qupeXj


Экран завершения игры

Настройка сложности игры


И, наконец, нужно увеличивать сложность игры, основываясь на том, сколько очков набрал пользователь. Если змейка постоянно движется с одной и той же скоростью, играть в Snake довольно просто, а значит — скучно.

1. Добавьте в код SnakeLayer следующий метод.

updateDifficulty: function(curScore) {
var scoreToDiff = {};

/* Задаём уровни сложности путём настройки соответствия количества набранных очков и временного интервала, используемого для управления скоростью перемещения змеи */

scoreToDiff[0] = 0.15;
scoreToDiff[5] = 0.10;
scoreToDiff[15] = 0.05;
scoreToDiff[25] = 0.03;
scoreToDiff[35] = 0.01;

/* Обновляем интервал */
        
if (scoreToDiff[curScore] !== undefined) {
this.interval = scoreToDiff[curScore];
}        
},


2. Задайте вызов метода updateDifficulty в моменты, когда змея съедает печенье и при создании слоя SnakeLayer.

var SnakeLayer = cc.Layer.extend({
    ...
    ctor: function () {
        
  ...
        // Добавьте код ниже
        /* Инициализация подсистемы управления сложностью */
        this.updateDifficulty();
    },    
    ...
    checkCollision: function() {
        /* Проверяем столкновение с печеньем */
        if (head.x == this.biscuit.x && head.y == this.biscuit.y) {
            /* Увеличиваем очки */
            this.parent.score_layer.scoreIncrease();
            /* Обновляем позицию печенья */
            this.updateBiscuit();
            /* Увеличиваем длину змеи */
            this.addPart();
            // Добавьте код ниже 
            /* Увеличим сложность, если набрано соответствующее следующему уровню сложности количество очков */
            this.updateDifficulty(this.parent.score_layer.score);
        }                
    },
    ...
});


Выводы


Итак, сегодня вы узнали:

  • Как создать экран меню.
  • Как создать экран завершения игры.
  • Как создать систему подсчёта очков.
  • Как настраивать сложность игры.


Игра готова! Примите поздравления с успешным освоением этого учебного руководства, и с тем, что вы создали свою первую HTML5-игру в Intel XDK! Испытайте игру, выясните, всё ли хорошо работает, измените её так, как вам захочется. А, если что-то в её функционировании вам всё ещё непонятно, разберитесь с этим.

Для того чтобы узнать подробности о том, как собрать дистрибутив игры для различных платформ, таких, как iOS, Android и Windows 8, загляните в документацию по Intel XDK.

Теперь — самое время заняться собственным проектом.

21b4e4f80e884771bc6508cb0f5b6dbe.png
Часть 1 » Часть 2 » Часть 3 » Часть 4 » Часть 5 » Часть 6 » Часть 7 // Конец)
21b4e4f80e884771bc6508cb0f5b6dbe.png

© Habrahabr.ru