четверг, 30 декабря 2010 г.

Изменения

За время моего отсутствия у меня многое поменялось.
С С++ программиста я сначала превратился в Flash-аниматора, потом в AS3-программиста :) Бесценный опыт! Правда теперь пытаясь сесть за свой C++ движок обнаружилась одна недоработка. Так, как я не документировал свой движок, то спустя почти полгода я перестал понимать что и как в нём работает :) Приходится методом тыка и разбором исходников понимать, что же я когда-то понаписывал :)

Ещё многое изменилось в моей жизни, не связанным с программированием, но об этом я умолчу ;)


С приближающимися праздниками!

вторник, 20 июля 2010 г.

Внимательность

    Самый главный враг программиста - недостаток внимательности. Проявляется в основном от усталости. В таком состоянии можно допустить самые нелепые ошибки. Потому, как только замечаете за собой рассеянность, постарайтесь незамедлительно дать отдых своему мозгу. Умыться, постоять у окна, выпить чаю, почитать анекдоты, и.т.д. В общем делать всё, что не связанно с программированием и не особо задействующим мозг :)

    Показательный пример невнимательности был у меня сегодня. Добавил функциональности к классу отрисовки растровых шрифтов. В частности - возможность изменения размера шрифта в real-time. Скомпилировал, запустил - шрифт изменяет размер, но как-то не плавно. Пересмотрел код и увидел, что часть переменных у меня типа int, а не float. Перевёл их на float, запускаю - и опять нет плавности. Пошёл отдохнул, выпил чаю. Вернулся к компьютеру и сразу же увидел, что float то везде, но параметры функции непосредственной отрисовки как были типа int,  так ими и остались %) 

    В общем, будьте внимательнее, коллеги ;)

понедельник, 19 июля 2010 г.

Получение Lua таблицы в С++ (проблема с lua_next)

Боролся сегодня со злостным багом. Как только пытался получить таблицу из Lua, как тут же слетало приложение. Как оказалось, после прочтения документации, причина была довольно проста - ключи в таблице были типа number и к ним в случае считывания с таблицы нельзя применять функцию lua_tostring(), только lua_tonumber().
Цитата:
While traversing a table, do not call lua_tolstring directly on a key, unless you know that the key is actually a string. Recall that lua_tolstring changes the value at the given index; this confuses the next call to lua_next.

воскресенье, 18 июля 2010 г.

Передача таблицы в Lua (способ №2)

Наткнулся на статью: http://ilovelua.narod.ru/step4.html
На её основе немного переделал работу с таблицами. Создал глобальный map:

std::map<std::wstring,float>FloatMap; 

Далее, используя функцию toLua, описанную в статье, я передают map в Lua в виде таблицы:

int l_SpriteGetActualPos(lua_State* L)  
{  
 fromLua(L,1,String); // Получаю имя спрайта в массиве и записываю его в переменную String
 FloatMap.clear(); // очищаю map от данных
 FloatMap[L"X"] = Sprites[String].TempPos.x;
 FloatMap[L"Y"] = Sprites[String].TempPos.y;
 toLua(L,FloatMap);
 return 1;  
} 

Как видите, размер функции существенно уменьшился, данный метод существенно удобнее предыдущего.

пятница, 16 июля 2010 г.

Передача таблицы в Lua

Нужно было написать функцию, которая бы передавала несколько переменных в Lua в виде таблицы. Немного погуглил и нашёл простой работающий способ. Покажу его на примере функции, возвращающей текущее положение спрайта на экране:

int l_SpriteGetActualPos(lua_State* L)
{
 String = CharToWString(lua_tostring(L, 1)); // Получаю имя спрайта в массиве 
 lua_pop(L,1); // удаляю имя спрайта из стека Lua
 lua_newtable(L); //создаётся новая таблица
 lua_pushstring(L,"X"); // добавляю в стек ключ "Х"
 lua_pushnumber(L,Sprites[String].TempPos.x); // добавляю в стек значение для ключа "Х"
 lua_rawset(L,-3); // записываю пару "значение-ключ" в таблицу
 lua_pushstring(L,"Y"); // добавляю в стек ключ "Н"
 lua_pushnumber(L,Sprites[String].TempPos.y); // добавляю в стек значение для ключа "Н"
 lua_rawset(L,-3);  // записываю пару "значение-ключ" в таблицу
 return 1;
}

Из Lua эта функция используется следующим образом:

local Pos = Sprite_GetActualPos("Sprite_Name") -- в Pos записывается указатель на таблицу
    -- доступ к таблице осуществляется так
    Pos.X = 10
    Pos.Y = 20 

