Физический движок, являющийся частью Atrium, будет разрабатываться в качестве отдельного проекта — dmech.
Исходники доступны на GitHub:
https://github.com/gecko0307/dmech
Физический движок, являющийся частью Atrium, будет разрабатываться в качестве отдельного проекта — dmech.
Исходники доступны на GitHub:
https://github.com/gecko0307/dmech
Страница проекта:
https://github.com/gecko0307/dlib
Скачать dlib 0.1.2:
https://github.com/gecko0307/dlib/releases/tag/v0.1.2
Состоялся первый нестабильный релиз коллекции библиотек dlib.
Нововведений по сравнению с последней ревизией SVN практически нет (если не считать функцию генерации тангенс-векторов для полигональных мешей) — релиз просто ознаменовал переезд проекта на GitHub (однако старый репозиторий в обозримом будущем продолжит обновляться параллельно с новым).
Одновременно с этим был зарегистрирован пакет dlib в реестре DUB: http://code.dlang.org/packages/dlib.
Страница проекта:
https://github.com/gecko0307/dlib
Скачать dlib 0.1:
https://github.com/gecko0307/dlib/releases/tag/v0.1
Читайте в этом номере:
Номер доступен для онлайн-чтения и загрузки на сервисе Issuu.com, Документах Google и Dropbox.
Последние новости по проекту вы можете узнать в публичной странице журнала в социальной сети Google+: http://gplus.to/fpsmag. Добавляйте нас в круги, оставляйте свои комментарии и отписывайтесь в нашем сообществе.
Изменения доступны в ревизии r23 и выше.

Оружие в шутерах от первого лица не должно быть прибито к камере гвоздями – оно раскачивается в такт ходьбе, да и при стоянии на месте медленно ходит туда-сюда из-за постоянного движения рук. Конечно, довольно трудно сымитировать этот эффект в полном соответствии с реальностью, но можно обойтись дешевым и убедительным фейком. Оружие можно двигать вдоль кривой Лиссажу: x = sin(t), y = cos(2t). В результате получается траектория, изображенная на рисунке справа.
Vector2f lissajousCurve(float t)
{
return Vector2f(sin(t), cos(2 * t));
}
//...
if (playerWalking)
t += 10.0f * delta;
else
t += 1.0f * delta;
if (t > 2 * PI)
t = 0.0f;
Vector2f p = lissajousCurve(t) / 10.0f;
weapon.localPos = Vector3f(p.x, p.y, 0.0f);
Состоялось довольно значительное обновление кодовой базы Atrium. В частности, было реализовано главное меню и меню паузы. Кроме того, репозиторий был синхронизирован с последней ревизией dlib.
Доступны свежие сборки:
Для Windows (1,74 МБ)
Для Linux (2,76 МБ).
Исходники проекта доступны на GitHub.
Свершилось! Результат моей работы за последние месяцы — основа будущего шутера от первого лица с физическими головоломками — доступен на GitHub. Добавлена заготовка игрового уровня, а также действующий гравитационный излучатель, при помощи которого игрок может передвигать динамические объекты (из-за ограничений в нынешнем физическом движке, таковые объекты представлены только сферами, но в будущем не исключена поддержка других типов тел). Исходники собираются DMD 2.060 и выше. Под Linux рекомендуется использовать LDC.
Сборка для Windows: atrium-testbuild3-win32.zip (1.18 МБ).
Один из распространенных приемов в игровой логике – использование элемента случайности. Он используется, например, при машинной генерации уровней, лабиринтов, или когда на локации появляются случайные враги или бонусы. При этом зачастую требуется выбрать случайный объект из какого-либо списка с учетом того, что некоторые из них имеют большую вероятность выбора, чем другие – то есть, имеют больший “вес”.
Я написал особую реализацию алгоритма такой выборки – она работает не с обычными массивами, а с перечислениями (enum). В шаблон функции передаются два перечисления – самих элементов и их весов. Этот пример иллюстрирует также богатые возможности метапрограммирования, CTFE и интроспекции в D.
import std.stdio;
import std.traits;
import std.random;
import std.algorithm;
T weightedRandomEnum(T, W)()
if (isNumeric!W &&
is(T == enum) && is(W == enum) &&
EnumMembers!T.length == EnumMembers!W.length)
{
enum members = [EnumMembers!T];
enum weights = [EnumMembers!W];
enum weightsSum = reduce!("a + b")([EnumMembers!W]);
auto randomNumber = uniform(0, weightsSum);
foreach(i, weight; weights)
{
if (randomNumber < weight)
return members[i];
else
randomNumber -= weight;
}
assert(0, "Should never get here");
}
enum Color
{
Red, Yellow, Green, Blue
}
enum Weights
{
Red = 100,
Yellow = 20,
Green = 20,
Blue = 5
}
void main()
{
foreach(i; 0..10)
writeln(weightedRandomEnum!(Color, Weights));
}