Форум: "Игры";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
ВнизНепонятные глюки со спрайтами и Delphi Найти похожие ветки
← →
NailMan (2003-08-13 16:17) [0]Пишу я сейчас парсер конфигов для загрузки моделек. При добавлении спрайтов(габаритных фонарей) к актеру все идет пучком: спрайты создаются в глобальном массиве спрайтов, но когда делро доходит до рендера -происходит глюк. Заключается он в том что если в конфиге описаны 3 координаты и цвет 3-х спрайтов, то они в дальнейшем нормально функционируют при перемещении актера(спрайты привязаны к актеру в определенных точках и при перемещениях/поворотах актер двигает все за собой), но стоит добавить четвертый спрайт(точку) и это спрайт перемещает 2-й спрайт на свое место и сам находясь там же перестает двигаться за объектом(только поворачивается).
Функция загрузки спрайта и кусок парсера ниже:
//Загрузка спрайта
Procedure TActor.LoadFlare(n:string;Var Spr:TGameSprite);
var
v,s:td3dvector;
c:td3dcolorvalue;
begin
//В строке n находится строка вида
//(-1.8,4.1,10.2)(1,0,0,1)(4,4,4)
//где первая скобка - координаты, вторая - цвет RGBA, третья - масштаб
v:=extractcoords(n);
c:=extractcolorvalue(n);
s:=extractcoords(n);
Spr:=TGameSprite.Create("Flare1.BMP",GSpr_FLARE);
Spr.Color:=D3DCOLOR_COLORVALUE(C.r,
c.g,
c.b,
c.a);
//Задаем считанные координаты точки привязки базовым(привязочным) координатам спрайта
Spr.POSZ:=v;
Spr.FSize:=s;
//ресетим матрицу. В принципе этого можно и не делать, так как при перемещении спрайта его матрица заполняется полность вручную.
d3dxmatrixidentity(Spr.Fmat);
end;
И вот кусок парсера файла конфигурации актера
...
//Signal flares section
SlaveSprCount:=0;
SearchLnstr(f,"[Signal flares]",false);
readlnstr(f,n);
count:=extractdword(n); //Вычленяет Dword из строки вида "xxx=123"
For i:=0 to Count-1 do
begin
readlnstr(f,n);
//получаем индекс незанятого(=nil) спрайта в общем массиве и помещаем его в список связанных спрайтов у актера
SlaveSpr[SlaveSprCount]:=GetFreeIndex(FREE_SPRITE);
//для наглядности присваиваем индекс левой переменной
Z:=SlaveSpr[SlaveSprCount];
//грузим спрайт
LoadFlare(n,Z);
Spr[Z].Enabled:=true;
end;
...
Вот кусок процедуры перемещения актера:
Procedure TActor.AMoveTo;
var i:integer;
m:td3dmatrix;
begin
//собственное перемещение координат и положения актера
Moveto;
...
For i:=0 to SlaveSprCount-1 do
begin
//быстрое копирование матрицы через строковую операцию movsd или через 3DNow!
FastMatrixMove(world.fMat,M);
//обнуление координат
m._41 := 0;
m._42 := 0;
m._43 := 0;
//трансформирование координат спрайта матрицей актера(относительно центра актера) и координатами привязки
D3DXVec3TransformCoord(Spr[SlaveSpr[i]].fpos,Spr[SlaveSpr[i]].posz,m);
//смещение положения(трансформированного относительно нуля) спрайта в координаты актера
D3DXVec3Add(tempvec,Spr[SlaveSpr[i]].fpos,World.POS);
Spr[SlaveObj[i]].SetPos(tempvec);
end;
...
вот...
собсно как я и говорил уже, в случае 3-х привязанных спрайтов, они двигаются вместе с актером нормально(и расположены в тех точках как задано в конфиге). Стоит добавить четвертую точку/спрайт как все смещается и неправильно двигается(этот самый четвертый спрайт).
Координаты и другие параметры четвертого спрайта на результат не влияют.
Пятый и так далее спрайты ничего дают еще худшую картину.
Максимальное количество подчиненнхй спрайтов(индексов) у актера ограничено 64 штуками.
Вобщем в чем глюк может быть?
← →
NailMan (2003-08-13 16:23) [1]Да недоглядел когда вставлял кусок в окно редактирования(когда вырезал логгинг создания спрайта):
в куске где парсится конфиг, после строки
Spr[Z].Enabled:=true;
идет конечно же еще и строка
Inc(SlaveSprCount);
← →
cyborg (2003-08-13 23:23) [2]Трудно разобраться в том, чего сам не писал.
Что такое TGameSprite?
extractcoords(n); как работает? Почему 2 раза одно и тоже к разным переменным делаешь?
v:=extractcoords(n);
s:=extractcoords(n);
Вместо этого
For i:=0 to Count-1 do
Лучше делать
For i:=1 to Count do затем использовать индекс I-1
Например если коунт будет равен нулю, то цикл будет выполняться, и может возникнуть ошибка, во втором случае цикл исполняться не будет.
Неизвестно что такое For i:=0 to SlaveSprCount-1 do и откуда берётся.
← →
NailMan (2003-08-14 10:29) [3]Что такое TGameSprite?
TYPE
TGameSprite = CLASS
Private
SpriteType : integer; //Тип спрайта. Влияет только на флаг D3DPT_ при рендере
Public
Fmat : TD3DMatrix; //матрица трансформаций
FPOS : TD3DVector; //Позиция в мире
POSZ : TD3DVector; //Смещение относительно актера(когда он в нуле)
FSize : TD3DVector; //масштаб(Z=1)
TexName : String; //ну это поятно
Enabled : Boolean; //----//---
TextureIndex : Dword; //Индекс текстуры в общем массиве
Color : TD3DCOLOR; //цвет модуляции
Constructor Create(Const FileName:String;SprType:Integer);
Procedure Render;
Procedure MoveTo; //для билбоардинга берется глобальная матрица вида(при передв-ии камеры, она копирует туда свою матрицу)
Procedure SetPos(const v: TD3DVector); //установить спрайт в нужную позицию
END;
extractcoords(n); как работает?
Function ExtractCoords(var n:string):Td3dvector;
begin
delete(n,1,pos("(",n));
result.x:=strtofloat(copy(n,1,pos(",",n)-1)); delete(n,1,pos(",",n));
result.y:=strtofloat(copy(n,1,pos(",",n)-1)); delete(n,1,pos(",",n));
result.z:=strtofloat(copy(n,1,pos(")",n)-1));
delete(n,1,pos(")",n));
end;
Функция вырезает скобку координат из общей строки, выдает вектор, вырезает эту скобку и выдает строку обратно для дальнейших манипуляций.
Почему 2 раза одно и тоже к разным переменным делаешь?
v:=extractcoords(n);
s:=extractcoords(n);
Ну как я и говорил в одной строке несколько скобок с разными данными(порядок параметров в строки всегда постоянный)
Вместо этого
For i:=0 to Count-1 do
Лучше делать
For i:=1 to Count do затем использовать индекс I-1
Например если коунт будет равен нулю, то цикл будет выполняться, и может возникнуть ошибка, во втором случае цикл исполняться не будет.
Ж-) По моему в первом случае при count=0 цикл вообще не выполнится, даже ошибки не получится.
Неизвестно что такое For i:=0 to SlaveSprCount-1 do и откуда берётся.
Ну я же во втором постинге добавил где получается SlaveSprCount. Это количество подчиненных актеру спрайтов. индексы спрайтов хранятся в актере в массиве интегеров SlaveSpr.
← →
Sapersky (2003-08-14 13:54) [4]Spr[SlaveObj[i]].SetPos(tempvec)
Возможно, здесь должно быть Spr[ SlaveSpr[i]].SetPos(tempvec) ?
Вместо этого
For i:=0 to Count-1 do
Лучше делать
For i:=1 to Count doзатем использовать индекс I-1
Например если коунт будет равен нулю, то цикл будет выполняться, и может возникнуть ошибка, во втором случае цикл исполняться не будет.
Никакой ошибки не будет, будет цикл от 0 до -1, т.е. ни разу, что и требуется. Единственное, что меня здесь волнует - соображает ли компилятор заранее вычесть единицу или делает это на каждой итерации (в случае использования индекса i-1 наверняка приходится вычитать на каждой... хотя не знаю... компиляторы нынче умные пошли).
← →
NailMan (2003-08-14 15:32) [5]To -> Sapersky ©
Блин точно! А я тут колупаюсь и не догоняю в чем дело. Даже супер подробный лог прикрутил.
Надо это в ветку о том как программисты тупят, что когда-то ходила в "Потрепаться".
ЗЫ: Уря, теперь дела продвинутся далеко, так как долелал таки я свой
ListBox в GUI и консоль. Завтра выложу на свой сайт демо-версию.
← →
cyborg (2003-08-14 22:53) [6]Никакой ошибки не будет, будет цикл от 0 до -1, т.е. ни разу, что и требуется.
И правда :о), я раньше наткнулся на проблему выхода за границы, поэтому теперь делаю так, как сказал. В данном случае этот совет можно не слушать ;о)
Страницы: 1 вся ветка
Форум: "Игры";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.032 c