Page 1 of 2 12 LastLast
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
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Firstly dynamic arrays start at 0 so you should do :

    Code:
    for I := 0 to numofbullets-1 do
    Secondly your answer my lie in your checks - you've got an array of bullets and you're checking to see if a member is nil before you render - perhaps they are nil? please post your code for how you setup the array of bullets so we can check to see if that's a factor.

    Thirdly you have a 'picture' property for each bullet - if each bullet has a different image then this is fine but I'm guessing you only have a single bullet texture - it's best to load it once and draw it over and over for each bullet - only storing the unique properties per bullet IE :

    Code:
    Canvas.Draw(bullets[i].xplace,bullets[i].yplace, FGlobalBulletPicture);
    and lastly because dynamic arrays start at 0 you don't need :

    Code:
    if numofbullets>1 then
    (but that should read numofbullets > 0 or numofbullets >= 1) because :

    Code:
    for I := 0 to numofbullets-1 do
    when numofbullets = 0 equates to :

    Code:
    for 0 to -1 do
    Which will not enter the loop (use 'downto' instead of 'to' if you want to use descending for loops)
    Last edited by phibermon; 19-12-2015 at 06:52 PM.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  2. #2
    Quote Originally Posted by phibermon View Post
    please post your code for how you setup the array of bullets
    I'm using fixed length arrays:
    Code:
    bullets: array [0..100] of TBullet;
    Then in a Timer event I create, move and destroy the bullets:
    Code:
    if (plshoot=true) and (plcanshoot=true) then
      begin
             abullet:=TBullet.create(Player.Left,Player.Top,bulletpic);
             bullets[numofbullets]:=abullet;
             inc(numofbullets);
      end;
    
    
      if numofbullets>=1 then
      begin
           for i:=0 to numofbullets-1 do
           begin
            if bullets[i]<>nil then
            begin
                bullets[i].yplace:=bullets[i].yplace-4;
                if bullets[i].yplace<10 then
                begin
                     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;
                end;
            end;
           end;
      end;
    (I have already corrected the first variable of the loops from 1 to 0, as you wrote.)
    When I press the fire button, the bullets are only flash at the top of the player. :-/

  3. #3
    Is your numofbullets global variable or is it declared inside Timers OnEvent method.
    If it is declared in an OnTimer event method that means that it is cleared after ending of each Timer cycle and then recreated in another cycle with default value which is 0.

  4. #4
    The numofbullets is a global variable; only the i and j variables are declared in the timer.

  5. #5
    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.

  6. #6
    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.

  7. #7
    "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...

  8. #8
    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.

  9. #9
    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.

  10. #10
    Hello and happy new year, everybody!


    At last, my first game with Lazarus is done: a small space shooter, with some enemies, one boss and power-ups.
    It's name is "Space Defender" and you can download from here:
    http://www.programozzunk.ucoz.hu/laz...k/spacedef.zip
    Unfortunately it has some bugs:
    - the appearance of bullets of enemies sometimes happens in wrong place,
    - the sprites of the spacehips are flashing,
    - sometimes the game throw you out, when the player is rebirth at the boss and you press buttons.
    In spite of all this, I hope that you will enjoy this game, but if you will find the solutions for these bugs, please tell me.

Page 1 of 2 12 LastLast

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
  •