Code:
unit SpriteSheet;
interface
uses w3ctrls, w3graphics, w3system;
type
TW3SpriteSheet = Class(TObject)
private
FImage : TW3Image;
FRows, FColumns : Integer;
FTotal : Integer;
FWidth, FHeight : Integer;
FHalfWidth, FHalfHeight : Integer;
FReady : Boolean;
FOnReady : TNotifyEvent;
procedure HandleImageReady(sender : TObject);
Procedure setWidth(aValue : Integer);
procedure setheight(aValue : Integer);
Procedure ReCalcInfo;
protected
class var vSinCosReady : Boolean;
class var vCosTable : array of Float;
class var vSinTable : array of Float;
class procedure InitSinCos;
public
Constructor Create;virtual;
destructor Destroy;Override;
procedure LoadImage(aUrl : String); overload;
procedure LoadImage(aUrl : String; aSpriteWidth, aSpriteHeight : Integer); overload;
// top left anchored
Procedure Draw(Canvas : TW3Canvas; dx,dy : Integer; FrameIndex : Integer); overload;
Procedure Draw(Canvas : TW3Canvas; dx,dy : Integer; FrameIndex : Integer;
rotationDegrees : Integer); overload;
// center anchored
procedure DrawScaled(canvas : TW3Canvas; dx,dy : Float; FrameIndex : Integer;
scale : Float); overload;
Property SpriteWidth:Integer read FWidth write setWidth;
Property SpriteHeight:Integer read FHeight write setHeight;
property SpriteHalfWidth : Integer read FHalfWidth;
property SpriteHalfHeight : Integer read FHalfHeight;
property Rows : Integer read FRows;
property Columns : Integer read FColumns;
property NbFrames : Integer read FTotal;
Property Ready : Boolean read FReady;
property OnReady : TNotifyEvent read FOnReady write FOnReady;
End;
implementation
Constructor TW3SpriteSheet.Create;
Begin
inherited Create;
FImage:=TW3Image.Create(NIL);
FImage.OnLoad:=HandleImageReady;
FWidth:=32;
FHeight:=32;
InitSinCos;
end;
destructor TW3SpriteSheet.Destroy;
Begin
FImage.onLoad:=NIL;
FImage.free;
inherited;
end;
class procedure TW3SpriteSheet.InitSinCos;
var
i : Integer;
begin
if vSinCosReady then Exit;
vSinCosReady:=True;
for i:=0 to 359 do begin
var a := DegToRad(i);
vCosTable.Add(Cos(a));
vSinTable.Add(Sin(a));
end;
end;
Procedure TW3SpriteSheet.setWidth(aValue:Integer);
Begin
FWidth:=Max(aValue,4);
ReCalcInfo;
end;
procedure TW3SpriteSheet.setheight(aValue:Integer);
Begin
FHeight:=Max(aValue,4);
ReCalcInfo;
end;
Procedure TW3SpriteSheet.ReCalcInfo;
var
img : Variant;
Begin
if FReady then Begin
img:=ObjToVariant(FImage.TagRef);
FColumns:=(img.width+1) div FWidth;
FRows:=(img.height+1) div FHeight;
FTotal:=FColumns * FRows;
end else Begin
FColumns:=0;
FRows:=0;
FTotal:=0;
end;
FHalfHeight:=FWidth shr 1;
FHalfWidth:=FHalfHeight shr 1;
end;
procedure TW3SpriteSheet.HandleImageReady(sender:TObject);
Begin
FReady:=True;
ReCalcInfo;
if Assigned(FOnReady) then
FOnReady(Self);
end;
Procedure TW3SpriteSheet.LoadImage(aUrl:String);
Begin
FReady:=False;
ReCalcInfo;
FImage.LoadFromUrl(aUrl);
end;
procedure TW3SpriteSheet.LoadImage(aUrl : String; aSpriteWidth, aSpriteHeight : Integer);
begin
LoadImage(aURL);
SpriteWidth:=aSpriteWidth;
SpriteHeight:=aSpriteHeight;
end;
Procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas;
dx,dy:Integer;FrameIndex:Integer);
var
sx,sy: Integer;
Begin
if FReady then Begin
sy:=FrameIndex div FColumns;
sx:=FrameIndex-sy*FColumns;
Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
sx*SpriteWidth, sy*SpriteHeight,
SpriteWidth, SpriteHeight,
dx, dy, SpriteWidth, SpriteHeight);
end;
end;
Procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas;
dx,dy:Integer;FrameIndex:Integer; rotationDegrees : Integer);
var
sx,sy: Integer;
begin
if rotationDegrees=0 then begin
Draw(Canvas, dx, dy, FrameIndex);
exit;
end;
if FReady then begin
sy:=FrameIndex div FColumns;
sx:=FrameIndex-sy*FColumns;
Canvas.Save;
case rotationDegrees of
0 : Canvas.Translate(dx, dy);
90 : Canvas.Transform(0, -1, 1, 0, dx, dy+SpriteHeight);
180 : Canvas.Transform(-1, 0, 0, -1, dx+SpriteWidth, dy+SpriteHeight);
270 : Canvas.Transform(0, 1, -1, 0, dx+SpriteWidth, dy);
else
while rotationDegrees<0 do
rotationDegrees+=360;
while rotationDegrees>=360 do
rotationDegrees-=360;
var c := vCosTable[rotationDegrees];
var s := vSinTable[rotationDegrees];
if rotationDegrees>=360-45 then
rotationDegrees+=45-360
else rotationDegrees+=45;
var c2 := vCosTable[rotationDegrees];
var s2 := vSinTable[rotationDegrees];
const r2 = Sqrt(2)/2;
Canvas.Transform(c, -s, s, c, dx+SpriteWidth*(0.5-r2*s2), dy+SpriteHeight*(0.5-r2*c2));
end;
Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
sx*SpriteWidth, sy*SpriteHeight,
SpriteWidth, SpriteHeight,
0, 0, SpriteWidth, SpriteHeight);
Canvas.Restore;
end;
end;
procedure TW3SpriteSheet.DrawScaled(canvas : TW3Canvas; dx, dy : Float; frameIndex : Integer;
scale : Float);
var
sx, sy : Integer;
sw, sh : Float;
begin
if FReady then Begin
sy:=FrameIndex div FColumns;
sx:=FrameIndex-sy*FColumns;
sw:=SpriteWidth*scale;
sh:=SpriteHeight*scale;
Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
sx*SpriteWidth, sy*SpriteHeight,
SpriteWidth, SpriteHeight,
dx-sw*0.5, dy-sh*0.5, sw, sh);
end;
end;
Bookmarks