PROGMANIST
Данный блог посвящен программированию и всему что связано с программированием.
22 авг. 2014 г.
AppCent - cайт для заработка денег путем установок приложений на Android, iOS.
ссылка: AppCent После регистрации, в личном аккаунте на вкладке "Приложения" отображается список приложений и сумма денег, которые будут зачислены на счет после установки приложения. То, что скрыто под катом Читать дальше......
7 мая 2013 г.
C# Создание Windows Service
C# Создание Windows Service
Для создания сервиса использовалась среда Visual Studio 2010. 1. Откройте студию и создайте новый проект
2. Для того чтобы службу можно было установить необходимо добавить в проект installer.
В Sulution Explorer дважды щелкните по классу "Service1.cs", в появившемся окне щелкните правой кнопкой мыши и выберите "Add Installer". Появится новый класс "ProjectInstaller.cs" с двумя компонентами: "serviceProcessInstaller" и "serviceInstaller".
Установите свойства этих компонентов как показано на рисунках:
serviceProcessInstaller
serviceInstaller 3. Откройте код файла "Service1.cs". Здесь мы видим два метода "OnStart" и "OnStop" которые срабатывают при запуске и остановке сервиса соответственно.
Допустим нам необходимо чтобы наш сервис каждую секунду записывал строку в файл.
Для этого создадим отдельный поток который будет запускаться при старте сервиса в методе "OnStart". В данном котором будем производить запись в файл:
В методе "DoWork" реализуем запись в файл:
Теперь при старте сервера будем запускать поток, а при остановке сервера - останавливать поток:
Добавим также метод который будет записывать в лог нашего сервиса события запуска и остановки сервера:
И будем вызывать его при запуске и остановке сервера.
Полностью код будет выглядеть следующим образом
После того как сервис создан, его необходимо установить. В этом нам поможет утилита "installutil.exe", которая распространяется вместе с фраемворком.
Создайте батник со следующим содержимым
здесь запускается утилита "installutil.exe", которой в качестве указывается наш сервис
запустите созданный батник из командной строки
если установка сервиса прошла успешно вы увидите сообщения:
"The Commit phase completed successfully".
"The transacted install has completed"
Теперь можно запустить наш сервер и посмотреть результат его выполнения
Зайдите в "Панель управления -> Администрирование -> Службы". Найдите установленную вами службу и запустите её
Теперь можно открыть созданный файл и посмотреть результат работы нашей службы
Как видно служба прекрасно отрабатывает
Теперь остановите службу.
Также в логе службы мы можем просмотреть когда наша служба запускалась и останавливалась
Зайдите в "Панель управления -> Администрирование -> Просмотр событий -> Журнал приложений и служб".
Здесь мы можем увидеть когда наша служба запускалась и останавливалась
Читать дальше......
Для создания сервиса использовалась среда Visual Studio 2010. 1. Откройте студию и создайте новый проект
2. Для того чтобы службу можно было установить необходимо добавить в проект installer.
В Sulution Explorer дважды щелкните по классу "Service1.cs", в появившемся окне щелкните правой кнопкой мыши и выберите "Add Installer". Появится новый класс "ProjectInstaller.cs" с двумя компонентами: "serviceProcessInstaller" и "serviceInstaller".
Установите свойства этих компонентов как показано на рисунках:
serviceProcessInstaller
serviceInstaller
Допустим нам необходимо чтобы наш сервис каждую секунду записывал строку в файл.
Для этого создадим отдельный поток который будет запускаться при старте сервиса в методе "OnStart". В данном котором будем производить запись в файл:
private readonly Thread workerThread; public Service1() { InitializeComponent(); workerThread = new Thread(DoWork); workerThread.SetApartmentState(ApartmentState.STA); }
В методе "DoWork" реализуем запись в файл:
private static void DoWork() { while (true) { string fname = @"c:\temp\temp.txt"; using (StreamWriter stream = new StreamWriter(fname, true)) { stream.WriteLine("Hello World!"); } // do some work, then Thread.Sleep(1000); } }
Теперь при старте сервера будем запускать поток, а при остановке сервера - останавливать поток:
protected override void OnStart(string[] args) { workerThread.Start(); } protected override void OnStop() { workerThread.Abort(); } }
Добавим также метод который будет записывать в лог нашего сервиса события запуска и остановки сервера:
public void AddLog(string log) { try { if (!EventLog.SourceExists("MyExampleService")) { EventLog.CreateEventSource("MyExampleService", "MyExampleService"); } eventLog1.Source = "MyExampleService"; eventLog1.WriteEntry(log); } catch { } }
И будем вызывать его при запуске и остановке сервера.
Полностью код будет выглядеть следующим образом
public partial class Service1 : ServiceBase { private readonly Thread workerThread; public Service1() { InitializeComponent(); workerThread = new Thread(DoWork); workerThread.SetApartmentState(ApartmentState.STA); } protected override void OnStart(string[] args) { AddLog("Service is started"); string fname = @"c:\temp\temp.txt"; using (StreamWriter stream = new StreamWriter(fname, true)) { stream.WriteLine("Служба запущена!"); } workerThread.Start(); } protected override void OnStop() { AddLog("Service is stopped"); string fname = @"c:\temp\temp.txt"; using (StreamWriter stream = new StreamWriter(fname, true)) { stream.WriteLine("Служба остановлена!"); } workerThread.Abort(); } public void AddLog(string log) { try { if (!EventLog.SourceExists("MyExampleService")) { EventLog.CreateEventSource("MyExampleService", "MyExampleService"); } eventLog1.Source = "MyExampleService"; eventLog1.WriteEntry(log); } catch { } } private static void DoWork() { while (true) { string fname = @"c:\temp\temp.txt"; using (StreamWriter stream = new StreamWriter(fname, true)) { stream.WriteLine("Hello World!"); } // do some work, then Thread.Sleep(1000); } } }
После того как сервис создан, его необходимо установить. В этом нам поможет утилита "installutil.exe", которая распространяется вместе с фраемворком.
Создайте батник со следующим содержимым
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe E:\MyProjects\test\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe pause
здесь запускается утилита "installutil.exe", которой в качестве указывается наш сервис
запустите созданный батник из командной строки
если установка сервиса прошла успешно вы увидите сообщения:
"The Commit phase completed successfully".
"The transacted install has completed"
Теперь можно запустить наш сервер и посмотреть результат его выполнения
Зайдите в "Панель управления -> Администрирование -> Службы". Найдите установленную вами службу и запустите её
Теперь можно открыть созданный файл и посмотреть результат работы нашей службы
Как видно служба прекрасно отрабатывает
Теперь остановите службу.
Также в логе службы мы можем просмотреть когда наша служба запускалась и останавливалась
Зайдите в "Панель управления -> Администрирование -> Просмотр событий -> Журнал приложений и служб".
Здесь мы можем увидеть когда наша служба запускалась и останавливалась
12 мар. 2012 г.
Unity3d + Blender + GIMP - создание анимации с помощью спрайтов.
Для создания анимации с помощью
спрайтов я использовал метод создания 3d модели и рендеринга её в различных
положениях. Для этого я использовал следующие программы: Blender 2.6, GIMP 2.6, плагин для GIMP (для создания спрайтов) и Unity3d 3.5.
Blender.
Сделаем анимацию простого
куба. Запускаем Blender,
создаем куб: Shift+A -> Mesh->Cube.
Настраиваем камеру чтобы она смотрела на куб. Нажимаем F12, ждем пока рисунок
отрендерится, потом жмем F3.
Во вкладке Save as Image выбираем PNG и RGBA (чтоб фон был прозрачным). Называем рисунок 1.png. Потом нажимаем Esc. Поднимем немного куб, опять рендер
и сохранение. Называем рисунок 2.png. Проделайте так несколько
раз.
GIMP.
Теперь
когда у нас готовы рисунки, нужно их склеить в один спрайт. Для этого сначала
нужно установить плагин в GIMP.
Переходим по ссылке скачиваем плагин, кладем его в директорию {GIMPHOME}\share\gimp\2.0\scripts\SpriteSheet.scm
Запускаем GIMP,
жмем Фильтры – Scripts-Fu – обновить
сценарии. Плагин установлен. Теперь жмем Фаил
– Открыть как слои, и выбираем наша рисунки, жмем Фильтры – Sprite-Sheets – Create from layers. У вас появиться
спрайт. Сохраняем его, жмем в появившемся окне Фаил – Сохранить как… ,
открываем вкладку Выберите тип файла (по расширениею) и выбираем там PNG, жмем сохранить потом ещё
раз жмем сохранить. Всё спрайт готов, осталось загрузить его в Unity3d и анимировать.
Unity3d.
Создаем Plane. Поворачиваем его лицом к камере,
не забудьте добавить источник света. Добавляем наш спрайт в проект, создаем
новый материал, в качестве текстуры указываем наш спрайт. Выберите Shader: Transparent – Diffuse, чтобы фон был
прозрачным. Примените данный материал к созданному Plane. Теперь осталось анимировать его,
делать мы это будем с помошью вот этого скрипта Добавьте этот скрипт к Plane, и установите
нужные настройки в скрипте.
Анимация
готова! Можете запустить проект и любоваться.
10 мар. 2012 г.
Blender 2.6 Hot Key (горячие клавиши).
Горячие клавиши Blender 2.6
Общие:
- F12 – рендер изображения.
- F1 – открыть файл.
- F2 – сохранить файл.
- Space – вызывает меню поиска по командам Blender.
- Shift + F – режим полета камеры.
- Shift + Space – полноэкранный режим просмотра.
Перемещение в пространстве:
- Клавиши на дополнительной цифровой клавиатуре: 1,3,7 – вид спереди, справа и сверху соответственно. 0– вид из камеры, .(точка) – сфокусироваться на объекте. 5 – переключение между ортогональным и перспективным отображением. 2,8,4,6 – вращение – вниз, вверх, влево и вправо соответственно. +, - - масштабирование.
- Ctrl + 1,3,7 – вид сзади, слева, снизу. Ctrl + 2,8,4,6 – перемещение вниз, вверх, влево и вправо. Ctrl + 5 –сфокусироваться на курсоре.
- ЛКМ – перемещение курсора. Курсор определяет место, где будет создаваться новый объект.
- ПКМ – щелчок правой кнопкой мыши объекту выделяет этот объект (в объектном режиме).
- Зажатое среднее колесо мыши + перемещение мыши – вращение вокруг сцены.
- Зажатое среднее колесо мыши + Shift + перемещение мыши – передвижение.
- Зажатое среднее колесо мыши + Ctrl + перемещение мыши – масштабирование.
- T – открытие панели инструментов.
- N – открытие панели трансформации.
- Tab – переход между объектным режимом(Object Mode) и режимом редактирования (Edit Mode).
Объектный режим (Object Mode):
Объектный режим предназначен для изменения объекта в целом.
- Shift + A – вызов меню добавления объектов.
- Shift + S – вызов меню точного расположения курсора. (and Edit Mode)
- R – вращение объекта (если нажать х или у или z вращение будет происходить вокруг соответствующей оси). (and Edit Mode)
- G – перемещение объекта (если нажать х или у или z перемещение будет происходить относительно соответствующей оси). (and Edit Mode)
- S – масштабирование (если нажать х или у или z масштабирование будет происходить относительно соответствующей оси). (and Edit Mode)
- Shift+D – создание копии объекта.
- Del или X – удаление выделенного объекта.
- Z – переход между заполненным и каркасным видом отображения объекта (and Edit Mode).
- Alt + Z – переход между текстурированным и затененным видами объектов. (and Edit Mode).
- Ctrl + Z – отмена последнего действия.
- Ctrl + Shift + Z – повторить последнее отмененное действие.
- Ctrl+J – объединение выделенных объектов.
- M – перемещение выделенных объектов в другие слои.
- [~] – объединение всех слоев.
Режим редактирования (Edit Mode):
Режим редактирования предназначен для изменения формы объекта.
- Shift + A – вызов меню добавления объектов (добавленный объект будет объединён с текущим объектом).
- Shift+D – создание копии объекта (скопированный объект будет объединен с исходным).
- ПКМ – выделение вершин, ребер или граней.
- Ctrl+Tab – изменения режима выделения(вершины, грани, ребра).
- ПКМ + Shift – выделение нескольких вершин, граней, ребер.
- B – выделение прямоугольником.
- С – выделение окружностью. (с помощью колесика мыши или кнопок +, -, можно менять размер окружности).
- A – выделение всех вершин. (повторное нажатие – снятие выделения).
- E – экструдирование выделенных вершин, можно перемещать +G, вращать +R, масштабировать +Z.
- Esc – отменяет работу с текущим инструментом выделения.
- Del или X – вызов контекстного меню выбора удаляемых объектов.
- W – вызывает меню “Specials” со специфичными для данного объекта параметрами преобразования.
- K – инструмент разрезания граней. Щелкайте ЛКМ в нужном месте грани чтобы разрезать её. Если нажатьCtrl – курсор будет расположен по середине грани.
- Ctrl+R – режим разрезания граней.
- P – отделить выделенные вершины от остального объекта. (или объединить в один объект выделенные вершины).
- F – создает грань между выделенными вершинами.
- Ctrl+F – открывает меню граней, для доступа к дополнительным параметрам граней.
20 февр. 2012 г.
Unity3d. Сохранение результата в базу данных расположенную на сервере. Часть вторая - клиент.
И так мы создали базу данных, создали скрипт, который осуществляет соединение с базой и чтение-запись данных. Теперь нам необходимо соединиться из нашей игры с php-скриптом, и получить из него данные, которые он получает с базы данных.
Т.к. данные которые мы будем получать из php-скрита будут в xml виде то первым делом создадим скрипт XmlParser который будет осуществлять чтение xml-данных, выбор из данных атрибутов name и score, и сохранять значения этих атрибутов в массивы name[] и score[].
using UnityEngine; using System.Collections; using System.Xml; public static class XmlParser { private static XmlDocument doc; private static XmlNode root; private static string[] names; // массив имен private static int[] scores; // массив результатов private static int userLenght; // длинна массива public static void Parse(string xml) { doc = new XmlDocument(); doc.LoadXml(xml); root = doc.LastChild; if (root.HasChildNodes) { userLenght = root.ChildNodes.Count; names = new string[userLenght]; scores = new int[userLenght]; for (int i = 0; i < userLenght; i++) { XmlAttribute nameAtt = root.ChildNodes[i].Attributes["name"]; XmlAttribute scoreAtt = root.ChildNodes[i].Attributes["score"]; names[i] = (string)nameAtt.Value; scores[i] = ConvertStringToInt((string)scoreAtt.Value); } } } private static int ConvertStringToInt(string s) { int j; bool result = System.Int32.TryParse(s, out j); if (result = true) { return j; } else { Debug.Log("Error convert string to int"); return 0; } } public static string Name(int index) { return names[index]; } public static int Score(int index) { return scores[index]; } public static int UserLength() { return userLenght; } }
Теперь создадим скрипт ServerHiScore который будет осуществлять доступ к php-скрипту, получение и отправку данных из приложения на сервер.
using UnityEngine; using System.Collections; public class ServerHiScore : MonoBehaviour { //Set the PHP url here public string PHPUrl = "http://yourDomainName.byethost15.com/HiScore.php"; // адрес скрипта //Set the hash key id public string hashKey = "BRIGHTWORLDGAMES"; // ключ для шифрования данных private WWWForm obj_WWW; private bool b_loaded; private delegate void LoadXmlDel(string str); // Use this for initialization void Start () { } // Update is called once per frame void Update () { } //Отправка данных public void SendScore( int score, string name) { WWWForm w_form = new WWWForm(); //Telling PHP that the user is submiting the data w_form.AddField("action", "PostScore"); //Sending hash code key to prevent unwanted user w_form.AddField("hash", MD5.Md5Sum(name + "-" + score.ToString() + "-" + hashKey)); //Encrypt with MD5 //Sending the user score w_form.AddField("score", score); //Sending the user name w_form.AddField("name", name); //Start waiting for the response back from the server StartCoroutine(WaitingForResponse(new WWW(PHPUrl, w_form), null)); } // public IEnumerator WaitingForResponse(WWW www, System.Funccallback) { yield return www; // ожидаем пока получим с сервера данные if (www.error == null) { // Debug.Log("Successful."); } else { // Debug.Log("Failed."); } if (callback != null) { callback(www.text); callback = null; } //Очищаем данные www.Dispose(); } //Получение данных public void GetScores() { b_loaded = false; WWWForm w_form = new WWWForm(); //Telling PHP that the user is loading the data w_form.AddField("action", "GetScore"); //Start waiting for the response back from the server StartCoroutine(WaitingForResponse(new WWW(PHPUrl, w_form), LoadXMLData)); } //Parse the XML data from the server public bool LoadXMLData(string str) { XmlParser.Parse(str); b_loaded = true; return true; } //Getting User length public int GetUserLength() { return XmlParser.UserLength(); } //Getting User Name by index public string GetNameData(int index) { return XmlParser.Name(index); } //Getting User Score by index public int GetScoreData(int index) { return XmlParser.Score(index); } //Loaded XML public bool IsLoaded() { return b_loaded; } }
При передаче данных, мы также передаем ключ в зашифрованном виде, чтобы никакие злоумышленники не могли записать свои данные на сервер, в php-скрипте мы проверяем совпадает ли ключ который храниться на сервере с ключом который мы передали, и записывает данные только если ключи совпадают. При создании аккаунта на byethost у вас автоматически создается домен с названием как выше имя, http://yourDomainName.byethost15.com/, где вместо byethost15 будет ваше название, посмотрите на панели слева в админке. Также вы всегда может создать другой домен, если этот вас не устраивает.
Теперь реализуем метод MD5. Создайте js-скрипт с следующим содержанием:
#pragma strict static function Md5Sum(strToEncrypt: String) { var encoding = System.Text.UTF8Encoding(); var bytes = encoding.GetBytes(strToEncrypt); // encrypt bytes var md5 = System.Security.Cryptography.MD5CryptoServiceProvider(); var hashBytes:byte[] = md5.ComputeHash(bytes); // Convert the encrypted bytes back to a string (base 16) var hashString = ""; for (var i = 0; i < hashBytes.Length; i++) { hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, "0"[0]); } return hashString.PadLeft(32, "0"[0]); }
Т.к. это js-скрипт, а мы используем его в C# скрипте, то обязательно поместите скрипт MD5 в папку Plugins, иначе компилятров Unity3d будет выдавать вам ошибку. На этом вобщем-то всё. Теперь вы можете просто вызывать методы GetScores() и SendScores() скрипта ServerHiScore. Например у меня есть меню, в котором есть кнопка HiScore, при нажатии на которую появляется окно с результатами, тогда получать данные я буду следующим образом:
using UnityEngine; using System.Collections; public class Menu : MonoBehaviour { public GUISkin customSkin; enum Page {MENU, HOWTOPLAY, HISCORE, HISCOREMENU, EMPTY}; private Page page; private Vector2 scrollPosition = Vector2.zero; private int maxUsers = 10; private GameObject cloud; private ServerHiScore objServerHighScore; // объявляем экземпляр класса ServerHiScore void Awake() { } void Start () { Time.timeScale = 1f; objServerHighScore = this.GetComponentЕсли же мне нужно сохранить данные на сервер, то я делаю следующим образом:(); page = Page.MENU; cloud = GameObject.Find("HiScoreCloud"); } void Update () { } void OnGUI() { GUI.skin = customSkin; switch (page) { case Page.MENU: MenuPage(); break; case Page.HISCORE: HiScorePage(); break; case Page.EMPTY: break; }; } private void MenuPage() { GUI.BeginGroup(new Rect(Screen.width / 1.2f - 125, Screen.height / 1.6f - 100, 250, 200)); if (GUI.Button(new Rect(25, 20, 200, 30), "Start Game", GUI.skin.GetStyle("StartButton"))) { Application.LoadLevel("MainScene"); } if (GUI.Button(new Rect(10, 70, 220, 30), "How to Play", GUI.skin.GetStyle("HowToButton"))) { StartCoroutine(ChangePage(Page.HOWTOPLAY)); } if (GUI.Button(new Rect(25, 120, 180, 30), "Hi-Score", GUI.skin.GetStyle("QuitButton"))) { objServerHighScore.GetScores(); // если нажали кнопку Hi-Score вызываем метод для получения данных StartCoroutine(ChangePage(Page.HISCORE)); } GUI.EndGroup(); } private void HiScorePage() { GUI.BeginGroup(new Rect(Screen.width / 2f - 300, Screen.height / 2f - 210, 600, 420)); GUI.Label(new Rect(200, 50, 200, 50), "Top 10", GUI.skin.GetStyle("HiScoreLabelCenter")); if (objServerHighScore.IsLoaded()) // если данные загружены { int numUsers = objServerHighScore.GetUserLength(); if (numUsers > maxUsers) numUsers = maxUsers; scrollPosition = GUI.BeginScrollView(new Rect(100, 110, 400, 180), scrollPosition, new Rect(0, 0, 250, 30 * numUsers)); for (int i = 0; i < numUsers; i++) { GUI.Label(new Rect(0, i * 30, 35, 30), (i + 1).ToString() + ". ", GUI.skin.GetStyle("HiScoreLabel")); GUI.Label(new Rect(35, i * 30, 220, 30), objServerHighScore.GetNameData(i), GUI.skin.GetStyle("HiScoreLabel")); // получаем имя GUI.Label(new Rect(255, i * 30, 145, 30), objServerHighScore.GetScoreData(i).ToString(), GUI.skin.GetStyle("HiScoreLabel")); // получаем очки } GUI.EndScrollView(); } else { GUI.Label(new Rect(200, 200, 200, 30), "LOADING...", GUI.skin.GetStyle("HiScoreLabelCenter")); } if (GUI.Button(new Rect(210, 300, 180, 30), "Back", GUI.skin.GetStyle("ReplayButton"))) { StartCoroutine(ChangePage(Page.HISCOREMENU)); } GUI.EndGroup(); } IEnumerator ChangePage(Page pageNum) { switch (pageNum) { case Page.HOWTOPLAY: page = Page.EMPTY; while ((transform.position - new Vector3(178f, transform.position.y, transform.position.z)).magnitude > 0.5f) { transform.position = Vector3.Lerp(transform.position, new Vector3(178f, transform.position.y, transform.position.z), Time.deltaTime*3.0f); yield return new WaitForSeconds(0.01f); } page = Page.HOWTOPLAY; break; case Page.MENU: page = Page.EMPTY; while ((transform.position - new Vector3(0f, transform.position.y, transform.position.z)).magnitude > 0.5f) { transform.position = Vector3.Lerp(transform.position, new Vector3(0f, transform.position.y, transform.position.z), Time.deltaTime*3.0f); yield return new WaitForSeconds(0.01f); } page = Page.MENU; break; case Page.HISCORE: page = Page.EMPTY; while (cloud.transform.position.y > 0.1f) { cloud.transform.position = Vector3.Lerp(cloud.transform.position, new Vector3(cloud.transform.position.x, 0f, cloud.transform.position.z), Time.deltaTime*3f); yield return new WaitForSeconds(0.01f); } page = Page.HISCORE; break; case Page.HISCOREMENU: page = Page.EMPTY; while (cloud.transform.position.y < 87.9f) { cloud.transform.position = Vector3.Lerp(cloud.transform.position, new Vector3(cloud.transform.position.x, 88f, cloud.transform.position.z), Time.deltaTime * 3.0f); yield return new WaitForSeconds(0.01f); } page = Page.MENU; break; }; } }
private void SubmitDialog() { GUI.BeginGroup(new Rect(Screen.width / 2 - 150, Screen.height / 2 - 140, 300, 280)); GUI.Box(new Rect(0, 0, 300, 280), "", GUI.skin.GetStyle("PauseBox")); GUI.Label(new Rect(25, 10, 250, 50), "Submit Results", GUI.skin.GetStyle("LevelCompleteLabel")); GUI.Label(new Rect(25, 60, 250, 50), "Your score: " + totalScore.ToString(), GUI.skin.GetStyle("LabelMidCenter")); GUI.Label(new Rect(25, 90, 250, 50), "Enter your name:"); userName = GUI.TextField(new Rect(25, 140, 250, 45), userName, 20); if (GUI.Button(new Rect(105, 200, 80, 24), "Submit", GUI.skin.GetStyle("NextLevelButton"))) { submitResult = true; //сохранение результата на сервер objServerHighScore.SendScore(totalScore, userName); dialog = previousDialog; } if (GUI.Button(new Rect(105, 235, 80, 24), "Back", GUI.skin.GetStyle("NextLevelButton"))) { dialog = previousDialog; } GUI.EndGroup(); }
Читать дальше......
Unity3d. Сохранение результата в базу данных расположенную на сервере. Часть первая - сервер.
Всем доброго времени суток, в этом цикле статей я расскажу как создать базу данных на бесплатном интернет хостинге, и получить доступ к ней из вашей игры, сделанной на Unity3d.
Допустим вы создали онлайн игру и перед вами встала задача добавить возможность сохранения набранных очков пользователем, с возможностью вывода этих очков в HiScore. Для этого вам необходимо хранить эти очки на сервере с возможностью постоянного доступа к нему.
Я использовал бесплатный хостингwww.byethost.com. И так регестрируемся на www.byethost.com, на почту вам должно прийти письмо с логином и паролем. Авторизуемся на сайте, потом заходим в панель управления. Выбираем MySQL Database:
В появившемся окне в поле вводим имя вашей базы данных, и жмем Create Database. База данных создана теперь заходим в панель управления базой данных, жмем кнопку Admin. У вас должно появиться следующее окошко:
Создадим новую таблицу в которой будем хранить имя пользователя и набранные очки. В поле «Имя» введите название таблицы, например «scores», в поле «Количество столбцов» введите «2», и нажмите «Ок». Появится окно где нужно заполнить названия столбцов и тип хранимых данных. В первом столбце будем хранить имя пользователя: поле - name, тип - varchar, длинна - 20. Второй столбец: поле – score, тип int. Нажимае «Сохранить», таблица создана. Теперь выберите созданную таблицу, у вас появится окно со структурой таблицы, и внизу будет надпись «Индекс не определен». Напротив столбца «Name» нажмите «ещё» и выберите "добавить индекс".
База данных создана, теперь необходимо осуществить доступ к ней. Так как на сервере порт 3306 закрыт для внешнего доступа, по которому осуществляется связь с MySQL, мы не можем удаленно, из нашего приложения осуществлять доступ к базе данных. По этому мы создадим php скрипт в котором будет осуществляться доступ к нашей БД, чтение и запись данных и расположим его на сервере, а из приложения уже будем получать данные через этот скрипт.
И так создайте следующий php-скрипт:
?PHP // Connect to Database $link = mysql_connect( "hostname", "username", "password" ) or die( mysql_error() ); mysql_select_db( "databasename" ) or die( mysql_error() ); // Get Data $name = $_POST['name']; //Get name from Unity $score = $_POST['score']; //Get score from Unity $action = $_POST[ 'action' ]; //Get request action from Unity $unityHash = $_POST[ 'hash' ]; //Get hash key from Unity //Секретный ключ для шифрования данных при передаче $secretKey="BRIGHTWORLDGAMES"; $phpHash = md5($name."-".$score."-".$secretKey); switch ( $action ) { case "GetScore": GetScores(); break; case "PostScore": if( $phpHash == $unityHash ) { PostScore(); } break; default: GetScores(); break; } //////////////////////////////////////////////////////////////////////////////////////// function PostScore() { $score = $_POST[ 'score' ]; //score pass from Unity $name = $_POST[ 'name' ]; //name pass from Unity //scores = имя вашей БД //name = Первый столбец //score = второй столбец $query = "INSERT INTO scores ( name, score ) VALUES ( '" . $name . "', '" . $score . "')"; mysql_query( $query ) or die( mysql_error() ); } //////////////////////////////////////////////////////////////////////////////////////// function GetScores() { if( $_POST[ 'size' ] != "" ) { $size = $_POST[ 'size' ]; } else { $size = 10; } $query = "SELECT * FROM scores ORDER BY score DESC LIMIT " . $size; $results = mysql_query( $query ) or die( mysql_error() ); //Return XML String to Unity echo "\n"; echo "\n"; if( mysql_num_rows( $results ) > 0 ) { while( $line = mysql_fetch_array( $results ) ) { echo " \n"; } //////////////////////////////////////////////////////////////////////////////////////// // Close mySQL Connection mysql_close($link); ?>\n"; } } else { echo "No entries yet."; } echo "
Hostname вы можете посмотреть на панели слева, имя пользователя и пароль к БД должны были прийти вам на почту. Назовите данный скрипт HiScore, и залейте его на сервер через ftp (адрес ftp также можно увидеть на панели слева), в папку “htdocs”. На этом работа с сервером закончена, и можно переходить к клиентской части приложения.
6 окт. 2010 г.
Использование Google Maps в Android
Google Maps API позволяет добавлять в Android приложения возможность работы с картами Google. Чтобы подключить карты к вашему проекту, вам необходимо выполнить следующие шаги:
Отображение карты.
для того чтобы отобразить карты измените main.xml из папке res\layout. Вы должны использовать <com.google.android.maps.MapView> элемент, чтобы отобразить карту в вашем Activity.
Теперь откройте HelloMap.Activity, данный класс должен быть унаследован от MapActivity. При наследовании от класса MapActivity необходимо переопределить метод isRoyteDisplayed():
Всё готово! Теперь можете запустить проект и посмотреть результат.
Теперь откройте HelloMapActivity.java. Импортируйте следующие библиотеки:
Файл HelloMapActivity.java полностью:
Теперь можете запустить проект и посмотреть результат.
Читать дальше......
- Создать новый проект Android на базе библиотек Google API;
- Создать новый Android Virtual Device - c возможностью работы с Google API;
- Получить Map API Key;
- Подключить к проекту необходимые библиотеки и использовать классы Google Maps.
Шаг первый:
Запустите Eclipse, создайте новый Android Project, можете назвать его HelloMap, и в поле Build Target выберете Google APIs. Если у вас в Build Target нет Google APIs, значит у вас не установлен пакет с данным API. Пройдите Windows->Android SDK and AVD Manager->Installed Pakages, нажмите Update All... и установите пакет с Google API.
Шаг второй:
Теперь нужно создать Android Virtual Device который имеет возможность работы с Google API. Пройдите Windows->Android SDK and AVD Manager->Virtual Devices. Нажмите New и в поле Target выберете Google APIs. Теперь можете запустите созданный эмулятор.
Шаг третий:
Получение Map API Key. Для того чтобы иметь возможность отображать Google карты, вам необходимо использовать бесплатный Google Map API Key. Чтобы получить ключ необходимо выполнить следующие шаги:
- Найдите файл debug.keystore, он располагается в папке "C:\Documents and Settings\<User Name>\.android". Скопируйте данный файл в папку C:\(к примеру можете создать папку Android "C:\Android").
- Из данного keystore необходимо получить MD5 код. Для этого используйте утилиту keytool.exe которая поставляется вместе с JDK и располагается в папке "C:\Program Files\Java\<jdk using version>\bin".
- Запустите командную строку Пуск->Все программы->стандартные->командная строка. Перейдите в папку с keytool ("cd C:\Program Files\Java\<jdk uses version>\bin") и выполните следующую команду:
- Скопируйте полученный MD5 и пройдите по ссылке http://code.google.com/intl/ru-RU/android/maps-api-signup.html. Следуйте инструкциям и получите свой API Key.
keytool.exe -list -alias androiddebugkey -keystore "C:\android\debug.keystore" -storepass android -keypass androidПосле выполнения данный команды вы должны увидеть на экране свой MD5 код.
Шаг четвёртый:
Для того чтобы использовать Google Maps API необходимо подключить библиотеку для работы с картами <uses-library android:name="com.google.android.maps"> и так как наше приложение будет загружать карты через интернет нужно позволить ему работать с интернетом INTERNET permission.
Откройте AndroidManifest.xml и добавьте в него <uses-library> и INTERNET permission:
Отображение карты.
для того чтобы отобразить карты измените main.xml из папке res\layout. Вы должны использовать <com.google.android.maps.MapView> элемент, чтобы отобразить карту в вашем Activity.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.google.android.maps.MapView android:id="@+id/mapView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true" android:apiKey="Ваш API Key" /> </RelativeLayout>
Теперь откройте HelloMap.Activity, данный класс должен быть унаследован от MapActivity. При наследовании от класса MapActivity необходимо переопределить метод isRoyteDisplayed():
package com.alukardev.hellomap2; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import android.os.Bundle; public class HelloMapActivity extends MapActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } }
Всё готово! Теперь можете запустить проект и посмотреть результат.
Масштабирование.
Добавим в наш проект возможность масштабировать карту.
Откройте main.xml и добавьте в него <LinearLayout>:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.google.android.maps.MapView android:id="@+id/mapView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true" android:apiKey="0oJHawmPUco4Y2eJDV8r5cKv4kUseLVglm4-e0g" /> <LinearLayout android:id="@+id/zoom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" /> </RelativeLayout><LinearLayout> элемент нужен чтобы отобразить на нем кнопки масштабирования.
Теперь откройте HelloMapActivity.java. Импортируйте следующие библиотеки:
import com.google.android.maps.MapView.LayoutParams; import android.view.View; import android.widget.LinearLayout;Добавьте следующий код после строчки setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapView); LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom); View zoomView = mapView.getZoomControls(); zoomLayout.addView(zoomView, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mapView.displayZoomControls(true);
Файл HelloMapActivity.java полностью:
package com.alukardev.hellomap2; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import android.os.Bundle; import com.google.android.maps.MapView.LayoutParams; import android.view.View; import android.widget.LinearLayout; public class HelloMapActivity extends MapActivity { MapView mapView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mapView = (MapView) findViewById(R.id.mapView); LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom); View zoomView = mapView.getZoomControls(); zoomLayout.addView(zoomView, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mapView.displayZoomControls(true); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } }
Теперь можете запустить проект и посмотреть результат.
В качестве альтернативного решения можно использовать клавиши для масштабирования, для этого нужно вызывать методы zoomIn() и zoouOut() класса MapController:
package com.alukardev.hellomap2; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import android.os.Bundle; import com.google.android.maps.MapView.LayoutParams; import android.view.KeyEvent; import android.view.View; import android.widget.LinearLayout; public class HelloMapActivity extends MapActivity { MapView mapView; public boolean onKeyDown(int keyCode, KeyEvent event) { MapController mc = mapView.getController(); switch (keyCode) { case KeyEvent.KEYCODE_3: mc.zoomIn(); break; case KeyEvent.KEYCODE_1: mc.zoomOut(); break; } return super.onKeyDown(keyCode, event); } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mapView = (MapView) findViewById(R.id.mapView); LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom); View zoomView = mapView.getZoomControls(); zoomLayout.addView(zoomView, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mapView.displayZoomControls(true); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } }
Читать дальше......
Подписаться на:
Сообщения (Atom)