Results 1 to 10 of 31

Thread: Dynamic in-game object creation and manipulation

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    The numofbullets is a global variable; only the i and j variables are declared in the timer.

  2. #2
    Then I'm afraid I can't help you out further without seeing more code. Best thing would be access to your whole game so I can try to debug it.

  3. #3
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Yep - whatever is going wrong doesn't appear to be connected (at least entirely) with what you've posted so far - I will note however that :

    Code:
                     freeandnil(bullets[i]);
                     if i=numofbullets-1 then
                        dec(numofbullets)
                     else
                     begin
                          for j:=i+1 to numofbullets-1 do
                              bullets[j-1]:=bullets[j];
                          dec(numofbullets);
                     end;
    is convoluted and a mess - why free the bullet at all? just fill your array with created bullet objects and just have a new boolean property of TBullet called 'active'. Then you can simply do :

    Code:
    {go through the array and create a TBullet object with 'active' set to false for all objects as part of your game initialization}
    
    if (plshoot=true) and (plcanshoot=true) then
    begin
       I := 0;
       while Bullet[I].active do
          I := I + 1;
       if I > high(Bullet) then exit;
       Bullet[I].active := true;
       Bullet[I].Xplace := Player.Left;
       Bullet[I].Yplace := Player.Top;
    end;
    
    
    for I := 0 to numofbullets-1 do
    if bullets[I].active then
    begin
       bullet[I].YPlace := bullet[I].YPlace-4;
       if bullet[I].YPlace < 10 then
          bullet[I].Active := false;
    end;
    Then go through the array and only render 'active' bullets - yes you'll be skipping over 'inactive' bullets but that's still loads faster than constantly creating/destroying objects.

    An optimization of this would to be to treat the array like a ring-buffer - then by its very nature the start index is the oldest active bullet and the end index is the newest bullet - only iterate over these - still you'll itterate over some inactive bullets but it'll be much faster than constantly keeping the array tightly packed - you could also use a linked list but really unless you've got thousands of bullets there's no need to care performance wise.

    There are various reasons why you'd want to keep an array tightly packed - perhaps it needs to be kept sorted (but there are better structures such as linked lists) or perhaps you have a need to copy a continuous block of memory for some reason (uploading vertex data to a GPU) but you don't need either of these.

    Also bare in mind that there's no reason you can't have two container structures - a flat array and a linked list - scan the flat array for an inactive bullet - set it to active and add a reference to a linked list. If the bullet is to be 'destroyed' set it to inactive and remove it from the linked list - this way you have a flat array for 'storage' and the linked list for optimal iteration over active elements (linked lists are slow to index but are very fast for deletions/insertions - especially in your case where you delete from anywhere in the list but only add to the end)

    Even better have two linked lists - an active one and an inactive one - then you no longer have to scan for an active bullet or create one - you just remove one from the inactive list and add it to the active list and visa versa - a slow object creating, array shuffling operation becomes a case of setting a few pointers.

    --

    But : these are only suggestions to think about - it's overkill at this stage - as SilverWarrior suggests we'd need to see basically all of your code to tell you what's wrong.
    Last edited by phibermon; 20-12-2015 at 06:01 PM.

  4. #4
    "It's over 800 lines of code and not in english so it's difficult to read."


    I have written the program in Hungarian. (Maybe it's not an easy language, and you not saw it yet in full dress: with diacritics )


    The function "TFoablak.pontirany" is help to direct only the movement of the boss enemy and its bullets, which initial direction are towards the player.
    The bullets of the other enemies are only goes downwards (line 533: [I]if foellvan=0 then elllovedektomb[i].yhely:=elllovedektomb.yhely+4... ).
    And in line 419 happening the creating of bullets of these enemies in the coordinates of actual enemy (xhely: xplace, yhely: yplace):
    [I]elllovedektomb[elllovedekdb]:=TJatekEleme.Letrehoz(ellensegtomb[i].xhely,ellensegtomb.yhely,elllovkepe);
    But sometimes this coordinate totally different, and I don't know, why...

  5. #5
    I speak Hungarian too , but even I find it difficult to read code that is not in english.

    Your english is pretty good, it would help everyone here if you would develop your code in english.

  6. #6
    Quote Originally Posted by robert83 View Post
    I speak Hungarian too , but even I find it difficult to read code that is not in english.
    Your english is pretty good, it would help everyone here if you would develop your code in english.
    Maybe I will so, but it is better for me writing in Hungarian so far, because I can separate my variables and other things better.

  7. #7
    Quote Originally Posted by Tomi View Post
    Maybe I will so, but it is better for me writing in Hungarian so far, because I can separate my variables and other things better.
    I agree with Robert's suggestion.
    Having your code written in English does have a great benefit that you can just simply copy and paste part of your code when you are seeking help from others.

    I myself am not native English speaking person and used to write my code in Slovenian (my native language) but eventually I figured out that it is better if I write my code in English instead. Why?
    When I have all of my code written in English it allows my brains to kind of switch into "English mode" where even most of my thought process is done in English. I know it sounds a bit weird.
    But when I have parts of the code written in Slovenian my brain stays in "Slovenian mode" where I'm forced of constantly having to translate English parts of the code or documentation into Slovenian which I think it slows down the thought process a bit.
    And sometime it might even happen that my brain would en up being in "English mode" and I would end up constantly translating my Slovenian code into English. And yes I know that this seems even weirder.

  8. #8
    No, not so weird, SilverWarior, after all you are right: if I would like help from an English-speaking programmer community, the best is when I write my codes totally in English in order to better understand.
    Therefore today I have made a small program, which is focusing the "bullet appearing" problem:
    Code:
    unit Unit1;
    
    
    {$mode objfpc}{$H+}
    
    
    interface
    
    
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
    
    
    type
    
    
      { TForm1 }
    
    
      TForm1 = class(TForm)
        Timer1: TTimer;
        procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
        procedure FormCreate(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end;
    
    
    type TGameObject=class(TObject)
      private
      public
        xplace,yplace,celx,cely,movedir: integer;
        itsimage: TBitmap;
        canshoot: boolean;
        shoottimer: byte;
        constructor create(xplacehere,yplacehere: longint; imagehere: Tbitmap);
    end;
    
    
    var
      Form1: TForm1;
      backgroundimg,bulletimg,spaceshipimg: TBitMap;
      spaceship: TGameObject;
      bullet: array [0..100] of TGameObject;
      numofbullets: integer;
    
    
    implementation
    
    
    {$R *.lfm}
    
    
    constructor TGameObject.create(xplacehere,yplacehere: integer; imagehere: Tbitmap);
    begin
            xplace:=xplacehere;
            yplace:=yplacehere;
            itsimage:=imagehere;
    end;
    
    
    { TForm1 }
    
    
    procedure TForm1.FormCreate(Sender: TObject);
    var initialmovedir: shortint;
    begin
      backgroundimg := TBitmap.Create;
      backgroundimg.LoadFromFile('kepek/urhatter.bmp');
      bulletimg:=TBitMap.Create;
      bulletimg.LoadFromFile('kepek/ell_lov.bmp');
      bulletimg.transparent:=true;
      spaceshipimg:=TBitMap.Create;
      spaceshipimg.LoadFromFile('kepek/ell1.bmp');
      spaceshipimg.transparent:=true;
      randomize;
      if round(random(2))=1 then initialmovedir:=-2 else initialmovedir:=2;
      spaceship:=TGameObject.create(Form1.ClientWidth div 2,spaceshipimg.height,spaceshipimg);
      spaceship.movedir:=initialmovedir;
      spaceship.shoottimer:=100;
      spaceship.canshoot:=false;
      numofbullets:=0;
    end;
    
    
    procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
    begin
      backgroundimg.free;
      bulletimg.free;
      spaceshipimg.free;
    end;
    
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    var i,j: integer;
    begin
      Form1.Canvas.StretchDraw(Rect(0, 0, ClientWidth, ClientHeight), backgroundimg);
      if spaceship.shoottimer>0 then dec(spaceship.shoottimer) else spaceship.canshoot:=true;
      if (spaceship.xplace+spaceship.movedir>=ClientWidth-spaceshipimg.width) or (spaceship.xplace+spaceship.movedir<=1) then
      begin
           if spaceship.yplace+spaceshipimg.height<ClientHeight then
              spaceship.yplace:=spaceship.yplace+spaceshipimg.height
           else
               spaceship.yplace:=spaceshipimg.height;
           spaceship.movedir:=-spaceship.movedir;
      end
      else
      begin
           spaceship.xplace:=spaceship.xplace+spaceship.movedir;
      end;
      Form1.Canvas.Draw(spaceship.xplace,spaceship.yplace,spaceshipimg);
      if (round(random(50))=1) and (spaceship.canshoot=true) then
      begin
           bullet[numofbullets]:=TGameObject.create(spaceship.xplace,spaceship.yplace,bulletimg); {!!!WRONG!!!}
           inc(numofbullets);
           spaceship.canshoot:=false;
           spaceship.shoottimer:=100;
      end;
    
    
      if numofbullets>0 then
      begin
           i:=0;
           while i<numofbullets-1 do
           begin
                if bullet[i]<>nil then
                begin
                    if bullet[i].yplace>ClientHeight then
                    begin
                        freeandnil(bullet[i]);
                        if i=numofbullets-1 then
                                dec(numofbullets)
                        else
                        begin
                                for j:=i+1 to numofbullets-1 do
                                    bullet[j-1]:=bullet[j];
                                dec(numofbullets);
                                dec(i);
                        end;
                    end
                    else
                    begin
                        bullet[i].yplace:=bullet[i].yplace+4;
                        Form1.Canvas.Draw(bullet[i].xplace,bullet[i].yplace,bulletimg);
                    end;
                end;
                inc(i);
           end;
      end;
    end;
    
    
    end.
    Maybe somebody can help me...

  9. #9
    The last loop is still bothering me, it is needlessly complicated and could make errors. Like i suggested earlier, here's how it would look:
    Code:
      for i:=numofbullets-1 downto 0 do
      begin
        bullet[i].yplace:=bullet[i].yplace+4;
        if bullet[i].yplace>ClientHeight then
        begin
          bullet[i].Free;
          dec(numofbullets);
          bullet[i]:=bullet[numofbullets];
        else begin
          Form1.Canvas.Draw(bullet[i].xplace, bullet[i].yplace, bulletimg);
        end;
      end;

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
  •