Статьи

Разработка игр для Firefox с использованием Ionic Framework

Мне, вероятно, не нужно много говорить о Firefox OS, так как многие из вас уже много знают об этом. Если нет, у нас есть несколько отличных статей на тему SitePoint, это хорошая отправная точка.

Все, что вам нужно знать для этого урока, это то, что приложения Firefox OS — это просто веб- приложения, которые программируются на HTML5, CSS и JavaScript.

Я собираюсь создать простую игру под названием YALG , Another Another Logo Game .

Что нам нужно?

Во-первых, браузер Mozilla Firefox . У большинства из нас нет устройства с ОС Firefox, эмулятор ОС Firefox представляет собой плагин Firefox, вы можете узнать, как его установить здесь .

Я решил использовать фреймворк под названием Ionic для этого проекта.

Почему ионный?

  • Это просто и имеет отличную документацию
  • Это позволяет для кроссплатформенной разработки, используя ее основанный на Cordova CLI
  • Он основан на AngularJS, одной из лучших платформ Javascript
  • Ориентирован на мобильные устройства

Начиная проект

Сначала установите Ionic, вы можете сделать это, следуя нашему руководству по Ionic . Затем с помощью инструмента Ionic CLI выполните:

ionic start YALG blank
cd YALG
ionic platform add firefoxos 
# You can add more platforms as required

Это создаст новый пустой Ionic Project с поддержкой Firefox OS (вы можете захотеть изменить некоторые вещи в файле config.xml

Теперь выполните:

 cordova prepare firefoxos

Это делает ваше приложение готовым к развертыванию в Firefox OS.

Чтобы запустить новое приложение в эмуляторе, добавьте products/firefox/www

Настройка Firefox OS

Вы должны увидеть что-то подобное в эмуляторе:

Скриншот ионного стартера

Теперь мы внесем некоторые изменения в исходный код в папке www

Во-первых, откройте файл index.html Измените его содержание на это:

 <!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title>YALG</title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <script src="js/app.js"></script>
  </head>
  <body ng-app="yalg">

      <ion-nav-view>
          <!-- View Goes Here -->
      </ion-nav-view>

  </body>
</html>

Если вы не знакомы с AngularJS, вы можете заметить пару странных вещей. Одним из них является ng-app="yalg" Это способ сообщить HTML-странице, что она должна работать как угловой проект, управляемый угловым модулем под названием yalg

Еще один — ion -nav-view Это директива HTML, созданная Ionic Framework и используемая для загрузки различных представлений, так как AngularJS является платформой MVC. Эти представления определены в файле app.js

 var app = angular.module('yalg',['ionic']);

app.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
    $stateProvider.
        state('main', {
            url         : '/',
            templateUrl : 'templates/main.html',
            controller  : 'MainCtrl'
        }).
        state('levels', {
            url         : '/levels',
            templateUrl : 'templates/levels.html',
            controller  : 'LevelsCtrl'
        }).
        state('level', {
            url         : '/level/:levelId',
            templateUrl : 'templates/level.html',
            controller  : 'LevelCtrl'
        }).
        state('logo', {
            url         : '/level/:levelId/logo/:logoId',
            templateUrl : 'templates/logo.html',
            controller  : 'LogoCtrl'
        }). 
        state('about', {
            url         : '/about',
            templateUrl : 'templates/about.html',
            controller  : 'MainCtrl'
        });

    $urlRouterProvider.otherwise('/');

    /**
     * Firefox OS only
     * @see http://goo.gl/cKJyRm
     */
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|app):/);
});

Используя angular.moduleyalg Далее мы определяем различные представления и то, как каждое из них будет достигнуто приложением. Мы делаем это путем создания различных состояний приложения.

Для каждого отдельного представления мы добавляем состояние, определенное с помощью имени состояния, и объект, содержащий URL-адрес состояния, шаблон ( т.е. представление) и контроллер, который мы создадим позже.

Если мы перейдем к #/templates/main.htmlion -nav-view> Если мы перейдем к #/abouttemplates/about.html Если мы перейдем к неизвестному URL-адресу, будет загружено содержимое templates/main.html$urlRouterProvider.otherwise('/'); ,

Последняя строка кода — это способ исправить проблему с Firefox OS с маршрутами AngularJS. Если вы планируете протестировать это приложение на любой другой платформе, удалите последнюю строку кода.

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

 

Папка www
|---- css
| |---- style.css
|
|---- img
|---- js
| |---- app.js
|
|---- lib
|---- templates
|---- about.html
|---- level.hmtl
|---- levels.html
|---- logo.html
|---- main.html

Добавьте это в файл lib

 templates/main.html

Если вы не распознаете какие-либо теги HTML, найдите их в документации Ionic Framework . Ionic добавляет много полезных тегов / угловых директив.

