Results 1 to 6 of 6

Thread: Controlling all instances of a class

  1. #1

    Controlling all instances of a class

    Hi

    I'm trying to get my sprite engine up and running, but I need to find a way to control all instances of the sprite class using one method.

    TSprite:
    [pascal]
    type
    TSprite = class
    private
    ...
    public
    X, Y, Z: Integer;
    ...
    procedure Draw();
    end;
    [/pascal]

    Instances:
    [pascal]
    var
    Sprite1, Sprite2: TSprite;
    ...
    [/pascal]

    Sprite Engine Class:
    [pascal]
    type
    TSpriteEngine = class
    private
    ...
    public
    ...
    procedure DrawAll();
    end;

    ...

    procedure TSpriteEngine.DrawAll();
    begin
    //Here all the instances of TSprite should be drawn...
    end;
    [/pascal]

    I know c/c++ has a way of doing it like this:
    Code:
    ...
    for each TSprite
    {
     Draw();
    };
    ...
    I'm trying to get the sprites to draw once and overlap each other according to the Z value. Is there a way that I can parse through all the instances of TSprite?

    Thanks ahead...

  2. #2

    Re: Controlling all instances of a class

    Quote Originally Posted by PJP Dev
    Instances:
    [pascal]
    var
    Sprite1, Sprite2: TSprite;
    ...
    [/pascal]
    I think this is where it goes wrong. You should make array in TSpriteEngine and keep Sprite instances only there.

    [pascal]TSpriteEngine = class
    private
    ...
    public
    Sprite: array of TSprite;
    Count: integer;
    ...
    procedure AddSprite(newSprite: TSprite);
    destructor Destroy; override;
    ...
    end;

    TPlayerSprite = class(TSprite)
    .. // You can add something custom to player here
    end;

    procedure TSpriteEngine.AddSprite(newSprite: TSprite);
    var i,j: integer; temp: TSprite;
    begin
    inc(Count);
    setlength(Sprite,Count);
    Sprite[Count-1]:=newSprite;

    // Z-Sort (is possible to optimize this...)
    for i:=0 to Count-2 do
    for j:=i+1 to Count-1 do
    if sprite[i].Z>Sprite[j].Z then begin // Change places
    temp:=sprite[i];
    sprite[i]:=sprite[j];
    sprite[j]:=temp;
    end;
    end;

    destructor TSpriteEngine.Destroy;
    var i: integer;
    begin
    for i:=0 to Count-1 do
    sprite[i].Free;
    setlength(sprite,0);
    inherited;
    end;
    [/pascal]

    [pascal]var newSprite: TPlayerSprite;
    begin
    ..
    newSprite:=TPlayerSprite.Create;
    SpriteEngine.Add(newSprite);
    newSprite.Z:=10;
    ..
    end;

    procedure TSpriteEngine.DrawAll();
    var i: integer;
    begin
    // Here all the instances of TSprite should be drawn...
    for i:=0 to Count-1 do
    Sprite[i].Draw;
    end;[/pascal]

    Hope it helps

  3. #3

    Re: Controlling all instances of a class

    You should take a look at the (Un)delphix DXSprite.pas unit. It's a great example of what a sprite-engine could look like. I learned alot of tricks (including some OOP) form that unit.

    Code:
    ...
    for each TSprite
    {
     Draw();
    };
    ...
    Does this really work in C++? I've never seen anything like this (Iterating through all instances of a type). It looks more like python, If it's at all possible.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  4. #4

    Re: Controlling all instances of a class

    Python? C++? I saw it somewhere...

    Thanks for the tip. I got it right by making the TSpriteEngine a derived class from TList and each time a TSprite instance gets created its added to the TSpriteEngine list... So calling TSpriteEngine.Draw() will draw all the sprites... and calculate drawing order according to the Z value of TSprite.

    [pascal]
    type
      TSprite = class;
      TSpriteEngine = class(TList);

      TSprite = class
      private
        FEngine: TSpriteEngine;
      public
        constructor Create(AEngine: TSpriteEngine);
        property Engine: TSpriteEngine;
      end;

      TSpriteEngine = class(TList)
      private
        ...
      public
        procedure Add(Sprite: TSprite);
        property Items[Index: Integer]: TSprite read GetItem write SetItem;
        procedure Draw();
      end;

    ...

    constructor TSprite.Create(AEngine: TSpriteEngine);
    begin
      //Create the sprite and add to engine
      FEngine := AEngine;
      FEngine.Add(Self);
    end;
    [/pascal]

    That helps to stop errors: "Undeclared identifier - TSpriteEngine"

    Thanks for the help everyone...

  5. #5

    Re: Controlling all instances of a class

    You don't need to derive from TList. I always create a TList object inside my objects, because you might want to add lists in the future. Only derive from a class when your class has a "Is a kind of" relationship with the ancestor class. In this case, it isn't true, because the sprite-engine isn't just one list of sprites.

    For example, in the DXSprite unit, the TSpriteEngine contains a "Sprite" list, a "Draw" list and a "dead" list.

    The sprite-list contains all the sprites present in the game. The draw list contains all the sprites that are visible in drawing order (so you don't have to sort them every frame). The dead-list contains all sprites that are dead and should be removed from the game. This is usually only possible at the end of a frame, since other sprites might rely on it while the frame is being computed/rendered.

    You should take a look at that unit. I found it really helpfull when i was learning this stuff.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  6. #6

    Re: Controlling all instances of a class

    Mmm... Seems like thats the best way to do it. I'll give it a try, but I'll have to rewrite most of the sprite engine code.

    Thanks everyone...

Bookmarks

Posting Permissions

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