Это продолжение моей прошлой статьи "Создаем html5 мини-бродилку на CraftyJS". Я подумал, сейчас так много возможностей относительно просто портировать любое html5 приложение на мобильную платформы, почему бы не попробовать?

Ниже, то что из этого вышло. Внимательно читаем вывод!
Нужно портировать игру бродилку на android, сделать краткий вывод статистики и управление по средствам акселерометра.
С начала, выслушав критику к прошлой статье, я убрал из index.html множественные вызовы js файлов, оставив только главные библиотеки. Для этого я подключил библиотеку requirejs. Так же я сразу подключил phonegap.js и немного изменил верстку, вот как теперь все это выглядит:
/index.html
/css/game.css
/js/game.js
Обратите внимание, что я так же изменил width и height в соответствие с разрешением мобильного телефона.
Теперь давайте займемся управлением, для это изменим /js/objects/player.js заменив компонент Fourway на FourwayAccel, а так же вызов this.fourway(1) на this.fourway_accel(1). Дальше, нам нужно создать этот самый компонент, вот он:
После вызова метода fourway_accel, мы начинаем слушать событие «Acceleration», которое мы создадим чуть позже. Данное событие передает нам данные о наклоне (x,y,z). Нас тут интересует только x и y. Для упрощения, я проверяю достаточно большой уровень наклона, меньше -2 или больше 2.
Как только наклон достиг определенного градуса, вызывается функция «start_or_stop_move», которой передается направление наклона. Данная функция, в зависимости от скорости задает направление движения игрока, которое потом отрисовывается в событие «EnterFrame».
Дальше нам нужно создать сам генератор события «Acceleration», для этого добавим следующий код в /js/game.js:
Более подробно, о работе с акселерометром в phonegap, можно прочесть в документации.
Теперь, нам нужно вызвать startWatch() в сцене /js/scenes/main.js, а так же stopWatch() в сценах win.js и lose.js
Итак, будем считать что вы уже сделал все, что описано в документации. Нужно немного подправить AndroidManifest.xml, добавив в секцию activity строчку: android:screenOrientation=«landscape». Это необходимо для того, что бы ориентация экрана всегда была альбомной.
Приводим AndroidrpgActivity.java к такому виду:
Думаю переменная FLAG_FULLSCREEN говорит сама за себя.
Вот, что у меня в итоге получилось (извините за качество):

Работает? О да! Доволен ли я? О нет!
Дело в том, что толи я криворукий, толи лыжи не едут, но приложение получилось крайне тормазнутым. Результат больше похож на пошаговую стратегию, чем на Action. И дело тут, я думаю, все же в лыжах, ответ наверное очевиден. PhoneGap — отличная библиотека для tumblr читалок и прочих новостных ридеров, но для игрушек лучше использовать нативный для android Java.
Исходники, как обычно на GitHub.

