--- a/hedgewars/uRender.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uRender.pas Sun Dec 17 00:09:24 2017 +0100
@@ -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 DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline;
procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
@@ -73,6 +74,7 @@
procedure FinishRender();
function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
+function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
// 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen
function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
@@ -103,8 +105,8 @@
implementation
-uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils, uConsts
- {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uPhysFSLayer, uDebug;
+uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils
+ {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uConsts;
{$IFDEF USE_TOUCH_INTERFACE}
const
@@ -147,6 +149,20 @@
isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
end;
+function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
+var dRightX, dBottomY, dLeftX, dTopY: LongInt;
+begin
+ dRightX:= (X - ViewRightX);
+ dBottomY:= (Y - ViewBottomY);
+ dLeftX:= (ViewLeftX - X);
+ dTopY:= (ViewTopY - Y);
+ isCircleOffscreen:=
+ ((dRightX > 0) and (sqr(dRightX) > RadiusSquared)) or
+ ((dBottomY > 0) and (sqr(dBottomY) > RadiusSquared)) or
+ ((dLeftX > 0) and (sqr(dLeftX) > RadiusSquared)) or
+ ((dTopY > 0) and (sqr(dTopY) > RadiusSquared))
+end;
+
function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
begin
if X > ViewRightX then exit(1);
@@ -1131,11 +1147,8 @@
if Angle <> 0 then
begin
- // sized doubled because the sprite might occupy up to 1.4 * of it's
- // original size in each dimension, because it is rotated
- if isDxAreaOffscreen(X - SpritesData[Sprite].Width, 2 * SpritesData[Sprite].Width) <> 0 then
- exit;
- if isDYAreaOffscreen(Y - SpritesData[Sprite].Height, 2 * SpritesData[Sprite].Height) <> 0 then
+ // Check the bounding circle
+ if isCircleOffscreen(X, Y, sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) then
exit;
end
else
@@ -1164,6 +1177,43 @@
end;
+procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
+begin
+if Angle <> 0 then
+ begin
+ // Check the bounding circle
+ // Assuming the pivot point is inside the sprite's rectangle, the farthest possible point is 3/2 of its diagonal away from the center
+ if isCircleOffscreen(X, Y, 9 * (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then
+ exit;
+ end
+else
+ begin
+ if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
+ exit;
+ if isDYAreaOffscreen(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 rotation around the pivot after (conditional) mirroring
+if Angle <> 0 then
+ begin
+ openglTranslatef(PivotX, PivotY, 0);
+ openglRotatef(Angle, 0, 0, 1);
+ openglTranslatef(-PivotX, -PivotY, 0);
+ end;
+
+DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
+
+openglPopMatrix;
+end;
+
procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
begin
@@ -1733,19 +1783,31 @@
end;
procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
-var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt;
- lw, nWaves, shift: GLfloat;
+var first, count, topy, lx, rx, spriteHeight, spriteWidth, waterSpeed: LongInt;
+ waterFrames, waterFrameTicks, frame : LongWord;
+ lw, nWaves, shift, realHeight: GLfloat;
sprite: TSprite;
begin
// note: spriteHeight is the Height of the wave sprite while
// cWaveHeight describes how many pixels of it will be above waterline
if SuddenDeathDmg then
- sprite:= sprSDWater
+ begin
+ sprite:= sprSDWater;
+ waterFrames:= watSDFrames;
+ waterFrameTicks:= watSDFrameTicks;
+ waterSpeed:= watSDMove;
+ end
else
+ begin
sprite:= sprWater;
-
+ waterFrames:= watFrames;
+ waterFrameTicks:= watFrameTicks;
+ waterSpeed:= watMove;
+ end;
+
spriteHeight:= SpritesData[sprite].Height;
+realHeight:= SpritesData[sprite].Texture^.ry / waterFrames;
// shift parameters by wave height
// ( ox and dy are used to create different horizontal and vertical offsets
@@ -1806,14 +1868,19 @@
nWaves:= lw / spriteWidth;
shift:= - nWaves / 2;
-TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
-TextureBuffer[3].Y:= 0;
+if waterFrames > 1 then
+ frame:= RealTicks div waterFrameTicks mod waterFrames
+else
+ frame:= 0;
+
+TextureBuffer[3].X:= shift + ((LongInt((RealTicks * waterSpeed div 100) shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
+TextureBuffer[3].Y:= frame * realHeight;
TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
-TextureBuffer[5].Y:= 0;
+TextureBuffer[5].Y:= frame * realHeight;
TextureBuffer[4].X:= TextureBuffer[5].X;
-TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
+TextureBuffer[4].Y:= (frame+1) * realHeight;
TextureBuffer[2].X:= TextureBuffer[3].X;
-TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
+TextureBuffer[2].Y:= (frame+1) * realHeight;
if (WorldEdge = weSea) then
begin
@@ -1821,15 +1888,15 @@
// left side
TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
- TextureBuffer[1].Y:= 0;
+ TextureBuffer[1].Y:= frame * realHeight;
TextureBuffer[0].X:= TextureBuffer[1].X;
- TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
+ TextureBuffer[0].Y:= (frame+1) * realHeight;
// right side
TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
- TextureBuffer[7].Y:= 0;
+ TextureBuffer[7].Y:= frame * realHeight;
TextureBuffer[6].X:= TextureBuffer[7].X;
- TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
+ TextureBuffer[6].Y:= (frame+1) * realHeight;
end;
glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);