# HG changeset patch # User alfadur # Date 1558633061 -10800 # Node ID a315927a44b2c595da6c96d4a804be52bcbe8fa9 # Parent 981f16edea0214e2fb457abadf9d80447582c3e8 improve rope rendering diff -r 981f16edea02 -r a315927a44b2 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Thu May 23 13:41:14 2019 +0200 +++ b/hedgewars/uGearsRender.pas Thu May 23 20:37:41 2019 +0300 @@ -95,102 +95,64 @@ end; -function DrawRopeLine(X1, Y1, X2, Y2, roplen: LongInt; LayerIndex: Longword): LongInt; -var eX, eY, dX, dY: LongInt; - i, sX, sY, x, y, d: LongInt; - b: boolean; - angle: real; +procedure DrawRopeLine(X1, Y1, X2, Y2: Real; LayerIndex: Longword; var linesLength, ropeLength: Real); +var dX, dY, angle, length: Real; + FrameIndex: LongWord; begin if (X1 = X2) and (Y1 = Y2) then - begin - //OutError('WARNING: zero length rope line!', false); - DrawRopeLine:= 0; - exit - end; - eX:= 0; - eY:= 0; + exit; + dX:= X2 - X1; dY:= Y2 - Y1; + length:= sqrt(sqr(dX) + sqr(dY)); angle:= arctan2(dY, dX) * 180 / PI - 90; - if (dX > 0) then - sX:= 1 - else - if (dX < 0) then - begin - sX:= -1; - dX:= -dX - end - else sX:= dX; - - if (dY > 0) then - sY:= 1 - else - if (dY < 0) then - begin - sY:= -1; - dY:= -dY - end - else - sY:= dY; - - if (dX > dY) then - d:= dX - else - d:= dY; + dX:= dX / length; + dY:= dY / length; - x:= X1; - y:= Y1; - - for i:= 0 to d do - begin - inc(eX, dX); - inc(eY, dY); - b:= false; - if (eX > d) then - begin - dec(eX, d); - inc(x, sX); - b:= true - end; - if (eY > d) then - begin - dec(eY, d); - inc(y, sY); - b:= true - end; - if b then - begin - inc(roplen); - if (roplen mod (cRopeNodeStep * cRopeLayers)) = (cRopeNodeStep * LayerIndex) then - DrawSpriteRotatedF(sprRopeNode, x, y, roplen div cRopeNodeStep, 1, angle); - end + while (ropeLength - linesLength) <= length do + begin + FrameIndex:= round(ropeLength / cRopeNodeStep); + if (FrameIndex mod cRopeLayers) = LayerIndex then + DrawSpriteRotatedFReal(sprRopeNode, + X1 + (ropeLength - linesLength) * dX, + Y1 + (ropeLength - linesLength) * dY, + FrameIndex, 1, angle); + ropeLength:= ropeLength + cRopeNodeStep; end; - DrawRopeLine:= roplen; + linesLength:= linesLength + length end; procedure DrawRopeLayer(Gear: PGear; LayerIndex: LongWord); -var roplen, i: LongInt; +var i: LongInt; + linesLength, ropeLength: Real; begin - roplen:= 0; + linesLength:= 0; + ropeLength:= cRopeNodeStep; if RopePoints.Count > 0 then begin i:= 0; while i < Pred(RopePoints.Count) do begin - roplen:= DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy, - hwRound(RopePoints.ar[Succ(i)].X) + WorldDx, hwRound(RopePoints.ar[Succ(i)].Y) + WorldDy, roplen, LayerIndex); + DrawRopeLine(hwFloat2Float(RopePoints.ar[i].X) + WorldDx, hwFloat2Float(RopePoints.ar[i].Y) + WorldDy, + hwFloat2Float(RopePoints.ar[Succ(i)].X) + WorldDx, hwFloat2Float(RopePoints.ar[Succ(i)].Y) + WorldDy, + LayerIndex, linesLength, ropeLength); inc(i) end; - roplen:= DrawRopeLine(hwRound(RopePoints.ar[i].X) + WorldDx, hwRound(RopePoints.ar[i].Y) + WorldDy, - hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, roplen, LayerIndex); - roplen:= DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, - hwRound(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwRound(Gear^.Hedgehog^.Gear^.Y) + WorldDy, roplen, LayerIndex); + + DrawRopeLine(hwFloat2Float(RopePoints.ar[i].X) + WorldDx, hwFloat2Float(RopePoints.ar[i].Y) + WorldDy, + hwFloat2Float(Gear^.X) + WorldDx, hwFloat2Float(Gear^.Y) + WorldDy, + LayerIndex, linesLength, ropeLength); + + DrawRopeLine(hwFloat2Float(Gear^.X) + WorldDx, hwFloat2Float(Gear^.Y) + WorldDy, + hwFloat2Float(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) + WorldDy, + LayerIndex, linesLength, ropeLength); end else if Gear^.Elasticity.QWordValue > 0 then - roplen:= DrawRopeLine(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, - hwRound(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwRound(Gear^.Hedgehog^.Gear^.Y) + WorldDy, roplen, LayerIndex); + DrawRopeLine(hwFloat2Float(Gear^.X) + WorldDx, hwFloat2Float(Gear^.Y) + WorldDy, + hwFloat2Float(Gear^.Hedgehog^.Gear^.X) + WorldDx, hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) + WorldDy, + LayerIndex, linesLength, ropeLength); end; procedure DrawRope(Gear: PGear); diff -r 981f16edea02 -r a315927a44b2 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Thu May 23 13:41:14 2019 +0200 +++ b/hedgewars/uRender.pas Thu May 23 20:37:41 2019 +0300 @@ -34,6 +34,7 @@ procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); procedure DrawSpriteRotatedF (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); +procedure DrawSpriteRotatedFReal(Sprite: TSprite; X, Y: Real; Frame, Dir: LongInt; Angle: real); procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real); procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline; @@ -1152,7 +1153,7 @@ if Angle <> 0 then begin - // Check the bounding circle + // Check the bounding circle if isCircleOffscreen(X, Y, (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then exit; end @@ -1186,6 +1187,45 @@ end; +procedure DrawSpriteRotatedFReal(Sprite: TSprite; X, Y: Real; Frame, Dir: LongInt; Angle: real); +begin + + if Angle <> 0 then + begin + // Check the bounding circle + if isCircleOffscreen(round(X), round(Y), (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then + exit; + end + else + begin + if isDxAreaOffscreen(round(X) - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then + exit; + if isDYAreaOffscreen(round(Y) - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then + exit; + end; + + + openglPushMatrix; + openglTranslatef(X, Y, 0); + +// mirror + if Dir < 0 then + openglScalef(-1.0, 1.0, 1.0); + +// apply angle after (conditional) mirroring + if Angle <> 0 then + openglRotatef(Angle, 0, 0, 1); + + UpdateModelviewProjection; + + DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); + + openglPopMatrix; + + UpdateModelviewProjection; + +end; + procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real); begin if Angle <> 0 then