Дела программерские

Автоматизирую сегодня процесс шифрования текстур и компиляции Lua-скриптов. Через пару дней выложу демку с возможностями движка (графика вся нагло взятая с разных сайтов, но демка то некоммерческая, так что можно).



Помимо программирования я увлекаюсь фотографией. Раньше снимал больше, сейчас ощущается острая нехватка времени, снимаю гораздо меньше. 2 дня назад была сильная гроза, удалось заснять молнию:
Гроза, молнии

вторник, 13 июля 2010 г.

Эпическая борьба с кроссплатформенностью

Тяжко, ой как тяжко переходить на OpenGL после 3-х лет разработки в DirectX. Другой подход к текстурам, отсутствие некоторых удобных классов (типа LPD3DXSPRITE) . Но разобраться в этом нужно, ведь в результате будет +30-40% аудитории, у которых MacOS.

Ну что же, старт дан, есть 6-7 месяцев на развитие основного PC-ориентированного движка и перенос его функциональности в кроссплатформенный двиг.

понедельник, 12 июля 2010 г.

Анимация объектов при помощи "временных полос (таймлайнов)"

Обычный мой способ анимации объектов занимает довольно много кода и времени. Идея способа состоит в том, что назначаются объекту состояния (проявление альфы, изменение размера, прыжок, и.т.д ) и для каждого состояния я пишу свою логику. В итоге, для довольно сложной анимации приходится много писать.

И тут я обратил своё внимание на свой же класс системы частиц :) Для сложных эффектов я ввёл в класс понятие "временных полос". Суть их в чём. Работают они у меня на основе ассоциативного массива. В качестве ключа у меня стоит время. Допустим нужно создать объект с альфой 0 и за 2 секунды проявить его до 200. С помощью таймлайна это делается следующим образом:

//Инициализация
C_Timeline Alpha;
Alpha.Set(0.0f,0.0f) время и значение
Alpha.Set(2.0f,200.0f) время и значение

LifeTime=0.0f; //время жизни 

//Update
LifeTime += FrameTime; //FrameTime - время рендера предыдущего кадра
ObjectAlpha = Alpha.Get(LifeTime);

В этом коде, когда LifeTime будет равен 1, ObjectAlpha будет равно 100.

Так вот, посмотрел я на этот код и написал класс анимации, с использованием этих таймлайнов. Количество кода, необходимого для анимации, снизилось в разы. Результатом доволен :)

суббота, 10 июля 2010 г.

Классы в Lua

В этой небольшой статье я расскажу о создании и использовании классов в Lua при помощи стандартной библиотеки "classlib.lua".

dofile(GetResPath('Scripts\\classlib.lua')) 
-- GetResPath() - C++ функция, возвращающая путь к ресурсам движка

 
C_Sprite = class("C_Sprite") -- так объявляется класс
 
function C_Sprite:__init(Name,Texture,PosX,PosY,Left,Top,Width,Height)    -- Функция инициализации
    --Через self. задаются переменные класса
self.Name         = Name    
    self.Texture    = Texture
    self.Pos         = {x=PosX,y=PosY}
    self.StartPos    = {x=PosX,y=PosY}
    self.Size         = {Left=Left,Top=Top,Width=Width,Height=Height}
    self.Scale        = {x=1, y=1}
    self.Alpha        = 255
    Sprite_Add(Name,Texture,PosX,PosY,Left,Top,Width,Height) -- С++ функция, добавляющая спрайт в массив спрайтов 
end
function C_Sprite:Sync() 
-- Синхронизация данных класса с данными движка 
    Sprite_MoveTo(self.Name,self.Pos.x,self.Pos.y)
    Sprite_SetScale(self.Name,self.Scale.x,self.Scale.y)
    Sprite_SetAlpha(self.Name,self.Alpha)              
end
function C_Sprite:Draw()
   Sprite_Draw(self.Name)
end 
 
-- Теперь чтобы создать объект класса достаточно прописать следующее
SpriteObject = C_Sprite("TestSprite","TestTexture",512,384,100,100,100,100) 
--Обращение к свойству класса
SpriteObject.Pos.x = 10
--Вызов функции класса
SpriteObject:Sync()

Упаковываем INI файл в бинарник

В старом, "замороженном", проекте список объектов хранился в ini файле. В средней сцене было около 40-50 объектов, у каждого около 15 свойств. Через стандартные WinAPI функции процесс считывания одного такого считывания занимал секунд 6-10, что явно не айс. Решил упаковать ini в бинарник и существенно выиграл в скорости загрузки, которая стала гораздо меньше секунды :)