Friday 31 August 2007

I've now added a Sprite Pool Class

I have added the Animated Base Sprite class that now allows sprites to be created with built in functionality for handling animation. I have also created a new batch class that holds two lists of item. This batch allows me to create a "pool" of sprites held in what I call the "Dead List". A simple call to the batch transfers a "Dead" sprite to the "Live List". Any sprite on the Live List will be rendered. Once a sprite on the Live List is no longer needed another call will transfer it back to the Dead List ready for reuse. I am using some custom written Double Linked Lists to achieve this functionality. This will have speed gains over the built in Delphi TList class. The code below shows how I add three sprites to the SpritePool's Dead List. A single call to "Pool.Acquire" will move a sprite from the Dead List and place it on the Live List. The SpritePool Live List is then passed to the Graphics Device where the sprite is rendered. The SpritePool will be used where large volumes of sprites may need to be used in a hurry. A good example could be an explosion made up of many sprites. By creating a pool before the game play starts, there won't be an slow down when multiple explosions are required. Additional code could be added so that if the Pool ran out of "Dead" sprites, new ones could be created on-the-fly. Obviously we don't want this to happen so some careful calculations should be performed to optimise the size of the Pool.

Any comments ?

The implementation


procedure TForm1.btnListTestClick (Sender : TObject) ;
var
GraphicDev : TGraphicsDevice ;
Content : TVisualContent ;

Pool : TSpritePool ;

begin
GraphicDev := TGraphicsDevice.Create (800, 600, bs24) ;
Content := TVisualContent.Create ('Images') ;
Content.LoadImageContent ;

Pool := TSpritePool.Create ;

Pool.AddToDeadList (TTestSprite.Create (Content.GetImage ('Pic1'), 90, 90, 2)) ;
Pool.AddToDeadList (TTestSprite.Create (Content.GetImage ('Pic2'), 100, 100, 5)) ;
Pool.AddToDeadList (TTestSprite.Create (Content.GetImage ('Pic3'), 110, 110, 3)) ;

Pool.Acquire ;

GraphicDev.DrawSpritePool (Pool.LiveList) ;

GraphicDev.Flip ;

Pool.Update ;
end ;

Thursday 23 August 2007

A Test Sprite Class

To make my test sprite code a bit clearer I thought I should also show the sprite class so that you can see how the settings are used. Notice that my sprite class derives from "BaseSprite". I will soon be adding an "AnimatedSprite" class that will provide base functionality to animate an image.

The declaration

TTestSprite = class (TBaseSprite)
public
constructor Create (theSurface : PSDL_Surface ;
XPos : integer ;
YPos : integer ;
ZPos : cardinal) ;

procedure Update ; override ;
end ;

The implementation

constructor TTestSprite.Create (theSurface : PSDL_Surface ;
XPos : integer ;
YPos : integer ;
ZPos : cardinal) ;
begin
inherited Create ;
ImageSurface := theSurface ;

ImageLocationRect.x := XPos ;
ImageLocationRect.y := YPos ;

ZOrder := ZPos ;

ImageDisplayRect.w := 81 ;
ImageDisplayRect.h := 90 ;
ImageDisplayRect.x := 0 ;
ImageDisplayRect.y := 0 ;
end ;

procedure TTestSprite.Update ;
begin
end ;

Wednesday 22 August 2007

My game library works !


I quickly put together a test and shown below is all that is required to display three sprites on the screen (As shown above).

All the code does is create an SDL rendering surface with dimensions of 800x600 with 24 bits per pixel. All the graphical content in the "Images" directory is loaded. I then create three sprite and load them into a batch handler. I then sort the batch so that the sprite will be rendered using their z-order. I then render the sprites by passing the batch to the graphics device and finally flip the buffer to show the results. The graphics device will also accept single sprites as well as a batch list and there are several other options now shown in this example. And finally, before anyone asks, I haven't shown any code that calls "free" on the objects I have created. Any comments ?

The Code

procedure TForm1.btnSpriteTestClick (Sender : TObject) ;
var
GraphicDev : TGraphicsDevice ;
Content : TVisualContent ;
spr1 : TTestSprite ;

spr2 : TTestSprite ;
spr3 : TTestSprite ;
Batch : TSpriteBatch ;


begin

GraphicDev := TGraphicsDevice.Create (800, 600, bs24) ;

Content := TVisualContent.Create ('Images') ;
Content.LoadImageContent ;

spr1 := TTestSprite.Create (Content.GetImage ('Pic1'), 90, 90, 2) ;

spr2 := TTestSprite.Create (Content.GetImage ('Pic2'), 100, 100, 5) ;
spr3 := TTestSprite.Create (Content.GetImage ('Pic3'), 110, 110, 3) ;

Batch := TSpriteBatch.Create ;

Batch.Add (spr1) ;
Batch.Add (spr2) ;
Batch.Add (spr3) ;

Batch.Sort ;

GraphicDev.DrawSpriteBatch (Batch.SpriteList) ;

GraphicDev.Flip ;

end ;


Tuesday 21 August 2007

Sun, Sea and Cider

Well I'm back from two weeks in sunny Somerset / Devon. Whilst under the influence of sun, sea and cider I spent many a hour designing a set of classes for my next Delphi game. I wanted to produce a library that would make it easy to get a 2D sprite based game working with minimal coding. I also wanted a library that could be reused so that I didn't have to re-invent the wheel all the time. Having spent some time with the XNA content pipeline I have based my set of classes around this concept. I've based the classes around SDL and now have 6 classes that handle audio and visual content and the bliting of individual or batches of sprites. So far I'm very happy with the design as its very OO making it very flexible. It should be easy to add OpenGL support in the future so its reasonably future proof. Over the next few days I will start to put together the basic code of my new game so that I can tweak the library and get a demo up and running.