Results 1 to 10 of 87

Thread: Space Shooter Game Editor

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Hello,

    SilverWarriror, I've changed my map layout to the one youv'e suggested :
    Code:
       TTileData=record
             ImageIndex: integer; // Tile Number
             AnimStart: integer; // Tile Animation Start Position
             AnimSpeed: Single; // Tile Animation Speed
             AnimCount: Integer; // Tile Animation Count
            end;
      TMapLine=array [0..19] of TTileData; // Stores one line of tile data
      TMap=record
             name:string[20];  // Name of the Map
             map_length:integer; // Length of the Map
             Lines: array of TMapLine; // stores the Entire map [0,0..19] , first value is 0 till map_length (vertical), second value is 0..19 (horizontal)
           end;
    I've also managed to get smooth scrolling working in one direction using your method (took me a while I know, had some brainfog issues, was sitting before this damn computer for many hours and nothing, couldn't even start...then yesterday it suddenly hit me.

    This is the code that moves the map down ( I'll reverse my logic...and guess it'll work for up )

    Code:
     procedure TMain.TestExecute(Sender: TObject);
    var x,y : integer;
        new_line : boolean;
    begin
      if Offset < Map.map_length-14 then    // -14 , Number of Tile Lines Drawn on Screen
        begin
        inc(Counter,1);         // I'm using this to check if I've scrolled down one tile Height (32), if I did
        if Counter = 32 then    // then I'm increasing Offset by 1 and reseting Counter to 0, Offset is used to tell the new line of sprites which Line of TileData
          begin                 // to read from the array
            Inc(offset,1);
            Counter:=0;
          end;
        for y:=0 to 15 do
          begin
            for x :=0 to 19 do
              begin
                BackGround[x,y].Y:=BackGround[x,y].Y-1;
                if BackGround[x,y].Y = -32 then
                  begin
                    BackGround[x,y].Dead;
                    new_line := true;
                  end;
                if new_line = true then
                  begin
                    BackGround[x,y]:= TBackGround.Create(SpriteEngine);
                    Edit9.Text:=inttostr(offset);
                    BackGround[x,y].ImageName:= Images.Item[map.Lines[offset+15,x].ImageIndex].Name;
                    if BackGround[x,y].PatternCount = 1 then
                      begin
                        BackGround[x,y].DoAnimate:=false;
                      end
                    else
                      begin
                         BackGround[x,y].AnimStart:=0;
                         BackGround[x,y].AnimCount:=map.Lines[offset+15,x].AnimCount;
                         BackGround[x,y].AnimSpeed:=map.Lines[offset+15,x].AnimSpeed;
                         BackGround[x,y].AnimPos:=(GlobalAnimCounter mod BackGround[x,y].AnimCount)+map.Lines[offset+15,x].AnimStart;
                         BackGround[x,y].DoAnimate:=true;
                         BackGround[x,y].AnimLooped:=true;
                      end;
                    BackGround[x,y].X:=x*32;
                    BackGround[x,y].Y:=480;
                    BackGround[x,y].Z:=1;
                    new_line:=false;
                  end;
              end;
          end;
      end;
    end;

    Everything is nice with this, works like magic, but I have one problem... the animation is not in sync, I'm using GlobalAnimationCount as you've suggested (it works when I scroll trough the map line by line, but not when I do this smooth scrolling)

    EDIT : actually the newly created TILE Lines are in sync , meaning each New line which has 15 Sprites , all of them 15 sprites are in sync, but everytime a new line is created it's not in sync with the previous line.

    This is how GlobalAnimationCount is increased
    Code:
       if GlobalAnimCounter = 1000 then GlobalAnimCounter:=0;
      inc(GlobalAnimCounter,1);
    This above is defined on AsphyreDevice1.Render.


    Any idea why my anim is out of sync when "smooth" scrolling down, but not out of sync when scrolling line by line. I'm doing the same thing on Drawlevel and there it works :

    Code:
    procedure TMain.CreateSprites;
    var x,y : integer;
    begin
    // this procedure creates the starting sprites for one screen and fills them with Empty.image
      for y := 0 to 15 do  // vertically
        begin
          for x := 0 to 19 do   // horizontally
            begin
                BackGround[x,y] := TBackGround.Create(SpriteEngine);
                BackGround[x,y].ImageName:= 'Empty.image';
                BackGround[x,y].X:=x*32;
                BackGround[x,y].Y:=y*32;
                BackGround[x,y].Z:=1;
            end;
        end;
    end;
    
    procedure TMain.DrawSprites;
    var x,y: Integer;
    begin
    // this procedure changes the images for every sprite created at startup, creating the illusion of scrolling trough the map
    // line-by-line
         for y := 0 to 15 do   // vertically
            begin
              for x := 0 to 19 do // horizontally
                begin
                
                 BackGround[x,y].ImageName:= Images.Item[map.Lines[y+Offset,x].ImageIndex].Name;
                 if BackGround[x,y].PatternCount = 1 then
                    begin
                      BackGround[x,y].DoAnimate:=false;
                    end
                  else
                    begin
                       BackGround[x,y].AnimStart:=0;
                       BackGround[x,y].AnimCount:=map.Lines[y+Offset,x].AnimCount;
                       BackGround[x,y].AnimSpeed:=map.Lines[y+Offset,x].AnimSpeed;
                       BackGround[x,y].AnimPos:=(GlobalAnimCounter mod BackGround[x,y].AnimCount)+map.Lines[y+Offset,x].AnimStart;
                       BackGround[x,y].DoAnimate:=true;
                       BackGround[x,y].AnimLooped:=true;
                    end;
                end;
            end;
    end;
    EDIT : I was thinking that maybe I should use another counter , which would count the time between two created sprites ?

    1 I create the initial sprites 16 lines 0..15 .
    2 I start moving the sprites up (lines 0..15) and start the differential_timer
    3 I destroy spriteline which is -32 , and add a new sprite line and reset differential timer to 0 ( here I'm not sure... I maybe do this ?
    Code:
                          BackGround[x,y].AnimPos:=(GlobalAnimCounter-differential_timer mod BackGround[x,y].AnimCount)+map.Lines[offset+15,x].AnimStart;
    )

    and I keep repeating step 1,2,3 till I reach the end. This idea any good?
    Greetings
    Robert
    Last edited by robert83; 10-01-2013 at 01:22 PM.

  2. #2
    From your code I see that you are resetting your Global Animation Counter when it reches 1000. If I remember corectly your water animation has 3 pictures. So as 1000 is not dividable by 3 this creates a problem. So you should reset your counter at 999 and you should go and reset it to1 or if you have first animation picture at index 0 you should reset your counter at 998 and then reset it to 0.
    But there will be even bigger problem once you introduce animation with varios speeds and various lenghts. Why? Becouse you will need to find a right point when to reset your counter (first point when all animations would reach the starting position).
    Best way to do this is to calculate how much time each animation loop lasts (animation lenght * animation speed - where animation speed determines time between animation updates) and then find a time when all these animations will reach to starting position at the same time.
    You do this by finding first number which is dividable with all theese loop times. If my memory servews me correct there is a function in Math unit to do this. Do note that this function can be quite slow at some times.
    Workaround for this is to simply multiply all these loop times between each other as this will give you certain point in time when all these animations do get to starting position but ti might not be the first time when this happens.
    So for instance if you have three different animations first lasts two seconds, second lasts three seconds and third lasts 5 seconds you will the time when all of theese gets to starting position at the same time using 2*3*5=30. So int this case you could reset your Global Animation Counter every 30 seconds.

    I hope my explanation is understandable enough. I'm also sorry that I haven't yet prepared my programing enviroment to be able to compile your project. After about thee years I had some problems with my laptop for the first time which required some troublehunting. In the end it turned out that some files belonging to Eset antivirus software were damaged which in some ocasions caused unexpected program behavior. Also I noticed some system slowdows incase of large HDD activity but I'm not yet sure whether this is due to some software problem or it is hardware related (HDD S.M.A.R.T reports shows no anomalies or problems, but there is ocasional clickig sound coming from HDD but no Bad sectors yet).
    Best solution would be for me to buy a new disk drive probbably SSD and instal it as second drive (my laptop actually supports usage of two SATA 3 hard drives) and reinstal my whole operating system. This would alow me to keep all the old data so that incase I screw up something I don't use any data (I do have lots of important data on my Laptop and no space to make a safety backup of it). And another problem is that as I didn't had Windows 7 before my data isn't quite organized.
    Last edited by SilverWarior; 10-01-2013 at 03:36 PM.

  3. #3
    Hi,

    OFFTOPIC

    or use Virtual Machine with Windows 7 , I actually use windows xp virtual machine to administer my samba domain controllers...
    or just install Delphi 7 on Win7 , or Delphi 7SE if you wish...it works.

    OFFTOPIC

    Anyway I've decieded to attach my latest source, I've redid the entire window, this should be fully visible on your laptop screen (it is on mine... think it's 1280x800 or something....)

    You open up the editor...then click on FILE-OPEN level02.map ...then press the up arrow key (don't ask...why I used it for down )

    I've completely removed the GlobalAnimCounter reset...as you can see it goes till it reaches it's limit and probably makes the app crash or something....

    As you can see when you press UP arrow , and the map moves down... each new sprite line is created (every sprite on the new line is in sync with each other) , but each NEW sprite line is a bit off from the previous creating my wave effect....

    Greetings
    Robert
    Attached Files Attached Files

  4. #4
    If you must use such global animation counter, couldn't you make it single type, and run from [0.0 .. 1.0[ (means 1.0 isn't included)? Then just scale each animation to its specific framecount.
    Code:
    AniPos:=trunc(GlobalCounter*FrameCount);
    Code:
    GlobalCounter:=GlobalCounter+0.02; 
    if GlobalCounter>=1 then GlobalCounter:=GlobalCounter-1;
    Last edited by User137; 11-01-2013 at 09:00 AM.

  5. #5
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Ok so your basic issue is synchronizing the animation of sprites, that may of been added at any time during the animation of the others.

    There are many ways you could do this (although unless you have two co-dependant animations I can't see why you'd want this) but rather than incrementing every single sprite for the next frame of animation, how about you group the same sprites together or sprites that have the same number of frames? IE:

    SpriteGroup1_FrameNumber = 3

    for I := 0 to SpriteGroup1_SpriteCount-1 do
    Spites[I].CurrentFrame = spritegroup1_framenumber;


    That way you can ensure that for animations of the same speed/number of frames, that they are always rendered on the same frame, regardless if one was added halfway thru the animation cycle.

    Now as far as synchronzing animations of different lengths, why? scheduling so they start at the same time will mean that at some point, you'll have something that should be on screen, but isn't because it's waiting for the start of the next cycle.

    if you have animations of different lengths that you wish to synchronize, then you should scale the frame-rate of one of the animations so they both take the same amount of time to run.

    --

    I'm currently extending my 3D animation lib with better interpolation between animations. Here's an example to get you thinking :

    Walk animation -15 frames - 0.8 second cycle from left foot to left foot. actual movement Speed = 3
    Run animation - 20 frames - 0.4 second cycle """ actual movement Speed = 5

    So how do you smoothly interpolate the skeleton between frames so you can blend walk into run and visa versa?

    The trick is (other than other artist/bone related stuff to make animations that will blend well) that you scale both
    animations at the same time. so if walk has an anim cycle of 0.8, and run 0.4, then halfway through the blend, both animations are scaled so they both have a cycle of 0.6 and a speed of 4 (exactly half way between the two).

    So it doesn't matter where in the animation you start running or walking, it'll always be able to interpolate fairly well.

    --

    As far as sprites are concerned, what's so offputting about the non synchronized animations? if you created a forest you want all the trees to sway in sync?

    Like I say, unless your animations are co-dependant and require sync (two sprites throwing a ball at each other) then you should probably not bother.

    Oh and if you absolutely must sync different length anims so they start on the same frame, then just add dummy frames to the shorter one so it's the same number of frames. yes that'll use slightly more more memory but you'll save yourself a whole bunch of code. Combine that with grouping of sprites
    Last edited by phibermon; 11-01-2013 at 01:17 PM.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  6. #6
    I must have perfectly synced sprites somehow, I don't want to complicate my life with Sprite Groups...
    For example I might want to have some object that consists of 4 tiles do something out of sync, other times in a certain order, or in perfect sync. I believe it should be doable to sync newly created tiles with previously created tiles, only problem is this seems to be beyond my knowledge right now...

    I've tried to do it like this :

    1. Created a new 2d array , that is responsible for holding the current animation position for every tile on my tile map ( I though baaammmmmmm eat this EVIL sprite engine time offset demon )
    Code:
      TAnimTable=array of array [0..19] of single;
    2. I've created the following procedure :
    Code:
    procedure TMain.AnimCounter;
    var i,j: integer;
    begin
          for i:=0 to Map.map_length do
            begin
              for j:=0 to 19 do
                begin
                  if map.Lines[i,j].AnimCount > 1 then
                    begin
                      AnimTable[i,j]:=AnimTable[i,j]+(1*map.Lines[i,j].AnimSpeed);
                    end
                  else
                    begin
                      AnimTable[i,j]:=1;
                    end;
                  if AnimTable[i,j] > map.Lines[i,j].AnimCount then AnimTable[i,j]:=0;
                end;
            end;
    end;
    This I've checked (using a few EDIT boxes ) works, for example Animated Sprite at 0,0 has 3 animation positions , and it's speed is 0,01 ... I've checked the position goes up with the apropriate speed.
    I've added another Sprite at 0,1 which has 6 animation positions, and it's speed is 0,5 , I've checked it again it goes at a much faster rate...

    I thought to myself YEAH I solved this darn problem... (and the program is still pretty fast, even on me amd duron 1400+ , with my test level...which is not to long , but I don't plan to make enormous levels...a dude has to start somewhere...)

    I've modified my smooth scroll test procedure a bit :

    Code:
    procedure TMain.TestExecute(Sender: TObject);
    var x,y : integer;
        new_line : boolean;
    begin
      if Offset < Map.map_length-14 then    // -14 , Number of Tile Lines Drawn on Screen
        begin
        inc(Counter,1);         // I'm using this to check if I've scrolled down one tile Height (32), if I did
        if Counter = 32 then    // then I'm increasing Offset by 1 and reseting Counter to 0, Offset is used to tell the new line of sprites which Line of TileData
          begin                 // to read from the array
            Inc(offset,1);
            Counter:=0;
          end;
    
        for y:=0 to 15 do
          begin
            for x :=0 to 19 do
              begin
                BackGround[x,y].Y:=BackGround[x,y].Y-1;
                if BackGround[x,y].Y = -32 then
                  begin
                    BackGround[x,y].Dead;
                    new_line := true;
                  end;
                if new_line = true then
                  begin
                    BackGround[x,y]:= TBackGround.Create(SpriteEngine);
                    Edit9.Text:=inttostr(offset);
                    BackGround[x,y].ImageName:= Images.Item[map.Lines[offset+15,x].ImageIndex].Name;
    
                    if BackGround[x,y].PatternCount = 1 then
                      begin
                        BackGround[x,y].DoAnimate:=false;
                      end
                    else
                      begin
                       BackGround[x,y].DoAnimate:=true;
                       BackGround[x,y].AnimLooped:=true;
                      end;
                    BackGround[x,y].X:=x*32;
                    BackGround[x,y].Y:=480;
                    BackGround[x,y].Z:=1;
                    new_line:=false;
                   end;
                   BackGround[x,y].AnimStart:=round(AnimTable[x,y+Offset]);
                   BackGround[x,y].AnimCount:=map.Lines[y+Offset,x].AnimCount;
                   BackGround[x,y].AnimSpeed:=map.Lines[y+Offset,x].AnimSpeed;
              end;
          end;
      end;
    end;
    The AnimCounter procedure is executed at AsphyreDevice1Render .

    And I still get the cursed wave effect , how....is....this....possible ?

    Now that I think of it...maybe the problem is...that now since I'm doing the position calculation... maybe I should manually step the images? Can I do that somehow?
    The idea here was to calculate all animation positions for every tile , even uncreated... thus eliminating the lag caused by it's creation... I think it should work...if I could somehow manually step the Sprite Position
    every time when the TEST action runs to my AnimTable[x,y] position... I can even add Animation Offset into this combo...


    Greetings
    Robert
    Last edited by robert83; 11-01-2013 at 07:28 PM.

  7. #7
    I DID IT!!!!!!!!!!!!!!!!!! AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Code:
    procedure TMain.TestExecute(Sender: TObject);
    var x,y : integer;
        new_line : boolean;
    begin
      if Offset < Map.map_length-14 then    // -14 , Number of Tile Lines Drawn on Screen
        begin
        inc(Counter,1);         // I'm using this to check if I've scrolled down one tile Height (32), if I did
        if Counter = 32 then    // then I'm increasing Offset by 1 and reseting Counter to 0, Offset is used to tell the new line of sprites which Line of TileData
          begin                 // to read from the array
            Inc(offset,1);
            Counter:=0;
          end;
    
        for y:=0 to 15 do
          begin
            for x :=0 to 19 do
              begin
                BackGround[x,y].Y:=BackGround[x,y].Y-1;
                BackGround[x,y].AnimPos:=AnimTable[y+Offset,x];
                Edit2.Text:=formatfloat('####.##',AnimTable[y+Offset,x]);
                if BackGround[x,y].Y = -32 then
                  begin
                    BackGround[x,y].Dead;
                    new_line := true;
                  end;
                if new_line = true then
                  begin
                    BackGround[x,y]:= TBackGround.Create(SpriteEngine);
                    Edit9.Text:=inttostr(offset);
                    BackGround[x,y].ImageName:= Images.Item[map.Lines[offset+15,x].ImageIndex].Name;
                   if BackGround[x,y].PatternCount = 1 then
                      begin
                        BackGround[x,y].DoAnimate:=false;
                      end
                    else
                      begin
                       BackGround[x,y].AnimStart:=0;
                       BackGround[x,y].AnimCount:=map.Lines[offset+15,x].AnimCount;
                       BackGround[x,y].AnimSpeed:=map.Lines[offset+15,x].AnimSpeed;
                       BackGround[x,y].AnimPos:=AnimTable[y+Offset,x];
                       BackGround[x,y].DoAnimate:=true;
                       BackGround[x,y].AnimLooped:=true;
                      end;
                    BackGround[x,y].X:=x*32;
                    BackGround[x,y].Y:=480;
                    BackGround[x,y].Z:=1;
                    new_line:=false;
                   end;
              end;
          end;
    
      end;
    end;
    Had it reversed on AnimTable[x,y]... [y+Offset,x] is correct... damn I'm getting lost on my arrays... anyway I'll clean up the code a bit... and post the full source with the exe here... I've tried it again just to make sure...it works...no matter what I do
    I scroll down a bit ...wait....scroll again....or scroll completely to the end... the result...perfectly synced sprites the way I like em...

    EDIT : something is still off... I'll need to check the code ...I'm getting lost in my arrays.... I'm not reading the animpos correctly from the array for the vertical line... will recheck

    Greetings
    Robert
    Last edited by robert83; 11-01-2013 at 10:07 PM.

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
  •