Теперь давайте добавим немного стиля к этому представлению, отредактировав файл <ion-pane>
<ion-header-bar class="bar-positive">
<h1 class="title">{{appname}}</h1>
</ion-header-bar>

<ion-content class="content">

<div class="main-view">
<ul>
<li>
<a target="_blank" href="#/levels">
<button class="button button-positive main-button">Start Game</button>
</a>
<br>
</li>

<li>
<a target="_blank" href="#/about">
<button class="button button-positive main-button">About</button>
</a>
</li>
</ul>
</div>

</ion-content>
</ion-pane>

 css/style.css

Возможно, вы заметили, что заголовок представления .content {
text-align: center;
padding-top: 8%;
}

.button.main-button {
border-radius: 10px;
width: 300px;
}

ul li {
padding: 8px;
}
Мы не хотим этого, мы хотим, чтобы название было {{appname}} Поскольку это Angular-проект, он использует Angular-шаблоны, а все, что находится между YALG{{

Мы добавили контроллер с именем }} Теперь мы создаем этот контроллер. Добавьте это в файл MainCtrl

 js/app.js

Поскольку app.controller('MainCtrl', ['$scope',
function($scope) {
$scope.appname = "YALG";
$scope.descr = "Yet Another Logo Game";
}]);
main.html{{appname}}

Бегать:

 $scope.appname

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

Приложение работает с кнопками

Нажатие на кнопки ничего не изменит, так как мы не добавили их представления. Добавьте это в cordova prepare firefoxos

 templates/about.html

Здесь мы добавили кнопку возврата с Ionicon . Вот что вы должны увидеть в симуляторе после перезагрузки приложения:

О странице, запущенной в приложении

После нажатия кнопки « <ion-pane>
<ion-header-bar class="bar-positive">
<a target="_blank" href="#/">
<button class="button icon-left ion-chevron-left button-clear button-white">
</button></a>

<h1 class="title">About</h1>
</ion-header-bar>
<ion-content class="content">

<div class="about-view">
{{appname}} <br>
{{descr}}
</div>

</ion-content>
</ion-pane>
Поэтому мы сначала создаем список всех уровней, создавая файл Start Game

 data/levels.json

Я только создал два уровня с двумя логотипами на уровень, но вы можете добавить больше, следуя той же логике. Причина, по которой мы создаем этот [
{
"id" : 1,
"name" : "Level 1",
"content" : {
"logo_num" : 2,
"logos" : [
{
"id" : "sitepoint",
"name" : "Sitepoint",
"img" : "img/lvl1/sitepoint.jpg"
},
{
"id" : "fb",
"name" : "Facebook",
"img" : "img/lvl1/fb.png"
}
]
}
},

{
"id" : 2,
"name" : "Level 2",
"content" : {
"logo_num" : 2,
"logos" : [
{
"id" : "twitter",
"name" : "Twitter",
"img" :"img/lvl2/twitter.jpg"
},
{
"id" : "android",
"name" : "Android",
"img" : "img/lvl2/android.jpg"
}
]
}
}
]
JSON

Все, что нам нужно, это получить содержимое ng-repeat Итак, начнем с реализации data/levels.json Добавьте это в файл LevelsCtrl

 js/app.js

Это так просто. Вы заметили здесь внедрение зависимости от Angular, когда сервис app.controller('LevelsCtrl', ['$scope','$http',
function($scope,$http) {

//getting list of levels
$http.get('data/levels.json').success(function(data) {
$scope.levels = data;
});
}]);

Теперь, чтобы создать представление, добавьте этот код в ваш $http

 template/levels.html

Просто для удовольствия, добавьте это в файл <ion-pane>
<ion-header-bar class="bar-positive">
<a target="_blank" href="#/">
<button class="button icon-left ion-chevron-left button-clear button-white">
</button></a>
<h1 class="title">Levels</h1>
</ion-header-bar>

<ion-content class="content">

<ul class="level-list">
<li ng-repeat="lvl in levels" class="level-card">
<a target="_blank" href="#/level/{{lvl.id}}">
<button class="button button-positive level-button">{{lvl.name}}</button><br>
</a>
</li>
</ul>

</ion-content>
</ion-pane>

 css/style.css

И это вид, который вы получите, нажав кнопку « .level-button {
height: 150px;
width: 150px;
border-radius: 8px;
}

Уровни в приложении

Нажатие на них не сработает … пока!

Теперь мы реализуем другое представление, Start Game Этот файл покажет все логотипы для одного уровня (в данном случае 2 логотипа).

Сначала создайте файлы изображений, как они показаны в templates/level.html Добавьте это дерево каталогов в папку data/levels.json

 www

Теперь добавьте это в ваш файл img
|---- lvl1
| |---- fb.png
| |---- sitepoint.jpg
|
|---- lvl2
|---- twitter.jpg
|---- android.jpg

 template/level.html

