Smart Mobile Studio
  • News
  • Forums
  • Download
  • Store
  • Showcases
    • Featured demos
    • The Smart Contest 2013, Round 1 – Graphics
  • Documentation
    • Get the book
    • System requirements
    • Prerequisites
    • Getting started
      • Introduction
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • Themes and styles
    • Project types
      • Visual project
      • Game project
      • Console project
    • Layout manager
    • Networking
      • TW3HttpRequest
      • TW3JSONP
      • Loading files
  • About

A simple sprite-sheet

Posted on 06.01.2012 by Jon Lennart Posted in Developers log

A sprite sheet is basically just an image. But it’s an image that is organized in a special way, usually with a 32×32 or 64×64 pixel grid where each cell contains either a character animation frame – or a background tile. Back in the old Amiga days of 8 bit graphics and hand crafted sprites this was the only way to go.

Since the world of mobile javascript game development is more or less en-par with the old Amiga (in terms of cpu power and restrictions. Which is amazing since the Amiga had a 1hz motorola mc68000 CPU) an example of a spritesheet class might come in handy.

Classical sprite sheet from sega

Classical sprite sheet from sega

A simple spritesheet class

TW3SpriteSheet = class(TObject)
private
  FImage:     TW3Image;
  FReady:     Boolean;
  FColumns:   Integer;
  FRows:      Integer;
  FTotal:     Integer;
  FWidth:     Integer;
  FHeight:    Integer;
  FOnReady:   TNotifyEvent;
  procedure   HandleImageReady(sender:TObject);
  procedure   SetWidth(aValue:Integer);
  procedure   Setheight(aValue:Integer);
  Procedure   ReCalcInfo;
public
  Property    OnReady:TNotifyEvent read FOnReady write FOnReady;
  Property    SpriteWidth:Integer read FWidth write setWidth;
  Property    SpriteHeight:Integer read FHeight write setHeight;
  Property    Ready:Boolean read FReady;
  Procedure   LoadImage(aUrl:String);
  Procedure   Draw(Canvas:TW3Canvas;dx,dy:Integer;FrameIndex:Integer);
  Constructor Create;virtual;
  destructor  Destroy;Override;
end;

constructor TW3SpriteSheet.Create;
begin
  inherited Create;

  FWidth  := 32;
  FHeight := 32;
  FColumns := 0;
  FRows  := 0;
  FTotal := 0;

  FImage := TW3Image.Create(NIL);
  FImage.OnLoad := HandleImageReady;
end;

destructor TW3SpriteSheet.Destroy;
begin
  FImage.onLoad:=NIL;
  FImage.free;
  inherited;
end;

procedure TW3SpriteSheet.setWidth(aValue:Integer);
begin
  FWidth:=w3_ensureRange(aValue,4,MAXINT);
  ReCalcInfo;
end;

procedure TW3SpriteSheet.setheight(aValue:Integer);
begin
  FHeight:=w3_ensureRange(aValue,4,MAXINT);
  ReCalcInfo;
end;

procedure TW3SpriteSheet.ReCalcInfo;
begin
  if FReady then
  begin
    FColumns:=FImage.Width div FWidth;
    FRows:=FImage.Height div FHeight;
    FTotal:=FColumns * FRows;
  end else
  begin
    FColumns:=0;
    FRows:=0;
    FTotal:=0;
  end;
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.Draw(Canvas:TW3Canvas; dx,dy:Integer; FrameIndex:Integer);
var
  sx,sy:  Integer;
begin
  if  FReady
  and assigned(canvas)
  and (FrameIndex>=0)
  and (FrameIndex<FTotal) then
  Begin
    sx:=FrameIndex mod FColumns;
    sy:=FrameIndex div FRows;
    sx:=sx * FWidth;
    sy:=sy * FHeight;
    canvas.DrawImageEx2F(FImage.tagRef,sx,sy,FWidth,
    FHeight,dx,dy,FWidth,FHeight);
  end;
end;

Using the class

Using the class is simple. Initialize it in TApplication.ApplicationStarting method and load in a picture, like this:

  FSheet := TW3SpriteSheet.Create;
  FSheet.LoadImage('res/sprites.png');

When the actual sprite-sheet image is loaded, the “ready” property will be set to true. So in your PaintView method always check the ready flag before accessing it:

  if FSheet.Ready then
  begin
    FSheet.Draw(Canvas,100,100,10); // draw tile #10
    FSheet.Draw(Canvas,133,100,11); // draw tile #11
    FSheet.Draw(Canvas,166,100,12); // draw tile #12
  end;

Enjoy!

« How do i plot pixels on a offscreen bitmap?
Articles about Smart »

Pages

  • About
  • Feature Matrix
  • Forums
  • News
  • Release History
  • Download
  • Showcases
    • The Smart Contest 2013, Round 1 – Graphics
  • Store
  • Documentation
    • Creating your own controls
    • Debugging, exceptions and error handling
    • Differences between Delphi and Smart
    • Get the book
    • Getting started
      • Introduction
      • Local storage, session storage and global storage
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • pmSmart Box Model
      • Themes and styles
    • Layout manager
    • Networking
      • Loading files
      • TW3HttpRequest
      • TW3JSONP
    • Prerequisites
    • Real data, talking to sqLite
    • System requirements
    • Project types
      • Visual project
      • Game project
      • Console project

Archives

  • December 2019
  • December 2018
  • November 2018
  • July 2018
  • June 2018
  • February 2018
  • September 2017
  • April 2017
  • November 2016
  • October 2016
  • September 2016
  • April 2016
  • March 2016
  • January 2016
  • October 2015
  • September 2015
  • July 2015
  • April 2015
  • January 2015
  • December 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • November 2011
  • October 2011
  • September 2011

Categories

  • Announcements (25)
  • Developers log (119)
  • Documentation (26)
  • News (104)
  • News and articles (16)

WordPress

  • Register
  • Log in
  • WordPress

Subscribe

  • Entries (RSS)
  • Comments (RSS)
© Optimale Systemer AS