Results 1 to 2 of 2

Thread: SpriteSheet class

  1. #1

    SpriteSheet class

    For classic tiled sprite sheets.

    Currently supports drawing a tile with rotation or scaling.

    Fully hardware-accelerated on Chrome, IE9, iOS & (AFAIK) OSX Safari (but not Windows Safari)

    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;

  2. #2
    Hi

    Is there a sample in Smart Mobile Studio that uses the sprite sheet?
    The views expressed on this programme are bloody good ones. - Fred Dagg

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •