Данный пост де-факто является продолжением предыдущего. Поэтому некоторые моменты, рассмотренные в предыдущем посте, я подробно объяснять уже не буду.
Задача:
Создание глобальной таблицы игроков для небольшого (!) флеш-приложения.
Средства:
Использовать будем язык ActionScript 2.0 и среду разработки Macromedia Flash 8. Серверная часть будет на php. Хранить данные будем в текстовом файле на сервере.
Итак, начнём...
Первым делом создадим новый флеш-проект. В этом проекте создадим простенький интерфейс, который позволит нам проверить нашу таблицу рекордов в действии. То есть нам нужна возможность добавления данных в нашу импровизированную базу данных на сервере и возможность получения данных с сервера. Для этого создадим в нашем флеш-ролике следующие объекты:
1.) текстовое поле ввода id для ввода уникального (!) идентификатора пользователя (в качестве такого идентификатора может выступать число или строка);
2.) текстовое поле ввода score для ввода результатов текущего пользователя (очки, баллы и подобное);
3.) кнопка btn, нажатие по которой запустит обмен данными между сервером и флеш-приложением;
4.) динамическое текстовое поле mes, в котором будем выводить сообщения об ошибках;
5.) мувиклип animLoad с анимацией загрузки (он будет накрывать наш флеш-ролик всё время, пока идёт обмен данными между флеш-роликом и серверным скриптом).
Теперь, когда все необходимые элементы интерфейса созданы, приступим к написанию кода. Идём на главную временную шкалу проекта и помещаем туда следующий код...
Код ActionScript 2.0:
/*
Импортируем необходимые классы.
*/
import Serializer;
import MD5;
/*
Объявляет необходимые переменные и присваиваем им значения.
*/
var arr:Array = new Array(); // это массив, в котором будут хранится данные для таблицы рекордов
var dTabl:Number = 1000; // это уровень, на который будет помещаться окно с таблицей рекордов
var page:Number = 0; // текущая страница таблицы рекордов
/*
Путь к директории, в которой лежит php-скрипт.
*/
var strUrl:String = "http://edapskov.ru/applications/";
/*
Секретный ключ.
*/
var skey:String = "Natasha";
/*
Ограничения на символы, которые можно ввести через поля ввода.
Вам, скорее всего, это не потребуется, так как данные не будут браться из полей ввода.
Впрочем, фильтрация и проверка корректности данных - штука полезная :-)
*/
id.restrict = "0-9a-zA-Z";
score.restrict = "0-9";
/*
Функция сортировки многомерного массива.
*/
function sortScore(a, b) {
var aN:Number = parseInt(a[1], 10);
var bN:Number = parseInt(b[1], 10);
if (aN>bN) {
return -1;
} else if (aN<bN) {
return 1;
} else {
return 0;
}
}
/*
Функция, которая генерирует окно с глобальной таблицей рекордов.
*/
function tabl() {
/*
Создаём необходимые переменные и присваиваем им значение.
*/
var sw:Number = Stage.width;
var sh:Number = Stage.height;
/*
Форматирование текста.
*/
var format = new TextFormat();
format.size = 14;
format.font = "Verdana";
format.color = 0x999999;
format.bold = true;
format.align = "center";
/*
Создаём мувик, который будет для таблицы рекордов контейнером.
*/
_root.createEmptyMovieClip("cont", dTabl);
/*
Создаём мувик, который будет для таблицы рекордов фоном и будет перехватывать мышиные события.
*/
cont.createEmptyMovieClip("fon", cont.getNextHighestDepth());
cont.fon.beginFill(0xffffff);
cont.fon.moveTo(0, 0);
cont.fon.lineTo(sw, 0);
cont.fon.lineTo(sw, sh);
cont.fon.lineTo(0, sw);
cont.fon.onPress = function() {
};
cont.fon.useHandCursor = false;
/*
Создаём контейнер для таблицы рекордов.
*/
cont.createEmptyMovieClip("tfCont", cont.getNextHighestDepth());
/*
Генерируем таблицу рекордов.
*/
var max:Number = (page+1)*10;
var n:Number = page*10;
for (i=0; n+i<arr.length && n+i<max; i++) {
for (j=0; j<arr[n+i].length; j++) {
/*
Столбец с указанием места игрока.
*/
cont.tfCont.createTextField("num"+i+"_"+j, cont.tfCont.getNextHighestDepth(), 0, i*20, sw/6, 20);
cont.tfCont["num"+i+"_"+j].border = true;
cont.tfCont["num"+i+"_"+j].borderColor = 0xcccccc;
cont.tfCont["num"+i+"_"+j].selectable = false;
cont.tfCont["num"+i+"_"+j].setNewTextFormat(format);
cont.tfCont["num"+i+"_"+j].text = " - "+(n+i+1)+" - ";
/*
Столбец с указанием уникального идентификатора игрока.
*/
cont.tfCont.createTextField("user"+i+"_"+j, cont.tfCont.getNextHighestDepth(), sw/6, i*20, sw/6*2, 20);
cont.tfCont["user"+i+"_"+j].border = true;
cont.tfCont["user"+i+"_"+j].borderColor = 0xcccccc;
cont.tfCont["user"+i+"_"+j].selectable = false;
cont.tfCont["user"+i+"_"+j].setNewTextFormat(format);
cont.tfCont["user"+i+"_"+j].text = arr[n+i][0];
/*
Столбец с результатами игрока.
*/
cont.tfCont.createTextField("score"+i+"_"+j, cont.tfCont.getNextHighestDepth(), sw/6*3, i*20, sw/6, 20);
cont.tfCont["score"+i+"_"+j].border = true;
cont.tfCont["score"+i+"_"+j].borderColor = 0xcccccc;
cont.tfCont["score"+i+"_"+j].selectable = false;
cont.tfCont["score"+i+"_"+j].setNewTextFormat(format);
cont.tfCont["score"+i+"_"+j].text = arr[n+i][1];
}
}
/*
Навигация по страницам глобальной таблицы рекордов.
*/
cont.tfCont.createTextField("nav", cont.tfCont.getNextHighestDepth(), 0, 10*20+20, sw/6*4, 20);
cont.tfCont["nav"].selectable = false;
cont.tfCont["nav"].setNewTextFormat(format);
cont.tfCont["nav"].html = true;
if (Math.ceil(arr.length/10)>1) {
if (page<=0) {
cont.tfCont["nav"].htmlText = '<a href="asfunction:_root.exitTabl">Exit</a> | <a href="asfunction:_root.pageTabl,1">Next >></a>';
} else if (page>=Math.floor(arr.length/10)) {
cont.tfCont["nav"].htmlText = '<a href="asfunction:_root.pageTabl,-1"><< Prev</a> | <a href="asfunction:_root.exitTabl">Exit</a>';
} else {
cont.tfCont["nav"].htmlText = '<a href="asfunction:_root.pageTabl,-1"><< Prev</a> | <a href="asfunction:_root.exitTabl">Exit</a> | <a href="asfunction:_root.pageTabl,1">Next >></a>';
}
} else {
cont.tfCont["nav"].htmlText = '<a href="asfunction:_root.exitTabl">| Exit |</a>';
}
/*
Позиционируем контейнер с глобальной таблицей рекордов.
*/
cont.tfCont._x = sw/6;
cont.tfCont._y = (sh-(12*20))/2-20;
}
/*
Функция навигации по многостраничной таблице рекордов.
*/
function pageTabl(str) {
page = page+parseInt(str, 10);
tabl();
}
/*
Функция закрытия окна с таблицей рекордов.
*/
function exitTabl() {
_root.getInstanceAtDepth(dTabl).removeMovieClip();
}
/*
Создаём объект LoadVars для отправки и получения данных.
*/
var myLoadVars:LoadVars = new LoadVars();
myLoadVars.onLoad = function(success:Boolean) {
animLoad._visible = false;
if (success) {
/*
Очищаем поле вывода ошибок.
*/
mes.text = "";
/*
Очищаем массив, в котором хранится таблица рекордов.
*/
arr.length = 0;
/*
По умолчанию показываем первую страницу глобальной таблицы рекордов.
*/
page = 0;
/*
Принимаем данные от php-скрипта и переводим их в формат, удобный для работы в ActionScript.
*/
var serializer:Serializer = new Serializer();
var obj:Object = serializer.unserialize(myLoadVars.q);
/*
Можно, конечно, работать и с ассоциативным массивом, но лично мне привычнее иметь дело с индексированным массивом.
Поэтому я ассоциативный массив превращаю в индексированный.
*/
for (var name in obj) {
arr.push([name, obj[name]]);
}
/*
Сортирую массив по результатам игроков (я исхожу из того, что результат игрока является числовым значение).
Если результат игрока представлен строкой, то данную сортировку пропускаем.
*/
arr.sort(sortScore);
/*
Запускаем функцию, генерирующую глобальную таблицу рекордов.
*/
tabl();
} else {
mes.text = "Ошибка!";
}
};
/*
Отправляем данные.
*/
btn.onPress = function() {
animLoad._visible = true;
myLoadVars.id = id.text;
myLoadVars.q = score.text;
myLoadVars.key = new MD5().hash(String(myLoadVars.id+myLoadVars.q+skey).toLowerCase());
myLoadVars.sendAndLoad(strUrl+"test2.php", myLoadVars, "POST");
};
/*
Делаем мувик-псевдопрелоадер невидимым.
Этот мувик будет видимым только тогда, когда идёт обмен данными между сервером и флеш-приложением.
*/
animLoad._visible = false;
/*
Приказываем мувику animLoad ловить мышиные события, что приведёт к фактической блокировке работы всех расположенных ниже объектов.
Это нам надо, чтобы пользователи лишний раз не жали кнопки и не меняли содержимое полей ввода во время работы флеш-приложения с сервером.
*/
animLoad.onPress = function() {
};
Код снабжён комментариями и, по моему мнению, довольно понятен. А если не понятен, то и не надо. Просто вставьте вместо значений полей ввода свои значения. То есть замените следующий фрагмент кода:
myLoadVars.id = id.text;
myLoadVars.q = score.text;
на свой примерно следующего вида:
myLoadVars.id = идентификатор_пользователя;
myLoadVars.q = результат_пользователя;
Кроме этого, замените путь к php-скрипту на свой. Всё остальное можно оставить без изменений.
Для работы данного примера так же потребуется два файла с расширением .as:
- MD5.as - класс, позволяющий хэшировать строку в md5;
- Serializer.as - класс, который позволит превратить ответ сервера в удобный для работы массив.
Оба эти файла прилагаются к исходнику (ссылка в конце поста) и должны располагаться в одной папке с флеш-проектом.
Если всё сделано правильно, то получится что-то вроде этого:
Давайте посмотрим, как это работает. В поле ввода id введём идентификатор пользователя (например, «Alex», «id5», «123» и т.д.). А в поле ввода score введём воображаемый результат данного пользователя («1», «12», «123» или другое). Нажмём кнопку «Пуск». Появится мувик-псевдозагрузчик, а затем, если не произойдёт ошибок, будет сгенерирована первая страница глобальной таблицы рекордов нашего флеш-приложения.
Таблица рекордов может быть многостраничной (если все результаты не получается разместить на одной странице). На каждой странице выводится по 10 строчек. Для перехода между страницами и закрытия окна с таблицей рекордов имеется простая навигационная панель с ссылками «Prev», «Next» и «Exit».
Осталось рассмотреть серверную часть.
На стороне сервера у нас находится php-скрипт и текстовый файл, выполняющий роль базы данных нашего приложения. Создавать текстовый файл нам не надо. Он будет автоматически создан php-скриптом при первом его запуске. Надо создать только сам php-файл - test2.php.
Как и в прошлый раз, php-скрипт у нас будет в двух вариантах: для PHP 4 и для PHP 5. Выбираем ту версию, которую поддерживает ваш хостинг (как узнать версию PHP на вашем сайте смотри в предыдущем посте).
Код php-скрипта для PHP 5 (test2.php):
<?php
/*
проверяем, пришли ли переменные, необходимые для работы скрипта
*/
if(isset($_POST['id']) && isset($_POST['q']) && isset($_POST['key'])){
/*
адрес текстового файла, в котором будем хранить информацию
*/
$filename = "test2.txt";
/*
$skey - секретный ключ
*/
$skey = "Natasha";
/*
обрабатываем полученные переменные
*/
$user = trim($_POST['id']);
$q = trim($_POST['q']);
$h = trim($_POST['key']);
/*
если данные истинны и не равны пустоте, то запускаем работу скрипта
*/
if(md5(strtolower($user.$q.$skey))==$h && strlen($user) && strlen($q)){
$arr = array();
$arr = unserialize(file_get_contents($filename));
if($q > $arr[$user]){
$arr[$user] = $q;
}
$str = serialize($arr);
file_put_contents($filename,$str);
echo '&q='.$str;
}
}
Код php-скрипта для PHP 4 (test2.php):
<?php
/*
проверяем, пришли ли переменные, необходимые для работы скрипта
*/
if(isset($_POST['id']) && isset($_POST['q']) && isset($_POST['key'])){
/*
адрес текстового файла, в котором будем хранить информацию
*/
$filename = "test2.txt";
/*
$skey - секретный ключ
*/
$skey = "Natasha";
/*
обрабатываем полученные переменные
*/
$user = trim($_POST['id']);
$q = trim($_POST['q']);
$h = trim($_POST['key']);
/*
если данные истинны и не равны пустоте, то запускаем работу скрипта
*/
if(md5(strtolower($user.$q.$skey))==$h && strlen($user) && strlen($q)){
$arr = array();
$fr = fopen($filename,"r");
$arr = unserialize(fread($fr,filesize($filename)));
fclose($fr);
if($q > $arr[$user]){
$arr[$user] = $q;
}
$str = serialize($arr);
$fw = fopen($filename,"w");
fwrite($fw,$str);
fclose($fw);
echo 'q='.$str;
}
}
Размещаем скрипт на сайте или на локальном сервере. После этого тестируем работу флеш-приложения с php-скриптом.
Конечно, стоит поменять секретный ключ на свой. Напомню, что секретный ключ должен быть одним и тем же и для флеш-приложения, и для нашего серверного скрипта.
Кроме этого, рекомендуется защитить свой флеш-ролик от декомпиляции (возможно, в этом вам помогут программы из раздела «Скачать»). Иначе секретный ключ очень скоро утратит своё главное свойство - секретность.
Ограничения:
[!] Данная таблица рекордов не рассчитана на хранение больших объёмов данных. Думаю, что не стоит хранить таким способом более нескольких десятков записей. Сами записи старайтесь делать компактными.
[!] В данной таблице рекордов надо использовать только буквы варварского алфавита и цифры (желательно использовать только цифры). К сожалению, использование букв русского алфавита не предусмотрено :-(
Обещанный ранее исходник под Macromedia Flash 8 и php-скрипты можно скачать здесь.
Вот и всё...