Функцией Add устанавливаю значение переменной p в структуру с индексом 0, ВНЕЗАПНО это значение устанавливается всем переменным p во всём массиве структур. Что не так?
p.s. Темку переместите, а то промахнулся чуток)
Мир, как зеркало, отражает ваше отношение к нему. Когда боретесь с миром, он борется с вами. Когда прекращаете свою битву, мир идет навстречу.(В.Зеланд) vk.com/zonnery
Сообщение отредактировал Zonnery - Четверг, 20 Июня 2013, 01:38:11
Zonnery, зачем именно нужна структура наследующий массив? раз так то почему бы не сделать переменную p статической? или расписать метод create уже внутри структуры с переменной p и создавать ее через allocate?
Nic nie wiem bo mam chuj. редактирую посты! ВСЕ!
Сообщение отредактировал lawson - Четверг, 20 Июня 2013, 10:37:31
В общем, нужен был способ реализации одной фишки. А именно простой системки движения, основанной на самоочищающихся триггерах(вместо ресурсоёмкого picked unit, для каждого объекта создаётся триггер, который после разрушения объекта уничтожается на столько, на сколько это возможно, где-то около 16кб от объекта всё-таки утекает). Реализовал эту систему на массивах я просто. Создал библиотеку, в ней парочку функций. Одна создавала объект на основе физического тела, пихала его и его параметры в свободную ячейку парных массивов, запускала таймер-обработчик, проверял максимальный не пустой индекс в массиве для того, чтобы в таймере-обработчике цикл лишний раз не бегал(кстати, минус той системы был в том, что максимальный размер массива в варкрафте 8192, т.е. это лимит на кол-во объектов, его можно обойти при желании, но тем не менее). Вторая функция, как раз выполняла действия в таймере, т.е. двигала юнит, отключала таймер, если тело уничтожалось, или находилось в состоянии покоя. Всё работало перфекто и начинало подлагивать, лишь если одновременно обрабатывалось свыше 1к объектов.
private int maxArray = 0 private timer t = null private trigger array tr[8191] private triggeraction array tra[8191] private location l = null private real Abs(real r) { if r > 0. {return r} else {return -r} }
private real DistanceBLocs(real ax, real ay, real bx, real by) { return SquareRoot((bx - ax) * (bx - ax) + (by - ay) * (by - ay)) } private real DistanceBL3D(real ax, real ay, real az, real bx, real by, real bz) { return SquareRoot((bx - ax) * (bx - ax) + (by - ay) * (by - ay) + (bz - az) * (bz - az)) } private void DestroyTrig(int i){ uPath[i]=0 RemoveUnit(uLaser[i]) uLaser[i]=null uCaster[i]=null DisableTrigger(tr[i]) TriggerRemoveAction(tr[i],tra[i]) DestroyTrigger(tr[i]) tr[i]=null tra[i]=null } private void Do(){ int i = 0 int j = 0 while(i<=maxArray){ if(uLaser[i]!=null){ SetUnitX(uLaser[i],GetUnitX(uLaser[i])+Cos(bj_DEGTORAD*(GetUnitFacing(uLaser[i])+uRevers[i]))*speed) SetUnitY(uLaser[i],GetUnitY(uLaser[i])+Sin(bj_DEGTORAD*(GetUnitFacing(uLaser[i])+uRevers[i]))*speed) l=GetUnitLoc(uLaser[i]) SetUnitFlyHeight(uLaser[i],uZ[i]-GetLocationZ(l)+uZd[i],0) RemoveLocation(l) l=null
uPath[i]+=1 j++ if GetUnitFlyHeight(uLaser[i])<1 or(uPath[i]>maxPath)or(GetUnitX(uLaser[i])<=GetRectMinX(bj_mapInitialPlayableArea))or(GetUnitX(uLaser[i])>=GetRectMaxX(bj_mapInitialPlayableArea))or(GetUnitY(uLaser[i])<=GetRectMinY(bj_mapInitialPlayableArea))or(GetUnitY(uLaser[i])>=GetRectMaxY(bj_mapInitialPlayableArea)){ effect e = AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl",GetUnitX(uLaser[i]),GetUnitY(uLaser[i])) DestroyEffect(e) e=null DestroyTrig(i) } } i++ } if (j==0){ DestroyTimer(t) t=null } // BJDebugMsg("Снарядов: "+I2S(j)) }
private void Collision(){ int i = 0 while (tr[i]!=GetTriggeringTrigger()){ i++ }
if (Abs(GetUnitFlyHeight(GetEnteringUnit())-GetUnitFlyHeight(uLaser[i]))<300) and(GetEnteringUnit()!=uCaster[i])and(GetUnitTypeId(GetEnteringUnit()) != ID) and IsUnitEnemy(GetEnteringUnit(), GetOwningPlayer(uCaster[i])){ UnitDamageTarget(uCaster[i],GetEnteringUnit(),uDmg[i],true,true,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_LIGHTNING,WEAPON_TYPE_WHOKNOWS)
effect e = AddSpecialEffect("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl",GetUnitX(GetEnteringUnit()),GetUnitY(GetEnteringUnit())) DestroyEffect(e) e=null DestroyTrig(i) }
} void SystemMoveRun(unit u, float f, float dmg,float rangeofcol,int raw,unit u2){ int i = 0 while(uLaser[i]!=null){ //Находим индекс пустой ячейки для массива i++ } uCaster[i]=u
float a = GetUnitFacing(u) float x=GetUnitX(u)+(RangeOfCreation*Cos(a*bj_DEGTORAD)) float y=GetUnitY(u)+(RangeOfCreation*Sin(a*bj_DEGTORAD)) uLaser[i]=CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA),raw,x,y,a) SetUnitPathing(uLaser[i],true) SetUnitX(uLaser[i],x) SetUnitY(uLaser[i],y) UnitAddAbility( uLaser[i],'Amrf') SetUnitFlyHeight( uLaser[i], GetUnitFlyHeight(u)+f, 0.00 ) l = GetUnitLoc(uLaser[i]) uZ[i]=GetLocationZ(l)+GetUnitFlyHeight(uLaser[i]) if (u2!=null){ float uz=GetLocationZ(l) RemoveLocation(l) l=null l = GetUnitLoc(u2) float u1z=GetLocationZ(l) uZd[i]=DistanceBL3D(GetUnitX(uLaser[i]),GetUnitY(uLaser[i]),uz,GetUnitX(u2),GetUnitY(u2),u1z)-DistanceBLocs(GetUnitX(uLaser[i]),GetUnitY(uLaser[i]),GetUnitX(u2),GetUnitY(u2))
PauseUnit(uLaser[i],true) if (t==null){ t=CreateTimer() TimerStart(t,TimerPeriod,true,function Do) } if (i>maxArray){ maxArray=i }
i=0 if (maxArraySearch==true){ int j = 0 while(i<8191){ if(uLaser[i]!=null)and(j<i){ //Находим максимальный индекс непустого элемента j=i } i++ } maxArray=j //Найдя максимальный индекс непустого элемента, мы будем использовать его } //для нахождения максимального номера массива, который мы будем обрабатывать u=null
}
}
Код этот я где-то полгода назад писал, много лишнего, т.к. он уже был интегрирован в карту, и мне кое-что пришлось туда добавить) В игре всё работает нормально, но сам по себе код выглядит не ахти. Первое что стоит сделать, это заменить эти парные массивы на массив структур. Кроме того, можно сдвигать весь массив при уничтожении одного из элементов, дабы не существовало "дыр". Что ещё можно улучшить? Кстати говоря, хэш вообще не предлагать)
Мир, как зеркало, отражает ваше отношение к нему. Когда боретесь с миром, он борется с вами. Когда прекращаете свою битву, мир идет навстречу.(В.Зеланд) vk.com/zonnery
Сообщение отредактировал Zonnery - Пятница, 21 Июня 2013, 00:07:19
private real Abs(real r) { if r > 0. {return r} else {return -r} }
А чем RAbsBJ не угодила?)
Цитата (Zonnery)
Что ещё можно улучшить?
Использовать одну точку на весь код карты:
Код
library_once L { constant location L = Location(.0, .0); }
library SystemOfMoving requires L { //... MoveLocation(L, GetWidgetX(u), GetWidgetY(u)); real u1z = GetLocationZ(L); //... }
Я, кстати, использую еще и library_once G { constant group G = CreateGroup(); }
Цитата (Zonnery)
if (maxArraySearch==true)
static if maxArraySearch
Цитата (Zonnery)
effect e = AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl",GetUnitX(uLaser[i]),GetUnitY(uLaser[i])) DestroyEffect(e) e=null
DestroyEffect(AddSpecialEffect(EFFECT /* В константы */, GetUnitX(uLaser[i]), GetUnitY(uLaser[i]))); И AdicHelper последней версии сам обнуляет локальные переменные.
Цитата (Zonnery)
Код
int i = 0 while (tr[i]!=GetTriggeringTrigger()){ i++ }
Код
int i = 0; handle h = GetTriggeringTrigger(); whilenot h == tr[i] { i++; }
Поскольку этот код выполняется каждые .02 секунды, неплохо было бы (Cos|Sin)(bj_DEGTORAD*(GetUnitFacing(uLaser[i])+uRevers[i]))*speed просчитать во время запуска.
А это чтобы каждый раз не вычислять границы карты:
Код
library SafeMove { private real minX, minY, maxX, maxY;
void SafeMove(unit u, real x, real y) { if x > minX && x < maxX { SetUnitX(u, x); } if y > minY && y < maxY { SetUnitY(u, y); } }
bool IsInMap(widget w) { real x = GetWidgetX(w), y = GetWidgetY(w); return x > minX && x < maxX && y > minY && y < maxY; }
Ty3uK, человек знает, что нужно обнулять переменные и зачем это нужно. Автообнуление - это просто удобство, ведь больше ни в каких языках (я сейчас имею в виду известные) в сборщике мусора нет таких багов.
Добавлено (21 Июня 2013, 14:14:35) --------------------------------------------- Можно явно указывать flush locals.
т.е. Адольф и Скорп, которые всем трындят, что обнулять его нет смысла, неправы?
Цитата (ScorpioT1000)
Производные типы от handle Все остальные типы, которые являются производными от handle (unit, item, player, code и др. См. common.j) – точно такие же ссылки. Но логически поделены на подтипы, у каждого из которых своя область применения. Стоит упомянуть, что некоторые вобще не содержат никаких таблиц хендлов, например, тип player. В Starcraft 2 этот тип заменили на int.
Сообщение отредактировал Diabfall - Пятница, 21 Июня 2013, 20:16:30