32 procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); |
32 procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); |
33 procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline; |
33 procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline; |
34 procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); |
34 procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); |
35 procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); |
35 procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); |
36 procedure DrawSpriteRotatedF (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
36 procedure DrawSpriteRotatedF (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
|
37 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real); |
37 |
38 |
38 procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline; |
39 procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline; |
39 procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat); |
40 procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat); |
40 procedure DrawTexture2 (X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat); |
41 procedure DrawTexture2 (X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat); |
41 procedure DrawTextureFromRect (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; |
42 procedure DrawTextureFromRect (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; |
71 |
72 |
72 // call this to finish the rendering of current frame |
73 // call this to finish the rendering of current frame |
73 procedure FinishRender(); |
74 procedure FinishRender(); |
74 |
75 |
75 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; |
76 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; |
|
77 function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline; |
76 |
78 |
77 // 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen |
79 // 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen |
78 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; |
80 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; |
79 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline; |
81 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline; |
80 |
82 |
101 procedure openglPopMatrix (); inline; |
103 procedure openglPopMatrix (); inline; |
102 procedure openglTranslatef (X, Y, Z: GLfloat); inline; |
104 procedure openglTranslatef (X, Y, Z: GLfloat); inline; |
103 |
105 |
104 |
106 |
105 implementation |
107 implementation |
106 uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils, uConsts |
108 uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils |
107 {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uPhysFSLayer, uDebug; |
109 {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uConsts; |
108 |
110 |
109 {$IFDEF USE_TOUCH_INTERFACE} |
111 {$IFDEF USE_TOUCH_INTERFACE} |
110 const |
112 const |
111 FADE_ANIM_TIME = 500; |
113 FADE_ANIM_TIME = 500; |
112 MOVE_ANIM_TIME = 500; |
114 MOVE_ANIM_TIME = 500; |
143 {$ENDIF} |
145 {$ENDIF} |
144 |
146 |
145 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; |
147 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; |
146 begin |
148 begin |
147 isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0); |
149 isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0); |
|
150 end; |
|
151 |
|
152 function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline; |
|
153 var dRightX, dBottomY, dLeftX, dTopY: LongInt; |
|
154 begin |
|
155 dRightX:= (X - ViewRightX); |
|
156 dBottomY:= (Y - ViewBottomY); |
|
157 dLeftX:= (ViewLeftX - X); |
|
158 dTopY:= (ViewTopY - Y); |
|
159 isCircleOffscreen:= |
|
160 ((dRightX > 0) and (sqr(dRightX) > RadiusSquared)) or |
|
161 ((dBottomY > 0) and (sqr(dBottomY) > RadiusSquared)) or |
|
162 ((dLeftX > 0) and (sqr(dLeftX) > RadiusSquared)) or |
|
163 ((dTopY > 0) and (sqr(dTopY) > RadiusSquared)) |
148 end; |
164 end; |
149 |
165 |
150 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; |
166 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; |
151 begin |
167 begin |
152 if X > ViewRightX then exit(1); |
168 if X > ViewRightX then exit(1); |
1129 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
1145 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
1130 begin |
1146 begin |
1131 |
1147 |
1132 if Angle <> 0 then |
1148 if Angle <> 0 then |
1133 begin |
1149 begin |
1134 // sized doubled because the sprite might occupy up to 1.4 * of it's |
1150 // Check the bounding circle |
1135 // original size in each dimension, because it is rotated |
1151 if isCircleOffscreen(X, Y, sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) then |
1136 if isDxAreaOffscreen(X - SpritesData[Sprite].Width, 2 * SpritesData[Sprite].Width) <> 0 then |
|
1137 exit; |
|
1138 if isDYAreaOffscreen(Y - SpritesData[Sprite].Height, 2 * SpritesData[Sprite].Height) <> 0 then |
|
1139 exit; |
1152 exit; |
1140 end |
1153 end |
1141 else |
1154 else |
1142 begin |
1155 begin |
1143 if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then |
1156 if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then |
1160 |
1173 |
1161 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); |
1174 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); |
1162 |
1175 |
1163 openglPopMatrix; |
1176 openglPopMatrix; |
1164 |
1177 |
|
1178 end; |
|
1179 |
|
1180 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real); |
|
1181 begin |
|
1182 if Angle <> 0 then |
|
1183 begin |
|
1184 // Check the bounding circle |
|
1185 // Assuming the pivot point is inside the sprite's rectangle, the farthest possible point is 3/2 of its diagonal away from the center |
|
1186 if isCircleOffscreen(X, Y, 9 * (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then |
|
1187 exit; |
|
1188 end |
|
1189 else |
|
1190 begin |
|
1191 if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then |
|
1192 exit; |
|
1193 if isDYAreaOffscreen(Y - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then |
|
1194 exit; |
|
1195 end; |
|
1196 |
|
1197 openglPushMatrix; |
|
1198 openglTranslatef(X, Y, 0); |
|
1199 |
|
1200 // mirror |
|
1201 if Dir < 0 then |
|
1202 openglScalef(-1.0, 1.0, 1.0); |
|
1203 |
|
1204 // apply rotation around the pivot after (conditional) mirroring |
|
1205 if Angle <> 0 then |
|
1206 begin |
|
1207 openglTranslatef(PivotX, PivotY, 0); |
|
1208 openglRotatef(Angle, 0, 0, 1); |
|
1209 openglTranslatef(-PivotX, -PivotY, 0); |
|
1210 end; |
|
1211 |
|
1212 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); |
|
1213 |
|
1214 openglPopMatrix; |
1165 end; |
1215 end; |
1166 |
1216 |
1167 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); |
1217 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); |
1168 begin |
1218 begin |
1169 |
1219 |
1731 glColor4ub($FF, $FF, $FF, $FF); |
1781 glColor4ub($FF, $FF, $FF, $FF); |
1732 {$ENDIF} |
1782 {$ENDIF} |
1733 end; |
1783 end; |
1734 |
1784 |
1735 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte); |
1785 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte); |
1736 var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt; |
1786 var first, count, topy, lx, rx, spriteHeight, spriteWidth, waterSpeed: LongInt; |
1737 lw, nWaves, shift: GLfloat; |
1787 waterFrames, waterFrameTicks, frame : LongWord; |
|
1788 lw, nWaves, shift, realHeight: GLfloat; |
1738 sprite: TSprite; |
1789 sprite: TSprite; |
1739 begin |
1790 begin |
1740 // note: spriteHeight is the Height of the wave sprite while |
1791 // note: spriteHeight is the Height of the wave sprite while |
1741 // cWaveHeight describes how many pixels of it will be above waterline |
1792 // cWaveHeight describes how many pixels of it will be above waterline |
1742 |
1793 |
1743 if SuddenDeathDmg then |
1794 if SuddenDeathDmg then |
1744 sprite:= sprSDWater |
1795 begin |
|
1796 sprite:= sprSDWater; |
|
1797 waterFrames:= watSDFrames; |
|
1798 waterFrameTicks:= watSDFrameTicks; |
|
1799 waterSpeed:= watSDMove; |
|
1800 end |
1745 else |
1801 else |
|
1802 begin |
1746 sprite:= sprWater; |
1803 sprite:= sprWater; |
1747 |
1804 waterFrames:= watFrames; |
|
1805 waterFrameTicks:= watFrameTicks; |
|
1806 waterSpeed:= watMove; |
|
1807 end; |
|
1808 |
1748 spriteHeight:= SpritesData[sprite].Height; |
1809 spriteHeight:= SpritesData[sprite].Height; |
|
1810 realHeight:= SpritesData[sprite].Texture^.ry / waterFrames; |
1749 |
1811 |
1750 // shift parameters by wave height |
1812 // shift parameters by wave height |
1751 // ( ox and dy are used to create different horizontal and vertical offsets |
1813 // ( ox and dy are used to create different horizontal and vertical offsets |
1752 // between wave layers ) |
1814 // between wave layers ) |
1753 dY:= -cWaveHeight + dy; |
1815 dY:= -cWaveHeight + dy; |
1804 |
1866 |
1805 spriteWidth:= SpritesData[sprite].Width; |
1867 spriteWidth:= SpritesData[sprite].Width; |
1806 nWaves:= lw / spriteWidth; |
1868 nWaves:= lw / spriteWidth; |
1807 shift:= - nWaves / 2; |
1869 shift:= - nWaves / 2; |
1808 |
1870 |
1809 TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1); |
1871 if waterFrames > 1 then |
1810 TextureBuffer[3].Y:= 0; |
1872 frame:= RealTicks div waterFrameTicks mod waterFrames |
|
1873 else |
|
1874 frame:= 0; |
|
1875 |
|
1876 TextureBuffer[3].X:= shift + ((LongInt((RealTicks * waterSpeed div 100) shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1); |
|
1877 TextureBuffer[3].Y:= frame * realHeight; |
1811 TextureBuffer[5].X:= TextureBuffer[3].X + nWaves; |
1878 TextureBuffer[5].X:= TextureBuffer[3].X + nWaves; |
1812 TextureBuffer[5].Y:= 0; |
1879 TextureBuffer[5].Y:= frame * realHeight; |
1813 TextureBuffer[4].X:= TextureBuffer[5].X; |
1880 TextureBuffer[4].X:= TextureBuffer[5].X; |
1814 TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry; |
1881 TextureBuffer[4].Y:= (frame+1) * realHeight; |
1815 TextureBuffer[2].X:= TextureBuffer[3].X; |
1882 TextureBuffer[2].X:= TextureBuffer[3].X; |
1816 TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry; |
1883 TextureBuffer[2].Y:= (frame+1) * realHeight; |
1817 |
1884 |
1818 if (WorldEdge = weSea) then |
1885 if (WorldEdge = weSea) then |
1819 begin |
1886 begin |
1820 nWaves:= (topy - ViewTopY) / spriteWidth; |
1887 nWaves:= (topy - ViewTopY) / spriteWidth; |
1821 |
1888 |
1822 // left side |
1889 // left side |
1823 TextureBuffer[1].X:= TextureBuffer[3].X - nWaves; |
1890 TextureBuffer[1].X:= TextureBuffer[3].X - nWaves; |
1824 TextureBuffer[1].Y:= 0; |
1891 TextureBuffer[1].Y:= frame * realHeight; |
1825 TextureBuffer[0].X:= TextureBuffer[1].X; |
1892 TextureBuffer[0].X:= TextureBuffer[1].X; |
1826 TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry; |
1893 TextureBuffer[0].Y:= (frame+1) * realHeight; |
1827 |
1894 |
1828 // right side |
1895 // right side |
1829 TextureBuffer[7].X:= TextureBuffer[5].X + nWaves; |
1896 TextureBuffer[7].X:= TextureBuffer[5].X + nWaves; |
1830 TextureBuffer[7].Y:= 0; |
1897 TextureBuffer[7].Y:= frame * realHeight; |
1831 TextureBuffer[6].X:= TextureBuffer[7].X; |
1898 TextureBuffer[6].X:= TextureBuffer[7].X; |
1832 TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry; |
1899 TextureBuffer[6].Y:= (frame+1) * realHeight; |
1833 end; |
1900 end; |
1834 |
1901 |
1835 glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id); |
1902 glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id); |
1836 |
1903 |
1837 SetVertexPointer(@VertexBuffer[0], 8); |
1904 SetVertexPointer(@VertexBuffer[0], 8); |