Если вы разрабатываете для другой платформы, все, что вам нужно сделать, это поместить этот код между тегами <ion-pane>
<ion-header-bar class="bar-positive">
<a target="_blank" href="#/levels">
<button class="button icon-left ion-chevron-left button-clear button-white">
</button></a>
<h1 class="title">{{lvl.name}}</h1>
</ion-header-bar>
<ion-content class="content">

<ul id="logo-list">

</ul>

</ion-content>
</ion-pane>

 ul

К сожалению, <li ng-repeat="logo in lvl.content.logos">
<a target="_blank" href="#/level/{{levelId}}/logo/{{logo.id}}">
<img ng-src="{{logo.img}}" class="logo-img">
</a>
</li>
ng-src

 js/app.js

Здесь вы можете увидеть еще одно внедрение зависимостей app.controller('LevelCtrl', ['$scope', '$stateParams', '$http',
function($scope,$stateParams,$http){
$scope.levelId = $stateParams.levelId;

//getting list of levels
$http.get('data/levels.json').success(function(data) {
$scope.levels = data;
for (var i=0;i<$scope.levels.length;i++) {
if($scope.levels[i].id == $scope.levelId) {
// lvl is the clicked level
$scope.lvl = $scope.levels[i];
break;
}
}

var logoList = angular.element(document.querySelector('#logo-list'));
var cnt = ""; //content of logoList
for (var i=0;i<$scope.lvl.content.logos.length;i++) {
var currLogo = $scope.lvl.content.logos[i];

cnt += '<li>'+
'<a target="_blank" href="#/level/'+$scope.levelId+'/logo/'+currLogo.id+'">' +
'<img src="'+currLogo.img+'" class="logo-img">'+
'</a>'+
'</li>';
}
//set the desired content
logoList.html(cnt);

});
}]);
$stateParams Этот сервис Angular используется для доступа к параметрам в URL. Когда мы создали состояние для этого представления, мы определили URL как /level/:levelId Здесь :levelId$stateParams

Как вы можете видеть, используя это

 angular.element(document.querySelector('#logo-list'));

мы выбрали элемент DOM, так же, как с помощью

 $('#logo-list')

в jQuery.

AngularJS поставляется с небольшим подмножеством jQuery, называемым jqLite . Используя это подмножество, мы можем поместить желаемый контент между тегами ul

Это представление, которое вы получите после перезагрузки симулятора:

Пример уровня

В настоящее время ничего не произойдет, когда вы нажмете логотипы. Нам все еще нужно добавить другое представление, последнее представление, templates/logo.html Добавьте этот код к нему:

 <ion-pane>
  <ion-header-bar class="bar-positive">
    <a ng-href="#/level/{{lvl.id}}">
    <button class="button icon-left ion-chevron-left button-clear button-white">
    </button></a>
  </ion-header-bar>

  <ion-content class="content">

    <div class="logo">
      <img src="" alt="{{logo.img}}" id="logo-img">
    </div>

     <div class="item item-input">
        <input type="text" name="logoName" ng-model="logo_name">
        <button class="button button-small button-royal" ng-click="check(logo_name)">
            Check
        </button>

    </div>

  </ion-content>
</ion-pane>

Также добавьте этот контроллер в js/app.js

 app.controller('LogoCtrl', ['$scope','$stateParams','$http',
    function($scope,$stateParams,$http){
        $scope.levelId = $stateParams.levelId;
        $scope.logoId = $stateParams.logoId;

        //getting list of levels
        $http.get('data/levels.json').success(function(data) {
            $scope.levels = data;
            for (var i=0;i<$scope.levels.length;i++) {

                //level found
                if($scope.levels[i].id == $scope.levelId) {
                    $scope.lvl = $scope.levels[i];
                    break;
                }
            }

            for (var i=0;i<$scope.lvl.content.logos.length;i++) {
                //getting the clicked logo as $scope.logo
                if($scope.lvl.content.logos[i].id == $scope.logoId) {
                    $scope.logo = $scope.lvl.content.logos[i];
                    break;
                }
            }

            var img = angular.element(document.querySelector('#logo-img'));
            img.attr('src',$scope.logo.img); //loading the image
        });
}]);

Используя ту же технику, что и в последнем контроллере, мы загружаем изображение нажатого логотипа. Теперь последнее, что нужно сделать, это добавить немного CSS:

 .logo-img {
    height: 70px;
    width: auto;
}

.logo {
    padding-bottom: 20px;
}

.button.button-small {
    padding: 5px 20px;
}

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

Логотип уровня

Вывод

У нас пока нет работающей игры, но у нас есть ее структура и работающий пользовательский интерфейс. В следующей части этого урока мы добавим функциональность, чтобы превратить это в настоящую игру!