Cheb's Game Engine
Модератор: Модераторы
Хитрость в том, чтобы:
а) жёстко 32-битные флоаты.
б) *любую* константу в коде заворачиваешь в тайп-каст во флоат. Любую. Всегда и везде. a:= b * Single(2.0); Иначе паскаль старается считать как можно шире и делает это в платформо-зависимом чём придётся: даблы, экстендеды, чёрная магия...
Добавлено спустя 3 часа 54 минуты 43 секунды:
З.Ы. Я ничего не принимаю на веру, экспериментирую, у меня в движке встроенная тестировалка, которая вычисляет md5 по всему 32-битному диапазону (4 миллиарда всего).
Блин, вот когда неудобно, что движок вообще не собирается.
ЕМНИП, я сравнивал x86, x86-64 и arm от малины - и везде синус сошёлся до бита.
Добавлено спустя 1 минуту 16 секунд:
З.З.Ы. НО! тогда я собирал ещё в 2.6.4 для x86-64 и, ЕМНИП, 2.6.4 тоже для арм.
Добавлено спустя 5 часов 37 минут 26 секунд:
З.З.З.Ы. Затеял отдельную тестировочную программу из одного исходника, повыдранного из движка - но когда будет готова х/з, времени нет совсем, куча дел со всех сторон.
а) жёстко 32-битные флоаты.
б) *любую* константу в коде заворачиваешь в тайп-каст во флоат. Любую. Всегда и везде. a:= b * Single(2.0); Иначе паскаль старается считать как можно шире и делает это в платформо-зависимом чём придётся: даблы, экстендеды, чёрная магия...
Добавлено спустя 3 часа 54 минуты 43 секунды:
З.Ы. Я ничего не принимаю на веру, экспериментирую, у меня в движке встроенная тестировалка, которая вычисляет md5 по всему 32-битному диапазону (4 миллиарда всего).
Блин, вот когда неудобно, что движок вообще не собирается.
ЕМНИП, я сравнивал x86, x86-64 и arm от малины - и везде синус сошёлся до бита.
Добавлено спустя 1 минуту 16 секунд:
З.З.Ы. НО! тогда я собирал ещё в 2.6.4 для x86-64 и, ЕМНИП, 2.6.4 тоже для арм.
Добавлено спустя 5 часов 37 минут 26 секунд:
З.З.З.Ы. Затеял отдельную тестировочную программу из одного исходника, повыдранного из движка - но когда будет готова х/з, времени нет совсем, куча дел со всех сторон.
О, сколько нам открытий чудных!
(примечание: если вы смотрели на показатель своего проца в Intel Burn Test/Lintel и мечтали - доставайте губозакатывательную машинку. На проце с лимитом 20 гигафлопс программа на паскале выдаст в районе 0.8. Ибо там - сферический конь, написанный на самом возвышенном AVX специальными людьми - а тут по одной, да ещё с гарантированной побитовой воспроизводимостью)
1. Frac() - чудовищно тормозная функция. Позорное днище на уровне Sin(). Если вы надеялись сделать ускоренный фейковый синус типа - забудьте, он будет валяться в одной канаве с синусом и хрюкать они будут ноздря в ноздрю (sin() 0.04 гигафлопса, ebd_sin() 0.05).
Что в 13 раз медленнее умножения и в полтора раза медленнее, чем 1/sqrt(x).
2. В 64-битном коде некоторые вещи сильно медленнее, а некоторые сильно быстрее - но воспроизводимость при этом идеальная. Контрольные суммы всегда сходятся с таковыми от 32-битного кода. Чтобы не сошлись - надо лезть в ассемблер и руками тянуться в розетку RSQRTPS (быстрый и грязный обратный квадратный корень). Вот та - да, у той на каждом процессоре контрольная сумма будет иная.
ЕМНИП, на Cortex A7 контрольные суммы были абсолютно такими же - хотя казалось бы. Не могу сейчас проверить, все мои малины и апельсины пылятся на полке. И тем более не могу проверить арм 64: у меня таких просто нет. Купил в прошлом году апельсин - думал, чё так дёшево. Оказалось - внутри всё тот же Cortex A7 в обнимку с Mali 400. То есть, Orange Pi PC - это китайский аналог Raspberry Pi 2B, не выше. А в продаже всё ещё есть!
Как бы то ни было, на x86-64:
- Frac() ускорилась ровно в три раза, благодаря чему ebd_sin() обогнал Sin() в 3.4 раза - поскольку тот *ещё* замедлился, до 0.035 гигафлопса. У них специальное соревнование, штоле?
- умножение на константу, не завёрнутую в тайпкаст ко флоату, замедлилось в 2.78 раза по сравнению с завёрнутой. Причём, контрольные суммы что того, что другого варианта - сходятся со своими аналогами из 32-битного кода (а между собой они разные).
Подробнее (включая исходник теста) - когда починю свой сервер и будет, куда выложить.
Добавлено спустя 21 час 10 минут 8 секунд:
Развивая тему скорости: SQRTPS + DIVPS заранее загруженными в регистры единицами *ровно* в четыре раза быстрее штатного 1/ sqrt(x). Очевидно, компилятор использует абсолютно те же команды - только скалярные, а не векторные. Во за счёт четырёх операций за раз - и ускорение ровно в четыре раза. У меня там закоментирована RCPPS - очевидно, контрольная сумма не сошлась, побитово получимлось не так, как честное 1/x посредством DIVPS.
Но вы посмотрите, как жжот RSQRTPS (в четыре с половиной раза быстрее воспроизводимого sse и в восемнадцать раз - штатного 1/ sqrt(x)) - и становится очевидно, что это не компилятор плохой, это процессор задумчивый, когда от него требуют побитового соответствия стандартам.
Добавлено спустя 3 минуты 45 секунд:
, где mm в подавляющем большинстве случаев = 2048
(примечание: если вы смотрели на показатель своего проца в Intel Burn Test/Lintel и мечтали - доставайте губозакатывательную машинку. На проце с лимитом 20 гигафлопс программа на паскале выдаст в районе 0.8. Ибо там - сферический конь, написанный на самом возвышенном AVX специальными людьми - а тут по одной, да ещё с гарантированной побитовой воспроизводимостью)
1. Frac() - чудовищно тормозная функция. Позорное днище на уровне Sin(). Если вы надеялись сделать ускоренный фейковый синус типа
Код: Выделить всё
function ebd_sin(a: float): float; inline;
begin
a:= frac(a * float(0.318309886183790671537767526745031));// 1 / 3.141592653589793));
a:= (float(1.0) - a) * a;
Result:= float (129600.0) * a / (float(40500.0) - a);
end;Что в 13 раз медленнее умножения и в полтора раза медленнее, чем 1/sqrt(x).
2. В 64-битном коде некоторые вещи сильно медленнее, а некоторые сильно быстрее - но воспроизводимость при этом идеальная. Контрольные суммы всегда сходятся с таковыми от 32-битного кода. Чтобы не сошлись - надо лезть в ассемблер и руками тянуться в розетку RSQRTPS (быстрый и грязный обратный квадратный корень). Вот та - да, у той на каждом процессоре контрольная сумма будет иная.
ЕМНИП, на Cortex A7 контрольные суммы были абсолютно такими же - хотя казалось бы. Не могу сейчас проверить, все мои малины и апельсины пылятся на полке. И тем более не могу проверить арм 64: у меня таких просто нет. Купил в прошлом году апельсин - думал, чё так дёшево. Оказалось - внутри всё тот же Cortex A7 в обнимку с Mali 400. То есть, Orange Pi PC - это китайский аналог Raspberry Pi 2B, не выше. А в продаже всё ещё есть!
Как бы то ни было, на x86-64:
- Frac() ускорилась ровно в три раза, благодаря чему ebd_sin() обогнал Sin() в 3.4 раза - поскольку тот *ещё* замедлился, до 0.035 гигафлопса. У них специальное соревнование, штоле?
- умножение на константу, не завёрнутую в тайпкаст ко флоату, замедлилось в 2.78 раза по сравнению с завёрнутой. Причём, контрольные суммы что того, что другого варианта - сходятся со своими аналогами из 32-битного кода (а между собой они разные).
Подробнее (включая исходник теста) - когда починю свой сервер и будет, куда выложить.
Добавлено спустя 21 час 10 минут 8 секунд:
Развивая тему скорости: SQRTPS + DIVPS заранее загруженными в регистры единицами *ровно* в четыре раза быстрее штатного 1/ sqrt(x). Очевидно, компилятор использует абсолютно те же команды - только скалярные, а не векторные. Во за счёт четырёх операций за раз - и ускорение ровно в четыре раза. У меня там закоментирована RCPPS - очевидно, контрольная сумма не сошлась, побитово получимлось не так, как честное 1/x посредством DIVPS.
Но вы посмотрите, как жжот RSQRTPS (в четыре с половиной раза быстрее воспроизводимого sse и в восемнадцать раз - штатного 1/ sqrt(x)) - и становится очевидно, что это не компилятор плохой, это процессор задумчивый, когда от него требуют побитового соответствия стандартам.
Напомню, это на камне, для которого Lintel репорртует 20 гигафлопс на одно ядро (и 30 на два, ибо оба на форсаже не укладываются в TDP)...checking 1/sqrt(x)
.................................
..ok, in 45 (pure 21,2) seconds (0,1 GFLOPS)
..md5 checksum = 7BA70F1439D5E2955151CC565477E924
..checking SSE SIMD4 1/sqrt(x)
.................................
..ok, in 29 (pure 5,31) seconds (0,401 GFLOPS)
..md5 checksum = 7BA70F1439D5E2955151CC565477E924
..checking SSE SIMD4 RSQRTPS (packed quick reverse square root)
.................................
..ok, in 25 (pure 1,18) seconds (1,81 GFLOPS)
..md5 checksum = F881C03FB2C6F5BBDFF57AE5532CFFFD
Добавлено спустя 3 минуты 45 секунд:
Код: Выделить всё
dck_one_div_sqrt: begin
for m:= 0 to (mm div 8) - 1 do begin
pointer(pv):= p + m * 8 * sizeof(float);
pv[0]:= 1/sqrt(pv[0]);
pv[1]:= 1/sqrt(pv[1]);
pv[2]:= 1/sqrt(pv[2]);
pv[3]:= 1/sqrt(pv[3]);
pv[4]:= 1/sqrt(pv[4]);
pv[5]:= 1/sqrt(pv[5]);
pv[6]:= 1/sqrt(pv[6]);
pv[7]:= 1/sqrt(pv[7]);
end;
end;
{$if defined(cpu386)}
dck_sse_one_div_sqrt: begin
for m:= 0 to (mm div 8) - 1 do begin
pointer(pv):= p + m * 8 * sizeof(float);
asm
mov eax, [fourones]
MOVAPS xmm5, [eax]
mov eax, [pv]
MOVAPS xmm6, [eax]
SQRTPS xmm6, xmm6
MOVAPS xmm4, xmm5
DIVPS xmm4, xmm6 //RCPPS xmm6, xmm6 //Reciprocal Parallel Scalars or, simply speaking, 1.0/x
MOVAPS xmm7, [eax + 16]
SQRTPS xmm7, xmm7
MOVAPS [eax], xmm4
DIVPS xmm5, xmm7 //RCPSS xmm7, xmm7
MOVAPS [eax + 16], xmm5
end['eax', 'xmm6', 'xmm7', 'xmm4', 'xmm5'];
end;
end;
dck_sse_rsqrtps: begin
for m:= 0 to (mm div 8) - 1 do begin
pointer(pv):= p + m * 8 * sizeof(float);
asm
mov eax, [pv]
MOVAPS xmm6, [eax]
RSQRTPS xmm6, xmm6
MOVAPS xmm7, [eax + 16]
RSQRTPS xmm7, xmm7
MOVAPS [eax], xmm6
MOVAPS [eax + 16], xmm7
end['eax', 'xmm6', 'xmm7'];
end;
end;
{$endif}Обновил требования, почистил определения в коде от лишней вариативности
Причина: мои минималки включают Athlon 64 X2 (2005, увы, не имею) и Pentium E2140 (2007, комп по имени Серый Гусь). Оба этих двухъядерных проца - 64-битные (увы, WinXP 64-битной не бывает) и поддерживают SSE3.
Тогда какого (вставьте эпитет здесь) я в своём движке минималкой имел SSE2, а не SSE3?
Отныне, любой код для x86 и x86-64, в любых ассемблерных вставках, предполагает, что SSE3 гарантированно есть.
SSE4 и выше рассматривать не собираюсь, ибо если хватит лошадей у E2140 с его двумя ядрами на 1.6 ГГц - то любой современный улетит на орбиту и просто нет смысла рвать жилы. Мои благие намерения в сторону AVX/AVX512 так намерениями и останутся.
Всё, приехали.
Далее, для LinuxSBC у меня минималка - Cortex A7. Он имеет VFPv4-16, и то же я объявляю у себя в коде единственным поддерживаемым вариантом - если вообще когда-либо доберусь до ассемблера под арм.
Всё, приехали.
Причина: мои минималки включают Athlon 64 X2 (2005, увы, не имею) и Pentium E2140 (2007, комп по имени Серый Гусь). Оба этих двухъядерных проца - 64-битные (увы, WinXP 64-битной не бывает) и поддерживают SSE3.
Тогда какого (вставьте эпитет здесь) я в своём движке минималкой имел SSE2, а не SSE3?
Отныне, любой код для x86 и x86-64, в любых ассемблерных вставках, предполагает, что SSE3 гарантированно есть.
SSE4 и выше рассматривать не собираюсь, ибо если хватит лошадей у E2140 с его двумя ядрами на 1.6 ГГц - то любой современный улетит на орбиту и просто нет смысла рвать жилы. Мои благие намерения в сторону AVX/AVX512 так намерениями и останутся.
Всё, приехали.
Далее, для LinuxSBC у меня минималка - Cortex A7. Он имеет VFPv4-16, и то же я объявляю у себя в коде единственным поддерживаемым вариантом - если вообще когда-либо доберусь до ассемблера под арм.
Всё, приехали.
Закладывал основы слоёв лагокомпенсации - чуть не наступил на те же грабли, что один мой знакомый-гастарбайтер: ты настраиваешься, "входишь в поток", творишь на автомате, мозг выключается... Потом оглядываешься на плоды трудов своих - и слов нет, только матерные. Теперь я понимаю, как люди умудряются закрасить себя в угол.
Короче, кто же *так* структуру данных организует!
Переделать по вменяемому! 
Добавлено спустя 12 часов 38 минут 1 секунду:
Кончилось тем, что я плюнул и начал впиливать поддержку слоёв прямо в диспетчер памяти.
Для каждого текущего слоя, аллокация будет выполняться в свой набор чанков, инстансы разных слоёв никогда не окажутся в одном чанке - что просто волшебным образом полезно для чистоты кеша.
Опять же, ускоренные поля со ссылками на клонов в дочерних слоях не будут создаваться для чанков по принципу "ой, туда один инстанс этого слоя затесался", что позволит избежать дорогих и ненужных пришиваний рукавов к звёздам.
А главное - ради чего это всё - когда слой дохнет с концами, достаточно дать диспетчеру памяти команду "гаси всех". Ибо диспетчер памяти знает про все инстансы, принадлежащие конкретному слою, и может загеноцидить их задёшево.
Короче, кто же *так* структуру данных организует!
Добавлено спустя 12 часов 38 минут 1 секунду:
Кончилось тем, что я плюнул и начал впиливать поддержку слоёв прямо в диспетчер памяти.
Для каждого текущего слоя, аллокация будет выполняться в свой набор чанков, инстансы разных слоёв никогда не окажутся в одном чанке - что просто волшебным образом полезно для чистоты кеша.
Опять же, ускоренные поля со ссылками на клонов в дочерних слоях не будут создаваться для чанков по принципу "ой, туда один инстанс этого слоя затесался", что позволит избежать дорогих и ненужных пришиваний рукавов к звёздам.
А главное - ради чего это всё - когда слой дохнет с концами, достаточно дать диспетчеру памяти команду "гаси всех". Ибо диспетчер памяти знает про все инстансы, принадлежащие конкретному слою, и может загеноцидить их задёшево.
"WinXP 64-битной не бывает "...
Упс !
https://ru.wikipedia.org/wiki/Windows_X ... 64_Edition
Зы
"Лайт-новеллу" про "битву за время" пришлось перечитывать что-б хоть немного вникнуть .
( Впечатление, что возьмись ты за квантовые вычисления они бы тебе слишком простыми показались
"Ну подумаешь Шор, Дойч-Йожи и Гровер какие-то! Вот основы слоёв лагокомпенсации это мерва...
" )
Я вот недавно освоил потокове обертки вокруг всего, что может потенциально повиснуть при чтении данных из интернета ( последний хит обертка вокруг CheckUrl (!) То есть то что должно защищать сбоев пришлось отдельно страховать запуская в своем личном "виртуальном-хроно-срезе" ) Но разумеется так пинать время как это делает Великий и Ужасный Какан я и близко не умею.
Добавлено спустя 41 минуту 4 секунды:
В начале такой "Щаз только тапочки одену!" (Сори за "мини мангу" Остапа снова понесло ...
)

А утром следующего дня "выйдя из потока" .. Упс! Что это было ...

"И снова годы исследований..."

"Что-то даже получилось..."

Но елку пришлось вернуть в лес.. (Бо на горизонте появились новые мысли и планы! )

Упс !
https://ru.wikipedia.org/wiki/Windows_X ... 64_Edition
Зы
"Лайт-новеллу" про "битву за время" пришлось перечитывать что-б хоть немного вникнуть .
( Впечатление, что возьмись ты за квантовые вычисления они бы тебе слишком простыми показались
Я вот недавно освоил потокове обертки вокруг всего, что может потенциально повиснуть при чтении данных из интернета ( последний хит обертка вокруг CheckUrl (!) То есть то что должно защищать сбоев пришлось отдельно страховать запуская в своем личном "виртуальном-хроно-срезе" ) Но разумеется так пинать время как это делает Великий и Ужасный Какан я и близко не умею.
Добавлено спустя 41 минуту 4 секунды:
А это увы знакомо .... Здорово напоминает мои попытки сделать свой парсер схем хайасма.Cheb писал(а):Потом оглядываешься на плоды трудов своих - и слов нет, только матерные. Теперь я понимаю, как люди умудряются закрасить себя в угол.
В начале такой "Щаз только тапочки одену!" (Сори за "мини мангу" Остапа снова понесло ...

А утром следующего дня "выйдя из потока" .. Упс! Что это было ...

"И снова годы исследований..."

"Что-то даже получилось..."

Но елку пришлось вернуть в лес.. (Бо на горизонте появились новые мысли и планы! )

Последний раз редактировалось Alex2013 22.03.2023 11:25:48, всего редактировалось 1 раз.
Вот. Таких разработчиков потом причисляют к лику святых.Alex2013 писал(а):Я вот недавно освоил потокове обертки вокруг всего, что может потенциально повиснуть при чтении данных из интернета
Хотя, по хорошему, обёртки нужны вокруг любых обращений к диску тоже. Потому что диск может быть сетевой, сейчас недоступный - и простая наивная попытка получить текущую папку оборачивается висяком в многие минуты, пока винда упорно долбится, пытаясь достучаться до выключенного файл-сервера.
Ыыыы... Это ещё повезло. Асли на этой ёлке уже висит что-то важное текущее ?Alex2013 писал(а):Но елку пришлось вернуть в лес..
По ходу понадобилось ваять хотническое "Разрежённый массив объектов, индексуемый тиком", где тик тикает вперёд и окно актуальных индексов смещается вместе с ним. Это нужно для кладбищ (для каждого тика своё, они лочатся по наличию слоёв-потомков) и для будильников (когда объект говорит "разбудите меня через полчасика", ибо физика ленивая). Решил, что специализация TMap слишком медленная, расширил скользящим окном на 1000 милисекунд вперёд. А сам тик - сущность зацикленная, заворачивается ровно через двое суток (но все считают его dword'ом). И, чисто случайно, по ходу, заглянул, как там у меня с оптимизированным массивом объектов (который бы не дёргал Setlength на каждом добавлении), поддерживающим сериализацию.
Чо, есть такой. Ещё в 2003-м году сделанный, оптимизированный под Фри Паскаль 1.0.6
Я заглянул в бездну, а бездна заглянула в меня:
Код: Выделить всё
procedure RP_TAOMO (PField: pointer; //OP: TTraverserOperation;
Tind: longint;
FieldProperties: TFieldPropertiesSet); RP_CallingConvention;
var
o: TAOMO;
s: longint;
begin
case Cps.CurrentTraverser.Operation of
trop_Deserialize: begin
s:= ReadLongInt();
if Assigned(PField) then begin
if s < 0 then pointer(PField^):=nil
else begin
TAOMO(PField^):=TAOMO.Create;
TAOMO(PField^).Load(s);
end;
end
else begin
if s >= 0 then begin
o:=TAOMO.Create; //load it and destroy it. The fate is cruel.
o.Load(s);
o.Free;
end;
end
end;
trop_Serialize: if Assigned(pointer(PField^))
then TAOMO(PField^).Save(FieldProperties)
else WriteNil;
trop_Generic: begin
for s:=0 to TAOMO(PField^).High do
Cps.CurrentTraverser.OnObject(
TChepersyObject(TAOMO(PField^).DataPointer(s)^)
// Error: Can't take the address of constant expressions
//TChepersyObject(TAOMO(PField^)[s])
, FieldProperties)
end;
end;
end;З.Ы. А ещё я планирую *сильно* сэкономить на интерфейсе редактора моделей: любой скелет и его иерархия костей будут создаваться кодом, ручным перечислением в исходниках на Паскале. Чтобы в редакторе их только двигать, подбирать размеры коллайдеров и положение точек привязки.
Устав раз за разом реанимировать труп, и обнаружив, что основная функциональность TDyna была "временно" заменена затычкой году этак в 2006-м, низведя его производительность до пошлого массива, я озверел и бросился переделывать яго на дженериках.
Ох, чует моё сердце, нарадуюсь я ещё с отладкой, когда проект, эдак к осени, соберётся наконец.
Ох, чует моё сердце, нарадуюсь я ещё с отладкой, когда проект, эдак к осени, соберётся наконец.
Полировал диздок, балансировал классы, упрощал механики, оставил пять классов, отправив деву щита лесом - но всё чувствовал,ч то чего-то не хватает.
Вот. Классика. Добавил в стандартный набор оружий, три класса из пяти смогут выбрать это вместо чего-нибудь полезного:
НЕ знаю, на каких грибах вскармливались дженерики, но это явно было что-то ядрёное.
Где-то в коде, в разделе имплементации у меня была давно забытая
- и компилятор ругается "Global Generic template references static symtable" на метод дженерика, в котором есть её вызов.
Если её добавить в интерфейс - перестаёт ругаться, что логично, учитывая природу дженериков.
Но, засада в том, что сообщение не уточняет, на какой конкретно символ из дофига длинного метода компилятор саггрился, и тыкает в end;.
Good luck, have fun
В багтрекер штоле зарепортить?.. Нее, лень.
Вот. Классика. Добавил в стандартный набор оружий, три класса из пяти смогут выбрать это вместо чего-нибудь полезного:
Добавлено спустя 11 часов 2 минуты 24 секунды:Skull Storm: a slowly charging swarm of explosive skulls, one per 0.8s. One skull does 50 damage with a splash radius of 1.5m. Only 15 damage to blocks. Fire in a conical burst of 20 degrees, skulls then converge to spiral in a cylinder 2.5 meters across.
Penalties: deafening sound, the skulls screech and cackle. Cannot be canceled. Fires on its own when you run out of MP or accumulate 6 skulls.
НЕ знаю, на каких грибах вскармливались дженерики, но это явно было что-то ядрёное.
Где-то в коде, в разделе имплементации у меня была давно забытая
Код: Выделить всё
function min(a, b: integer): integer; inline;
begin
if a < b then Result:=a else Result:=b;
end;Если её добавить в интерфейс - перестаёт ругаться, что логично, учитывая природу дженериков.
Но, засада в том, что сообщение не уточняет, на какой конкретно символ из дофига длинного метода компилятор саггрился, и тыкает в end;.
Good luck, have fun
В багтрекер штоле зарепортить?.. Нее, лень.
Начитавшись в википедии про суперконтинентальные циклы, был стёгнут по заднице озарением.
Теперь то, что раньше было монолитной "логикой", удобной, как чемодан без ручки, раскололось подобно Гондване: отдельно - логика, отдельно - диспетчер слоёв (причём, оба - НЕ менеджед), а корневой менеджед объект, что сериализуется в поток - это вообще транзиентный контейнер, создаваемый под это действо.
И сразу так легко стало. И инпуты (состояние которых тоже должно сериализоваться - я не забыл урок Clive Barker's Undying, где невидимый триггер перехода карты заставлял твой заряженный мега-бабах !внезапно выстрелить тебе под ноги: игра, видите ли, забывала, что ты держишь ЛКМ зажатой) выпнуты в отдельный от логики менеджед класс.
Теперь то, что раньше было монолитной "логикой", удобной, как чемодан без ручки, раскололось подобно Гондване: отдельно - логика, отдельно - диспетчер слоёв (причём, оба - НЕ менеджед), а корневой менеджед объект, что сериализуется в поток - это вообще транзиентный контейнер, создаваемый под это действо.
И сразу так легко стало. И инпуты (состояние которых тоже должно сериализоваться - я не забыл урок Clive Barker's Undying, где невидимый триггер перехода карты заставлял твой заряженный мега-бабах !внезапно выстрелить тебе под ноги: игра, видите ли, забывала, что ты держишь ЛКМ зажатой) выпнуты в отдельный от логики менеджед класс.
Проект стоит (раздражает), на досуге уигрался в ТФ2 и понял, что как бы ни был хорош убер - механику эту копировать не стоит, ни в каком виде.
Убер - это, по сути, средство взлома укреплённых позиций, созданных размещением турелей на статической карте. Но карта-то у нас динамическая. И средств взлома крепостей хватает без того - чуть не до ядрён-батона.
Нет, я воскрешу почившую Деву щита в виде лодаута Портняжки - которая вместо ножниц сможет выбрать щит (купол силового поля полтора метра в диаметре) который отнимет рукопашную атаку, взамен превратив её в хила-танка. Тогда лечимая держится позади неё, иногда выскакивая стрельнуть, а она прёт танком, ибо щит - абсолютно непробиваемый, отражающий все снаряды в случайном направлении.
Чтобы не вышла лютая имба, щит должен либо активироваться как элемент защитного набора (т.е. стоить дохрена маны и иметь ограниченное время действия) либо отражённый урон должен стоить маны. Ну, и пенальти на скорость передвижения и невозможность летать.
Так... Теперь сбалансировать всё это. Потому что в подземных тоннелях - *реально* конец света. Хмм... Делать щит отражать *дружественные* снаяряды тоже - это обязательно, но, может быть, делать его схлопываться, если с ним залезть в узость? Типа, только на открытом воздухе.
Ещё возможная уникальная фича - раз наш хил умеет летать (единственный из всех классов) - можно добавить вариант "поднять лечимую с собой в воздух и сбросить на вражеское укрепление сверху".
И никакого, нафик, убера.
Так... Вдогонку. Генератор щита берёт слот вспомогательного - т.е. лишает её дистанционной атаки. Цена - ноль, но разворачивается за две секунды, кулдаун - пять секунд, *не* останавливает рукопашные атаки и выстрелы в упор (при пересечении с противником или стеной - схлопывается и уходит в кулдаун), а ещё скорость разворота ограничена, не выше 180 градусов за две секунды. А ещё блокирует спринт и акробатику. И пока щит в кулдауне - невозможно переключить оружие (например, на рукопашные ножницы). И пул хит-пойнтов становится общим, любой урон получают обе, распределяется соразмерно текущим хит-пойнтам.
Возможность поднять лечимую в воздух - также занимает слот вспомогательного. Контроль в связке получает именно лечимая, и решения, куда лететь и кого бомбить, занимает тоже она. Ты за ней волочёшься, как воздушный шарик на привязи. Аналогично, общий пул хитов.
..Может, сделать это не фичей лодаюта, а фичей портняжки вообще? Всегда, когда лечит, урон делится и сдохнуть могут только вместе. Тогда при игре хилом нужен скилл на уворот - и совсем не нужно думать про всякие там зарядки уберов. Имбы не получается, поскольку у Портняжки всего 50 хитов, но бугурт на тему зафейлившего хила, из-за кривокрылости которого сдох танк - очень в кассу.
Добавлено спустя 25 минут 34 секунды:
..так, для простоты:
1. При отражении больше 100 урона в секунду, щит начинает жрать ману. Скажем, 20/с.
2. Активация щита - фактически переход в режим полёта (с поджатыми ногами) - требования те же, свободное пространство не менее 3 блоков и не касаться стен.
3. Отражённые щитом снаряды летят не случайно, а точно в обратную сторону, но недалеко (метра четыре) а потом угасают/детонируют. Как следствие - это неслабый (и единственный) туз против веера искр (шотган) с близкой дистанции.
4. Отражение снарядов отбрасывает, а по краю - ещё и разворачивает. Это не кнопка "я в домике" - надо активно сопротивляться, чтобы не развернули.
5. Осадные снаряды на щите рвутся, придавая портняжке кинетическое ускорение (ёжик сильный, но лёгкий) - вплоть до фатального влетания спиной в стенку на скорости 500%.
Убер - это, по сути, средство взлома укреплённых позиций, созданных размещением турелей на статической карте. Но карта-то у нас динамическая. И средств взлома крепостей хватает без того - чуть не до ядрён-батона.
Нет, я воскрешу почившую Деву щита в виде лодаута Портняжки - которая вместо ножниц сможет выбрать щит (купол силового поля полтора метра в диаметре) который отнимет рукопашную атаку, взамен превратив её в хила-танка. Тогда лечимая держится позади неё, иногда выскакивая стрельнуть, а она прёт танком, ибо щит - абсолютно непробиваемый, отражающий все снаряды в случайном направлении.
Чтобы не вышла лютая имба, щит должен либо активироваться как элемент защитного набора (т.е. стоить дохрена маны и иметь ограниченное время действия) либо отражённый урон должен стоить маны. Ну, и пенальти на скорость передвижения и невозможность летать.
Так... Теперь сбалансировать всё это. Потому что в подземных тоннелях - *реально* конец света. Хмм... Делать щит отражать *дружественные* снаяряды тоже - это обязательно, но, может быть, делать его схлопываться, если с ним залезть в узость? Типа, только на открытом воздухе.
Ещё возможная уникальная фича - раз наш хил умеет летать (единственный из всех классов) - можно добавить вариант "поднять лечимую с собой в воздух и сбросить на вражеское укрепление сверху".
И никакого, нафик, убера.
Так... Вдогонку. Генератор щита берёт слот вспомогательного - т.е. лишает её дистанционной атаки. Цена - ноль, но разворачивается за две секунды, кулдаун - пять секунд, *не* останавливает рукопашные атаки и выстрелы в упор (при пересечении с противником или стеной - схлопывается и уходит в кулдаун), а ещё скорость разворота ограничена, не выше 180 градусов за две секунды. А ещё блокирует спринт и акробатику. И пока щит в кулдауне - невозможно переключить оружие (например, на рукопашные ножницы). И пул хит-пойнтов становится общим, любой урон получают обе, распределяется соразмерно текущим хит-пойнтам.
Возможность поднять лечимую в воздух - также занимает слот вспомогательного. Контроль в связке получает именно лечимая, и решения, куда лететь и кого бомбить, занимает тоже она. Ты за ней волочёшься, как воздушный шарик на привязи. Аналогично, общий пул хитов.
..Может, сделать это не фичей лодаюта, а фичей портняжки вообще? Всегда, когда лечит, урон делится и сдохнуть могут только вместе. Тогда при игре хилом нужен скилл на уворот - и совсем не нужно думать про всякие там зарядки уберов. Имбы не получается, поскольку у Портняжки всего 50 хитов, но бугурт на тему зафейлившего хила, из-за кривокрылости которого сдох танк - очень в кассу.
Добавлено спустя 25 минут 34 секунды:
..так, для простоты:
1. При отражении больше 100 урона в секунду, щит начинает жрать ману. Скажем, 20/с.
2. Активация щита - фактически переход в режим полёта (с поджатыми ногами) - требования те же, свободное пространство не менее 3 блоков и не касаться стен.
3. Отражённые щитом снаряды летят не случайно, а точно в обратную сторону, но недалеко (метра четыре) а потом угасают/детонируют. Как следствие - это неслабый (и единственный) туз против веера искр (шотган) с близкой дистанции.
4. Отражение снарядов отбрасывает, а по краю - ещё и разворачивает. Это не кнопка "я в домике" - надо активно сопротивляться, чтобы не развернули.
5. Осадные снаряды на щите рвутся, придавая портняжке кинетическое ускорение (ёжик сильный, но лёгкий) - вплоть до фатального влетания спиной в стенку на скорости 500%.
Я тут совершенно случайно наткнулся на графон и механику игры Star Rail
https://youtu.be/Ye4qk1SW9TE
https://youtu.be/sQT8kCDOz_U
https://youtu.be/S6pEVSDTxgE
https://www.ixbt.com/live/games/prevyu- ... -jrpg.html
Черт подери это действительно привет из альтернативной реальности где не боятся рисовать действительно красивую графику без оглядки на убогую моду всячески уродовать (особенно женские) персонажи.
+ Продуманность деталей и гиперреалистичность фонового окружения не смотря на анимешность стиля просто поражает.
Так что читая про "Деву щита" я невольно представил ее "стиле Star Rail" понятно что Какан такие модели и плавную анимацию скорее всего не потянет но думаю фоновое окружение из Star Rail можно немного скопипастить.
https://youtu.be/Ye4qk1SW9TE
https://youtu.be/sQT8kCDOz_U
https://youtu.be/S6pEVSDTxgE
https://www.ixbt.com/live/games/prevyu- ... -jrpg.html
Черт подери это действительно привет из альтернативной реальности где не боятся рисовать действительно красивую графику без оглядки на убогую моду всячески уродовать (особенно женские) персонажи.
+ Продуманность деталей и гиперреалистичность фонового окружения не смотря на анимешность стиля просто поражает.
Так что читая про "Деву щита" я невольно представил ее "стиле Star Rail" понятно что Какан такие модели и плавную анимацию скорее всего не потянет но думаю фоновое окружение из Star Rail можно немного скопипастить.
Великолепный стиль графики - почти мой идеал.
Но надо не забывать, что мир - это торт из кубиков. У него три текстуры: бисквит, шоколад с мармеладом, шоколод с изюмом. На этом с миром - всё.
Игра - первая, мой фокус - на геймплее, и на анимациях. Да и то - первоначально оно будет обкатываться на деревянных марионетках - буратинах, которые в завершённой игре станут скинами для ботов.
Геймплей, анимации - мне хватит выше головы. А мир - лишь фон, абсолютный минимум.
Но... Не надо недооценивать мощь GLES2 и ранних встроенных видях Intel десятилетней давности. При правильном использовании графоний класса dx9 - это великая сила.
Особенно когда скины игроков - это 95% игры, а остальное - торт из кубиков.
З.Ы. Если осилю - может потом ещё декоративных объектов добавлю - там клубничины размером с воллейбольный мяч, кремовые розочки и прочая.
Добавлено спустя 1 минуту 43 секунды:
З.Ы. И ещё, такую детализацию причёсок и костюмов я не потяну с вероятностью равной вероятности, что шаттл хубологов не взлетит.
Добавлено спустя 20 минут 54 секунды:
Дизайн, дизайн, дизайн... Изучив The TF2 Sentry Gun vs The Overwatch Turret и прочие подобные материалы я уже давно принял решение, что *мои* турели будут ещё более брутальными, чем в ТФ2. Ботанка может посадить три искровых цветочка или один искровой и один ракетный - и стрелять эта сволочь будет *самонаводящимися* снарядами, с такой плотностью огня, что даже толстый танк дохнет за одну секунду. И как ПВО против такой заразы, как летающий хил-трикстер с кучей вредных абилок.
Почему? Чтобы заставить в стратегию, подкопы и продвижение, спамя укрытиями. А профессиональные лемминги чтобы дохли профессионально быстро.
Но надо не забывать, что мир - это торт из кубиков. У него три текстуры: бисквит, шоколад с мармеладом, шоколод с изюмом. На этом с миром - всё.
Игра - первая, мой фокус - на геймплее, и на анимациях. Да и то - первоначально оно будет обкатываться на деревянных марионетках - буратинах, которые в завершённой игре станут скинами для ботов.
Геймплей, анимации - мне хватит выше головы. А мир - лишь фон, абсолютный минимум.
Но... Не надо недооценивать мощь GLES2 и ранних встроенных видях Intel десятилетней давности. При правильном использовании графоний класса dx9 - это великая сила.
Особенно когда скины игроков - это 95% игры, а остальное - торт из кубиков.
З.Ы. Если осилю - может потом ещё декоративных объектов добавлю - там клубничины размером с воллейбольный мяч, кремовые розочки и прочая.
Добавлено спустя 1 минуту 43 секунды:
З.Ы. И ещё, такую детализацию причёсок и костюмов я не потяну с вероятностью равной вероятности, что шаттл хубологов не взлетит.
Добавлено спустя 20 минут 54 секунды:
Дизайн, дизайн, дизайн... Изучив The TF2 Sentry Gun vs The Overwatch Turret и прочие подобные материалы я уже давно принял решение, что *мои* турели будут ещё более брутальными, чем в ТФ2. Ботанка может посадить три искровых цветочка или один искровой и один ракетный - и стрелять эта сволочь будет *самонаводящимися* снарядами, с такой плотностью огня, что даже толстый танк дохнет за одну секунду. И как ПВО против такой заразы, как летающий хил-трикстер с кучей вредных абилок.
Почему? Чтобы заставить в стратегию, подкопы и продвижение, спамя укрытиями. А профессиональные лемминги чтобы дохли профессионально быстро.
З.Ы. Всё, конечно, будет энцать раз корректироваться на готовой игре, но намеченный темп - неторопливый. Типовая скорость перемещения в TF2 (5.5м/с) примерно соответствует моему спринту (который возможен только вперёд, на 6 м/с), а нормальная скорость перемещения - вполовину от того (3м/с = 100%).
Перебалансировал Ботанку, оставив только основной слот оружия, как оружие - причём, фаерболомётная турель перемещается в него, при выборе оставляя её с одной киркой для атаки собственнолично.
Убрал вереницу искр и веер искр, превращавшие её в полноценную боевую имбу - оставил только рой искр (калька с нэйлгана из третьего квейка) - который хоть мощный, но неудобный в использовании.
Добавил варианты: репей, который суть слабенькая бомба-липучка, и лианный хлыст, который вообще рукопашный, до 5 метров, но стаггерит - и расчитан на комбо с последующим рашем собственной тушкой и пинанием ногой (падающего-подтолнки) чтобы сметать противников с воздушных мостов.
Из вспомогательного: перенёс туда искромётный цветочек (основную турель), добавил вариант цветок-репейник, котоый страдает страшно малой дальностью, но в относительно замкнутых пространствах способен засрать репьями всё и вся. Перенёс во вспомогательное из дополнителього и колючие кусты - которые вообще пассивка, зато не запирают ману и сажать их можно до посинения.
Волоконное дерево ушло лесом: лечить хит-пойнты теперь только и исключительно к портняжке. У неё для этого волоконный тотем есть во вспомогательном.
См. http://forum.chebmaster.com/viewtopic.p ... 83#p161783 (на английском)
Добавлено спустя 12 часов 46 минут 38 секунд:
Не, к чёрту хлыст. Берём эйрбласт от пайро, делаем медленно заряжающимся (4 секунды чтобы мочь сдуть нафик), и вражьи снаряды не отражает, а только слегка отклоняет - и вот это делаем *единственным* оружием. Чисто сметать посторонних с твоих воздушных мостов.
Причём, умышленно бесполезным в подземельях, развивая дихотомию "элой vs морлок" между ботанкой и крушилой.
Убрал вереницу искр и веер искр, превращавшие её в полноценную боевую имбу - оставил только рой искр (калька с нэйлгана из третьего квейка) - который хоть мощный, но неудобный в использовании.
Добавил варианты: репей, который суть слабенькая бомба-липучка, и лианный хлыст, который вообще рукопашный, до 5 метров, но стаггерит - и расчитан на комбо с последующим рашем собственной тушкой и пинанием ногой (падающего-подтолнки) чтобы сметать противников с воздушных мостов.
Из вспомогательного: перенёс туда искромётный цветочек (основную турель), добавил вариант цветок-репейник, котоый страдает страшно малой дальностью, но в относительно замкнутых пространствах способен засрать репьями всё и вся. Перенёс во вспомогательное из дополнителього и колючие кусты - которые вообще пассивка, зато не запирают ману и сажать их можно до посинения.
Волоконное дерево ушло лесом: лечить хит-пойнты теперь только и исключительно к портняжке. У неё для этого волоконный тотем есть во вспомогательном.
См. http://forum.chebmaster.com/viewtopic.p ... 83#p161783 (на английском)
Добавлено спустя 12 часов 46 минут 38 секунд:
Не, к чёрту хлыст. Берём эйрбласт от пайро, делаем медленно заряжающимся (4 секунды чтобы мочь сдуть нафик), и вражьи снаряды не отражает, а только слегка отклоняет - и вот это делаем *единственным* оружием. Чисто сметать посторонних с твоих воздушных мостов.
Причём, умышленно бесполезным в подземельях, развивая дихотомию "элой vs морлок" между ботанкой и крушилой.
Хоба. Вот в чём было дело!
Нашёл мега-сайт, который позволяет дизасемблировать на лету: https://godbolt.org/
Так почему такая разница между умножениями, завёрнутыми и не завёрнутыми в тайпкаст?
вылилось в
..чё?
То есть, если *просто* множить - компилятор задействует x87 наших дедушек, а тайпкаст заставляет его переключиться на sse?...
Wut?..
Нашёл мега-сайт, который позволяет дизасемблировать на лету: https://godbolt.org/
Так почему такая разница между умножениями, завёрнутыми и не завёрнутыми в тайпкаст?
Код: Выделить всё
{$mode objfpc}
unit krya;
{$fputype sse64}
interface
type float = single;
var a, b: float;
procedure testit;
implementation
procedure testit;
begin
b:= a * float(3.14);
end;
procedure testit1;
begin
b:= a * 3.14;
end;
end. Код: Выделить всё
testit():
movss xmm0,DWORD PTR ds:0x430ef8
mulss xmm0,DWORD PTR ds:0x4244b0
movss DWORD PTR ds:0x430efc,xmm0
ret
testit1():
fld DWORD PTR ds:0x430ef8
fld TBYTE PTR ds:0x4244c0
fmulp st(1),st
fstp DWORD PTR ds:0x430efc
ret То есть, если *просто* множить - компилятор задействует x87 наших дедушек, а тайпкаст заставляет его переключиться на sse?...
Wut?..
