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.Func callback)
{
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";
}
}
else {
echo "No entries yet.";
}
echo " \n";
}
////////////////////////////////////////////////////////////////////////////////////////
// Close mySQL Connection
mysql_close($link);
?>
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)