diff -r ae2950c5465c -r 0e27949850e3 hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Sun Jan 15 23:56:47 2006 +0000 +++ b/hedgewars/uCollisions.pas Thu Jan 19 21:12:20 2006 +0000 @@ -35,98 +35,93 @@ interface uses uGears; {$INCLUDE options.inc} +const cMaxGearArrayInd = 255; -type TCollisionEntry = record - X, Y, HWidth, HHeight: integer; - cGear: PGear; - end; +type TDirection = record + dX, dY: integer + end; + PGearArray = ^TGearArray; + TGearArray = record + ar: array[0..cMaxGearArrayInd] of PGear; + Count: Longword + end; -procedure AddGearCR(Gear: PGear); -procedure UpdateCR(NewX, NewY: integer; Index: Longword); -procedure DeleteCR(Gear: PGear); -function CheckGearsCollision(Gear: PGear; Dir: integer; forX: boolean): PGear; +procedure FillRoundInLand(X, Y, Radius: integer; Value: Longword); +procedure AddGearCI(Gear: PGear); +procedure DeleteCI(Gear: PGear); +function CheckGearsCollision(Gear: PGear): PGearArray; function HHTestCollisionYwithGear(Gear: PGear; Dir: integer): boolean; function TestCollisionXwithGear(Gear: PGear; Dir: integer): boolean; function TestCollisionYwithGear(Gear: PGear; Dir: integer): boolean; function TestCollisionXwithXYShift(Gear: PGear; ShiftX, ShiftY: integer; Dir: integer): boolean; function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: integer; Dir: integer): boolean; -function TestCollisionY(Gear: PGear; Dir: integer): boolean; implementation uses uMisc, uConsts, uLand; +type TCollisionEntry = record + X, Y, Radius: integer; + cGear: PGear; + end; + const MAXRECTSINDEX = 255; var Count: Longword = 0; - crects: array[0..MAXRECTSINDEX] of TCollisionEntry; + cinfos: array[0..MAXRECTSINDEX] of TCollisionEntry; + ga: TGearArray; -procedure AddGearCR(Gear: PGear); +procedure FillRoundInLand(X, Y, Radius: integer; Value: Longword); +var ty, tx: integer; begin +for ty:= max(-Radius, -y) to min(radius, 1023 - y) do + for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047,round(x+radius*sqrt(1-sqr(ty/radius)))) do + Land[ty + y, tx]:= Value; +end; + +procedure AddGearCI(Gear: PGear); +begin +if Gear.CollIndex < High(Longword) then exit; TryDo(Count <= MAXRECTSINDEX, 'Collision rects array overflow', true); -with crects[Count] do +with cinfos[Count] do begin X:= round(Gear.X); Y:= round(Gear.Y); - HWidth:= Gear.HalfWidth; - HHeight:= Gear.HalfHeight; + Radius:= Gear.Radius; + FillRoundInLand(X, Y, Radius, $FF); cGear:= Gear end; Gear.CollIndex:= Count; inc(Count) end; -procedure UpdateCR(NewX, NewY: integer; Index: Longword); +procedure DeleteCI(Gear: PGear); begin -with crects[Index] do - begin - X:= NewX; - Y:= NewY - end +if Gear.CollIndex < Count then + begin + with cinfos[Gear.CollIndex] do FillRoundInLand(X, Y, Radius, 0); + cinfos[Gear.CollIndex]:= cinfos[Pred(Count)]; + cinfos[Gear.CollIndex].cGear.CollIndex:= Gear.CollIndex; + Gear.CollIndex:= High(Longword); + dec(Count) + end; end; -procedure DeleteCR(Gear: PGear); -begin -if Gear.CollIndex < Pred(Count) then - begin - crects[Gear.CollIndex]:= crects[Pred(Count)]; - crects[Gear.CollIndex].cGear.CollIndex:= Gear.CollIndex - end; -Gear.CollIndex:= High(Longword); -dec(Count) -end; - -function CheckGearsCollision(Gear: PGear; Dir: integer; forX: boolean): PGear; -var x1, x2, y1, y2: integer; +function CheckGearsCollision(Gear: PGear): PGearArray; +var mx, my: integer; i: Longword; begin -Result:= nil; +Result:= @ga; +ga.Count:= 0; if Count = 0 then exit; -x1:= round(Gear.X); -y1:= round(Gear.Y); - -if forX then - begin - x1:= x1 + Dir*Gear.HalfWidth; - x2:= x1; - y2:= y1 + Gear.HalfHeight - 1; - y1:= y1 - Gear.HalfHeight + 1 - end else - begin - y1:= y1 + Dir*Gear.HalfHeight; - y2:= y1; - x2:= x1 + Gear.HalfWidth - 1; - x1:= x1 - Gear.HalfWidth + 1 - end; +mx:= round(Gear.X); +my:= round(Gear.Y); for i:= 0 to Pred(Count) do - with crects[i] do - if (Gear.CollIndex <> i) - and (x1 <= X + HWidth) - and (x2 >= X - HWidth) - and (y1 <= Y + HHeight) - and (y2 >= Y - HHeight) then + with cinfos[i] do + if (Gear <> cGear) and + (sqrt(sqr(mx - x) + sqr(my - y)) <= Radius + Gear.Radius) then begin - Result:= crects[i].cGear; - exit + ga.ar[ga.Count]:= cinfos[i].cGear; + inc(ga.Count) end; end; @@ -135,14 +130,14 @@ begin Result:= false; y:= round(Gear.Y); -if Dir < 0 then y:= y - Gear.HalfHeight - else y:= y + Gear.HalfHeight; +if Dir < 0 then y:= y - Gear.Radius + else y:= y + Gear.Radius; if ((y - Dir) and $FFFFFC00) = 0 then begin x:= round(Gear.X); - if (((x - Gear.HalfWidth) and $FFFFF800) = 0)and(Land[y - Dir, x - Gear.HalfWidth] <> 0) - or(((x + Gear.HalfWidth) and $FFFFF800) = 0)and(Land[y - Dir, x + Gear.HalfWidth] <> 0) then + if (((x - Gear.Radius) and $FFFFF800) = 0)and(Land[y - Dir, x - Gear.Radius] <> 0) + or(((x + Gear.Radius) and $FFFFF800) = 0)and(Land[y - Dir, x + Gear.Radius] <> 0) then begin Result:= true; exit @@ -151,15 +146,12 @@ if (y and $FFFFFC00) = 0 then begin - x:= round(Gear.X) - Gear.HalfWidth + 1; - i:= x + Gear.HalfWidth * 2 - 2; + x:= round(Gear.X) - Gear.Radius + 1; + i:= x + Gear.Radius * 2 - 2; repeat if (x and $FFFFF800) = 0 then Result:= Land[y, x]<>0; inc(x) - until (x > i) or Result; - if Result then exit; - - Result:= CheckGearsCollision(Gear, Dir, false) <> nil + until (x > i) or Result end end; @@ -168,18 +160,16 @@ begin Result:= false; x:= round(Gear.X); -if Dir < 0 then x:= x - Gear.HalfWidth - else x:= x + Gear.HalfWidth; +if Dir < 0 then x:= x - Gear.Radius + else x:= x + Gear.Radius; if (x and $FFFFF800) = 0 then begin - y:= round(Gear.Y) - Gear.HalfHeight + 1; {*} - i:= y + Gear.HalfHeight * 2 - 2; {*} + y:= round(Gear.Y) - Gear.Radius + 1; {*} + i:= y + Gear.Radius * 2 - 2; {*} repeat if (y and $FFFFFC00) = 0 then Result:= Land[y, x]<>0; inc(y) until (y > i) or Result; - if Result then exit; - Result:= CheckGearsCollision(Gear, Dir, true) <> nil end end; @@ -197,32 +187,12 @@ begin Result:= false; y:= round(Gear.Y); -if Dir < 0 then y:= y - Gear.HalfHeight - else y:= y + Gear.HalfHeight; +if Dir < 0 then y:= y - Gear.Radius + else y:= y + Gear.Radius; if (y and $FFFFFC00) = 0 then begin - x:= round(Gear.X) - Gear.HalfWidth + 1; {*} - i:= x + Gear.HalfWidth * 2 - 2; {*} - repeat - if (x and $FFFFF800) = 0 then Result:= Land[y, x]<>0; - inc(x) - until (x > i) or Result; - if Result then exit; - Result:= CheckGearsCollision(Gear, Dir, false) <> nil; - end -end; - -function TestCollisionY(Gear: PGear; Dir: integer): boolean; -var x, y, i: integer; -begin -Result:= false; -y:= round(Gear.Y); -if Dir < 0 then y:= y - Gear.HalfHeight - else y:= y + Gear.HalfHeight; -if (y and $FFFFFC00) = 0 then - begin - x:= round(Gear.X) - Gear.HalfWidth + 1; {*} - i:= x + Gear.HalfWidth * 2 - 2; {*} + x:= round(Gear.X) - Gear.Radius + 1; {*} + i:= x + Gear.Radius * 2 - 2; {*} repeat if (x and $FFFFF800) = 0 then Result:= Land[y, x]<>0; inc(x)