Ниже, то что из этого вышло. Внимательно читаем вывод!
Что нам потребуется
- PhoneGap и окружение для работы с ним (инструкция по установке)
- Проект из предидущей статьи
- Крайне желательно наличие android телефона
Задача
Нужно портировать игру бродилку на android, сделать краткий вывод статистики и управление по средствам акселерометра.
Предварительная подготовка
С начала, выслушав критику к прошлой статье, я убрал из index.html множественные вызовы js файлов, оставив только главные библиотеки. Для этого я подключил библиотеку requirejs. Так же я сразу подключил phonegap.js и немного изменил верстку, вот как теперь все это выглядит:
/index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/phonegap.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/crafty.js"></script>
<script type="text/javascript" src="js/game.js"></script>
<link rel="stylesheet" href="css/game.css" type="text/css" media="screen" charset="utf-8">
<title>Simpe RPG</title>
</head>
<body>
<div id="cr-stage"></div>
<div id="sidebar">
<div id="level">
Level:
<span>1</span>
</div>
<div id="score">
Score:
<span>0</span>
</div>
</div>
</body>
</html>
/css/game.css
body, html { margin:0; padding: 0; overflow:hidden; font-family:Arial; font-size:20px; background-color: #000; }
#cr-stage { color:white; float:left; }
#sidebar { top: 0; left: 0; width: 150px; height: 100px; position: absolute; color:white;}
#sidebar div { margin: 10px 5px; text-align: center; }
/js/game.js
var Settings = {
width: 480, // ширина игрового поля
height: 320, // высота
poligon: 16, // размер полигона 16x16
level: 1, // текущий уровень
flower_count: 0 // цветков на уровне
};
var AllScripts = [
// objects
'js/objects/flower',
'js/objects/bush',
'js/objects/grass',
'js/objects/unit',
'js/objects/fourway_accel',
'js/objects/player',
'js/objects/fourway_ai',
'js/objects/monster',
// scenes
'js/scenes/loading',
'js/scenes/main',
'js/scenes/win',
'js/scenes/lose'
];
require(AllScripts, function() {
require.ready(function() {
Crafty.init(Settings.width, Settings.height); // создаем игровое поле
// подгружаем спрайт
Crafty.sprite(Settings.poligon, "images/sprite.png", {
grass1: [0,0],
grass2: [1,0],
grass3: [2,0],
grass4: [3,0],
flower: [0,1],
bush1: [0,2],
bush2: [1,2],
player: [0,3],
monster: [0,4]
});
// запускаем первую сцену
Crafty.scene("loading");
});
});
Обратите внимание, что я так же изменил width и height в соответствие с разрешением мобильного телефона.
Акселерометр
Теперь давайте займемся управлением, для это изменим /js/objects/player.js заменив компонент Fourway на FourwayAccel, а так же вызов this.fourway(1) на this.fourway_accel(1). Дальше, нам нужно создать этот самый компонент, вот он:
Crafty.c("FourwayAccel", {
_speed: 3,
_touch_element: null,
init: function() {
this._movement= { x: 0, y: 0};
this.accels = {};
this.accels['left'] = false;
this.accels['right'] = false;
this.accels['top'] = false;
this.accels['bottom'] = false;
},
fourway_accel: function(speed) {
var self = this;
self._speed = speed;
self.bind('Acceleration', function(acceleration) {
if (acceleration.y < -2) this.start_or_stop_move('left');
if (acceleration.y > 2) this.start_or_stop_move('right');
if (acceleration.x < -2) this.start_or_stop_move('top');
if (acceleration.x > 2) this.start_or_stop_move('bottom');
});
self.bind("EnterFrame",function() {
if (self.disableControls) return;
if(self._movement.x !== 0) {
self.x += self._movement.x;
self.trigger('Moved', {x: self.x - self._movement.x, y: self.y});
}
if(self._movement.y !== 0) {
self.y += self._movement.y;
self.trigger('Moved', {x: self.x, y: self.y - self._movement.y});
}
});
return self;
},
start_or_stop_move: function(move_type) {
var move_speed = this.get_speed(move_type);
if (this.accels[move_type]) {
// stop move
this._movement.x = Math.round((this._movement.x - move_speed.x)*1000)/1000;
this._movement.y = Math.round((this._movement.y - move_speed.y)*1000)/1000;
this.accels[move_type] = false;
} else {
// start move
this.accels[move_type] = true;
this._movement.x = Math.round((this._movement.x + move_speed.x)*1000)/1000;
this._movement.y = Math.round((this._movement.y + move_speed.y)*1000)/1000;
}
this.trigger('NewDirection', this._movement);
},
get_speed: function(key_id) {
switch (key_id) {
case 'top':
return {x: 0, y: -this._speed};
case 'left':
return {x: -this._speed, y: 0};
case 'right':
return {x: this._speed, y: 0};
case 'bottom':
return {x: 0, y: this._speed};
}
}
});
После вызова метода fourway_accel, мы начинаем слушать событие «Acceleration», которое мы создадим чуть позже. Данное событие передает нам данные о наклоне (x,y,z). Нас тут интересует только x и y. Для упрощения, я проверяю достаточно большой уровень наклона, меньше -2 или больше 2.
Как только наклон достиг определенного градуса, вызывается функция «start_or_stop_move», которой передается направление наклона. Данная функция, в зависимости от скорости задает направление движения игрока, которое потом отрисовывается в событие «EnterFrame».
Дальше нам нужно создать сам генератор события «Acceleration», для этого добавим следующий код в /js/game.js:
var watchID = null;
function stopWatch() {
if (watchID) {
navigator.accelerometer.clearWatch(watchID);
watchID = null;
}
}
function startWatch() {
var options = { frequency: 200 };
watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
// с помощью этого куска, можно дебажить акселерометр в хроме
// window.addEventListener('deviceorientation', function(event) {
// Crafty.trigger("Acceleration", {x: event.beta, y: event.alpha, z: event.gamma})
// }, false);
}
function onSuccess(acceleration) {
Crafty.trigger("Acceleration", acceleration)
}
function onError() {
console.log('error!');
}
Более подробно, о работе с акселерометром в phonegap, можно прочесть в документации.
Теперь, нам нужно вызвать startWatch() в сцене /js/scenes/main.js, а так же stopWatch() в сценах win.js и lose.js
Непосредственный запуск на телефоне
Итак, будем считать что вы уже сделал все, что описано в документации. Нужно немного подправить AndroidManifest.xml, добавив в секцию activity строчку: android:screenOrientation=«landscape». Это необходимо для того, что бы ориентация экрана всегда была альбомной.
Приводим AndroidrpgActivity.java к такому виду:
package com.phonegap.simplerpg;
import android.os.Bundle;
import android.view.WindowManager;
import com.phonegap.*;
public class AndroidrpgActivity extends DroidGap {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.loadUrl("file:///android_asset/www/index.html");
}
}
Думаю переменная FLAG_FULLSCREEN говорит сама за себя.
Результат и вывод
Вот, что у меня в итоге получилось (извините за качество):

Работает? О да! Доволен ли я? О нет!
Дело в том, что толи я криворукий, толи лыжи не едут, но приложение получилось крайне тормазнутым. Результат больше похож на пошаговую стратегию, чем на Action. И дело тут, я думаю, все же в лыжах, ответ наверное очевиден. PhoneGap — отличная библиотека для tumblr читалок и прочих новостных ридеров, но для игрушек лучше использовать нативный для android Java.
Исходники, как обычно на GitHub.