Page 2 of 4 FirstFirst 1234 LastLast
Results 11 to 20 of 31

Thread: Collission detection on level ( source Travels doc + some other examples)

  1. #11
    I'll throw out this kind of suggestion:
    Code:
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X-4,Blurp.Y) then
                    begin
                      Blurp.X:=Blurp.X-4;
                      AdSpriteEngine.X:=AdSpriteEngine.X+4;
                    end;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X+4+Blurp.Image.Width,Blurp.Y) then
                    begin
                      Blurp.X:=Blurp.X+4;
                      AdSpriteEngine.X:=AdSpriteEngine.X-4;
                    end;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X,Blurp.Y-4) then
                    begin
                      Blurp.Y:=Blurp.Y-4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y+4;
                    end;
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X,Blurp.Y+4+Blurp.Image.Height) then
                    begin
                      Blurp.Y:=Blurp.Y+4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-4;
                    end;
                end;
    Code:
    function TBlurp.testForWall(pointX,pointY:single):boolean;
    var tilenr: integer;
    begin
      tilenr:=TileInfo[trunc(pointX) div 64, trunc(pointY) div 64].tilenr;
      case tilenr of
        2: result:=true;
        else result:=false;
      end;
    end;
    Last edited by User137; 16-08-2011 at 03:58 PM. Reason: trunc

  2. #12
    Thank you! It's so simple and works wonderfully... I had to modify it a bit :

    Right :

    Code:
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X+Blurp.Image.Width,Blurp.Y) then
                    begin
                      Blurp.testForWall(Blurp.X+4+Blurp.Image.Width,Blurp.Y);
                      Blurp.X:=Blurp.X+4;
                      AdSpriteEngine.X:=AdSpriteEngine.X-4;
                    end;
                end;
    Down

    Code:
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X,Blurp.Y+Blurp.Image.Height) then
                    begin
                      Blurp.testForWall(Blurp.X,Blurp.Y+4+Blurp.Image.Height);
                      Blurp.Y:=Blurp.Y+4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-4;
                    end;
                end;
    removed +4 otherwise it stopped 4 pixels sooner as before to the right and bottom, now it stops when it hits the wall and I can move in any other direction ... GREAT!

    Only thing is there are two bugs, which I'll look into tonight for some reason the following is possible :

    Attachment 557


    If I approach the tile from bellow, and hit it... keep pressing UP...and start moving to the
    left... the moment a small part of my character sprite is "free" it allows me to go up and
    down inside the wall ( I'm still happy tough, this is a better BUG atleast )
    Right side is not affected by this... if I find another wall sprite, and keep pressing top
    and try to go right...I can only go up once my character is completely free.


    Attachment 556

    Same here, if I approach a Wall sprite from left or right, and my Character is a bit Higher ... it can go trough...and move Left and Right... if I do the same with my character being lover then the Wall sprite it is not happening...

    Think this has something to do with only using X,Y maybe... anyway I'll play with it tonight.

    Attached is my modified "demo" thing.

    Thank you again for "spoon feeding" this to me, thank you VERY VERY much!!!
    Attachment 555

    Greetings
    Robert

  3. #13
    Hey Robert, have you looked at that tile game tutorial site I posted earlier? That might really help you get this all working

    Maybe this site can help?
    http://www.tonypa.pri.ee/tbw/tut05.html

    It is using action script (Flash) but I managed to folow the tutorials, especially "Hit the Wall" and "Jumping" to make a simple platform game with collision that worked quite well
    cheers,
    Paul
    Games:
    Seafox


    Pages:
    Syntax Error Software itch.io page

    Online Chess
    http://gameknot.com/#paul_nicholls

  4. #14
    Hey Robert, I have whipped up some code (NOT tested) based on that tutorial if you want to study it?

    Code:
    // based on tutorial here:
    // http://www.tonypa.pri.ee/tbw/tut05.html
    uses
      Math;
    
    const
      cTileW = 32; // tile width
      cTileH = 32; // tile height
    
      cMapW = 20;  // map width in tiles
      cMapH = 20;  // map height in tiles
    
    type
      TTile = record
        Id     : Integer; // tile Id - not applicaple in this exercise
        IsWall : Boolean; // True = wall, False = no wall
      end;
    
      TSprite = record
        w,h   : Integer; //half object width and height in pixels
        x,y   : Single;  //current location (centre of object)
        vx,vy : Single;  //current velocity in pixels/second
      end;
    
      TCorners = record
        Up     : Integer; // object's top edge map tile index
        Down   : Integer; // object's bottom edge map tile index
        Left   : Integer; // object's left edge map tile index
        Right  : Integer; // object's right edge map tile index
    
        WallUL : Boolean; // is or isn't a wall at object's top left corner
        WallUR : Boolean; // is or isn't a wall at object's top right corner
        WallDL : Boolean; // is or isn't a wall at object's bottom left corner
        WallDR : Boolean; // is or isn't a wall at object's bottom right corner
      end;
    
    var
      Map: array[0..cMapH - 1,0..cMapW - 1] of TTile;
    
    function  WallAt(x,y: Integer): Boolean;
    // tests for the presence of a wall at a tile location
    begin
      Result := True;
    
      if (x < 0) or (x >= cMapW) then Exit; // returns true if location is out of bounds (safety reasons, object can't pass out of bounds)
      if (y < 0) or (y >= cMapH) then Exit; // returns true if location is out of bounds (safety reasons, object can't pass out of bounds)
    
      Result := Map[x,y].IsWall;
    end;
    
    function  GetCorners(aSpr: TSprite): TCorners;
    // get object corners, includes velocity!
    begin
      // calculate tile index for each object corner
      Result.Left      := Math.Floor((aSpr.x - aSpr.w + aSpr.vx) / cTileW);
      Result.Right     := Math.Floor((aSpr.x + aSpr.w + aSpr.vx) / cTileW);
      Result.Up        := Math.Floor((aSpr.y - aSpr.h + aSpr.vy) / cTileH);
      Result.Down      := Math.Floor((aSpr.y + aSpr.h + aSpr.vy) / cTileH);
    
      // if true then there is a wall there
      Result.WallUL    := WallAt(Result.Left  ,Result.Up);
      Result.WallUR    := WallAt(Result.Right ,Result.Up);
      Result.WallDL    := WallAt(Result.Left  ,Result.Down);
      Result.WallDR    := WallAt(Result.Right ,Result.Down);
    end;
    
    procedure MoveSprite(var aSpr: TSprite; aTimeDelta: Single);
    var
      cnrs: TCorners;
    begin
      cnrs := GetCorners(aSpr);
    
      if aSpr.vy < 0 then
      // moving up
      begin
        if not cnrs.WallUL and not cnrs.WallUR then
        // not obstructed so move normally
          aSpr.y := aSpr.y + aSpr.vy * aTimeDelta
        else
        // hit tile so move to edge of tile and stop
        begin
          aSpr.vy := 0;
          aSpr.y  := cnrs.Up * cTileH + cTileH + aSpr.h;
        end;
      end
      else
      if aSpr.vy > 0 then
      // moving down
      begin
        if not cnrs.WallDL and not cnrs.WallDR then
        // not obstructed so move normally
          aSpr.y := aSpr.y + aSpr.vy * aTimeDelta
        else
        // hit tile so move to edge of tile and stop
        begin
          aSpr.vy := 0;
          aSpr.y  := cnrs.Down * cTileH - aSpr.h;
        end;
      end;
    
      cnrs := GetCorners(aSpr);
    
      if aSpr.vx < 0 then
      // moving left
      begin
        if not cnrs.WallUL and not cnrs.WallDL then
        // not obstructed so move normally
          aSpr.x := aSpr.x + aSpr.vx * aTimeDelta
        else
        // hit tile so move to edge of tile and stop
        begin
          aSpr.vx := 0;
          aSpr.x  := cnrs.Left * cTileW + cTileW + aSpr.w;
        end;
      end
      else
      if aSpr.vx > 0 then
      // moving right
      begin
        if not cnrs.WallUR and not cnrs.WallDR then
        // not obstructed so move normally
          aSpr.x := aSpr.x + aSpr.vx * aTimeDelta
        else
        // hit tile so move to edge of tile and stop
        begin
          aSpr.vx := 0;
          aSpr.x  := cnrs.Right * cTileW - aSpr.w;
        end;
      end;
    end;
    cheers,
    Paul
    Games:
    Seafox


    Pages:
    Syntax Error Software itch.io page

    Online Chess
    http://gameknot.com/#paul_nicholls

  5. #15
    Hello,

    thank you very much, I'll be doing some reading on that site you've posted the link to.

    Thank you for the code as well!

    Greetings
    Rob

  6. #16

    Paul's way...

    Hello,

    I've modified my program so that it now kinda does what Paul suggested...only a bit dumbed down...

    I wanted to ask something, cause I think this might be the root cause of my problem, something I don't understand and need to make clear.

    For example when my character hits a wall in any direction, I need to make him go back one pixel in the oposite direction ? in order to prevent it from being stuck ?

    Right now in my program where tiles are 64x64, character is 32x32, and movement in any direction is by 4 pixels always, when I hit the wall (perfect hit) I get stuck... for example I hit the wall from left... upleft and downleft is TRUE... I should be able to move up and down but I can't because for UP and DOWN I check upleft upright, and downleft downright, and one of em is always true... so do I need to move my character back 1 pixel when I colide with a wall? I'm not sure...cause on that Flash tutorial link, the character thing seems to hit the wall perfectly and yet it's able to move and hit the wall from left for example perfectly and yet is still able to move up and down along the wall.

    my code :

    Code:
    unit Main;
    interface
    uses
      Windows,Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AdDraws, AdClasses, AdTypes, AdPerformanceCounter, AdDevIL,AdSprites,Math;
      type
      //Types that are used to tell the character which key has been pressed
      TKey = (kyUp, kyDown, kyLeft, kyRight);
      TKeys = set of TKey;
      TTileInfo = Record
      iswall : boolean;
      end;
      TCorners = record
        Up     : Integer; // object's top edge map tile index
        Down   : Integer; // object's bottom edge map tile index
        Left   : Integer; // object's left edge map tile index
        Right  : Integer; // object's right edge map tile index
        WallUL : Boolean; // is or isn't a wall at object's top left corner
        WallUR : Boolean; // is or isn't a wall at object's top right corner
        WallDL : Boolean; // is or isn't a wall at object's bottom left corner
        WallDR : Boolean; // is or isn't a wall at object's bottom right corner
      end;
     
      TPlatform = class(TImageSprite)
        private
        protected
          procedure DoMove(TimeGap: Double); override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean); override;
        public
          constructor Create(AParent:TSprite);override;
        end;
      TBlurp = class(TImageSprite)
        private
        FKeys:TKeys;
        X_Direction:double;
        Y_Direction:double;
        isfalling:boolean;
        iswall:boolean;
        protected
          procedure DoMove(TimeGap: Double);override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean);override;
        public
          constructor Create(AParent:Tsprite);override;
          procedure SetKeys(Keys:TKeys);
        end;
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
      private
        { Private declarations }
      public
        { Public declarations }
        AdDraw:TAdDraw;
        AdSpriteEngine:TSpriteEngine;
        AdImageList:TAdImageList;
        AdPerCounter:TAdPerformanceCounter;
        AdPixelCollisionTester: TAdSpritePixelCollisionTester;
        Blurp:TBlurp;
        procedure Idle(Sender:TObject; var Done:boolean);
        procedure LoadLevel;
        function GetCorners(aSpr: TSprite): TCorners;
        function WallAt(x,y: Integer): Boolean;
      end;
    var
      Form1: TForm1;
      TileInfo : array [1..39, 0..28 ] of TTileInfo;
      ActTime : double;
      szam : integer;
    implementation
    {$R *.dfm}
    procedure TForm1.LoadLevel;
    var
      level:TStringList;
      ax,ay:integer;
    begin
      level := TStringList.Create;
      level.LoadFromFile(ExtractFilePath(Application.ExeName)+'level2.txt');
      for ay := 0 to level.Count-1  do
      begin
        for ax := 1 to length(level[ay]) do
        begin
          case level[ay][ax] of
            'x':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatform.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            'X':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatForm.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka2');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            '-': TileInfo[ax,ay].iswall:=false;
          end;
        end;
      end;
      level.Free;
    end;
    procedure TBlurp.SetKeys(Keys: TKeys);
    begin
      if Keys = FKeys then exit;
      FKeys := Keys;
      if kyRight in Keys then x_direction:=1.5;
      if kyLeft in Keys then x_direction:=-1.5;
      if kyUp in Keys then y_direction:=-1.5;
      if kyDown in Keys then y_direction:=1.5;
      if Keys = [] then
        begin
          x_direction:=0;
          y_direction:=0;
        end;
    end;
    
    constructor TPlatform.Create(AParent: TSprite);
    begin
      inherited;
    end;
    constructor TBlurp.Create(AParent: TSprite);
    begin
      inherited;
    end;
     
    procedure TBlurp.DoMove(TimeGap: Double);
    begin
      inherited;
    
     { X:=X+X_direction;
      Y:=Y+Y_direction; }
    
     { if X <= 0 then X:=0;
      if X > 640-Image.Width then X:=640-Image.Width;
      if Y < 0 then Y:=0;
      if Y > 480-Image.Height then Y:=480-Image.Height; }
      Collision;
    end;
    function TForm1.WallAt(x,y: Integer): Boolean;
    // tests for the presence of a wall at a tile location
    begin
      Result := True;
      Result := TileInfo[x,y].IsWall;
    end;
    function  TForm1.GetCorners(aSpr: TSprite): TCorners;
    // get object corners, includes velocity!
    begin
      // calculate tile index for each object corner
      Result.Left      := Math.Floor((aSpr.x -4) / 64);
      Result.Right     := Math.Floor((aSpr.x + aSpr.Width) / 64);
      Result.Up        := Math.Floor((aSpr.y -4) / 64);
      Result.Down      := Math.Floor((aSpr.y + aSpr.Height) / 64);
      // if true then there is a wall there
      Result.WallUL    := WallAt(Result.Left  ,Result.Up);
      Result.WallUR    := WallAt(Result.Right ,Result.Up);
      Result.WallDL    := WallAt(Result.Left  ,Result.Down);
      Result.WallDR    := WallAt(Result.Right ,Result.Down);
    end;
     
    
    procedure TPlatform.DoMove(TimeGap : Double);
    begin
      inherited;
      Collision;
    end;
    
    procedure TBlurp.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
      if Sprite is TPlatform then
        begin
          isFalling:=false;
        end;
    end;
    procedure TPlatform.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
    end;
     
    
    procedure TForm1.FormCreate(Sender: TObject);
    var i: integer;
    begin
      AdPerCounter := TAdPerformanceCounter.Create;
      AdDraw := TAdDraw.Create(self);
      AdDraw.DllName := 'AndorraDX93D.dll';
     with AdDraw.Display do
        begin
        {  Width := 640;
          Height := 480;
          BitDepth := ad16Bit; //The colour depth. The values "ad16Bit" and "ad32Bit" are allowed here.
          DisplayMode := dmFullscreen; }
        end;
    
    if AdDraw.Initialize then
      begin
        Application.OnIdle := Idle;
        AdImageList := TAdImageList.Create(AdDraw);
        AdImageList.LoadFromFile('BackGround.ail');
    
        //create the SpriteEngine
         AdSpriteEngine := TSpriteEngine.Create(nil);
         AdSpriteEngine.Surface := AdDraw;
        //Create the collision tester
        AdPixelCollisionTester := TAdSpritePixelCollisionTester.Create(AdDraw);
        LoadLevel;
        //create TImageSprite
        Randomize;
            Blurp := TBlurp.Create(AdSpriteEngine);
            with Blurp.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Hero');
                X := 128;
                Y := 128;
                Z := 0;
                CollisionTester := AdPixelCollisionTester;
                SetKeys([]);
                isfalling:=true;
              end;
     
    
        // ************* hater *********************************
      end
     else
      begin
         ShowMessage('Error while initializing Andorra 2D. Try to use another display'+
                   'mode or use another video adapter.');
        halt; //<-- Completely shuts down the application
      end;
    end;
    procedure TForm1.Idle(Sender: TObject; var Done: boolean);
    var keys: TKeys;
        cnrs: TCorners;
     begin
       if AdDraw.CanDraw then // Only continue, if drawing is possible
       begin
        AdPerCounter.Calculate;
        AdPerCounter.MaximumFrameRate:=60;
    
        AdDraw.ClearSurface(clBlack); // Fill the surface with black color
        AdDraw.BeginScene;
        // Here you need to perform all drawing operations later
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 25 then
        begin
             cnrs := GetCorners(Blurp);
             keys := [];
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  if not cnrs.WallUL and not cnrs.WallDL then
                    begin
                      Blurp.X:=Blurp.X-4;
                      AdSpriteEngine.X:=AdSpriteEngine.X+4;
                    end;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  if not cnrs.WallUR and not cnrs.WallDR then
                    begin
                      Blurp.X:=Blurp.X+4;
                      AdSpriteEngine.X:=AdSpriteEngine.X-4;
                    end;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                  if not cnrs.WallUL and not cnrs.WallUR then
                    begin
                      Blurp.y := Blurp.y - 4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y+4;
                    end;
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  if not cnrs.WallDL and not cnrs.WallDR then
                    begin
                      Blurp.Y:=Blurp.Y+4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-4;
                    end;
                end;
              Blurp.SetKeys(Keys);
          ActTime := 0;
        end;
       { if Blurp.isfalling = true then
          begin
            Blurp.Y:=Blurp.Y+1;
          end;
        Blurp.isfalling:=true;}
     
        AdSpriteEngine.Draw;
        AdSpriteEngine.Move(25/1000);
        AdSpriteEngine.Dead;
        // debug
        AdDraw.Canvas.Textout(0,40,'Up left:    '+booltostr(cnrs.WallUL,true));
           AdDraw.Canvas.Textout(0,60,'Up right:    '+booltostr(cnrs.WallUR,true));
               AdDraw.Canvas.Textout(0,80,'Bottom left:    '+booltostr(cnrs.WallDL,true));
                   AdDraw.Canvas.Textout(0,100,'Bottom right:    '+booltostr(cnrs.WallDR,true));
        AdDraw.Canvas.TextOut(0,120,'Tile Tipus:' +inttostr(szam));
     
     
        AdDraw.EndScene;
        AdDraw.Flip; // Draws you result on the screen. Otherwise, you would not see anything
       end;
      Done := false; // Important, otherwise the function will not be called in every loop
     end;
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
       AdSpriteEngine.Free;
       AdImageList.Free;
       AdPerCounter.Free;
       AdDraw.Free;
    end;
    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key = VK_ESCAPE then Close;
    end;
     
    end.
    and zipped is the entire project... egyszeru 6.zip

    greetings
    Rob

  7. #17
    The collision depends very much on how the player is allowed to move. For example if you would let player to move freely in 360 degrees you'd have a very different collision algorithm, than if player can only move vertically or horizontally.

    There is not 1 way to make collision but 1000 different. For example:
    1) Before movement, save character's full position in temp variable. If player collisions, simply copy the old position to current position.
    Problem: If tile width is 32 and player is allowed to move in odd steps of 3.0812 for example, then player will never actually touch the wall but collide little outside different on each wall. Solution, move player by number that is divisible to 32.

    2) For each 4 directions (up, down, left, right), if player is moving down and hits wall:
    - Move player backwards by as much as he moves per frame.
    or
    - Count where player should be when it is exactly outside of collision range. For example if player is moving right and hits left wall, then PlayerX := WallX-PlayerSprite.Width

  8. #18
    You have to do the collision test BEFORE actually moving the character - this is what the checking corners part of the code is all about; only if you can move in that direction (not blocked by wall), do you then move there - otherwise you move to the wall edge.

    I'm having trouble following your code a bit, but it seems you are moving then testing for collisions?

    procedure TBlurp.DoMove(TimeGap: Double);
    begin
    inherited;

    { X:=X+X_direction;
    Y:=Y+Y_direction; }

    { if X <= 0 then X:=0;
    if X > 640-Image.Width then X:=640-Image.Width;
    if Y < 0 then Y:=0;
    if Y > 480-Image.Height then Y:=480-Image.Height; }
    Collision;
    end;
    And why are you moving 4 pixels each time? Doesn't this mean you are not going to get frame-independent movement in your game?
    I would have thought you should move by your velocity (4 pixels?) times by the frame time (TimeGap)?

    cheers,
    Paul
    Games:
    Seafox


    Pages:
    Syntax Error Software itch.io page

    Online Chess
    http://gameknot.com/#paul_nicholls

  9. #19
    Hello,

    Erm...I think I'm doing the movement incorrectly... I've cleaned up my code a bit, I'm doing the movement in the IDLE loop of my Form... every
    Code:
         ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 25 then
    I've limited the max framerate to 60, and by pressing any of the direction keys I move the Player.X or Y position with +4 or -4 to any direction...

    If this is a really bad habit, do tell me, I'm still trying to learn understand... and there are parts I still don't get completely. Andorra 2d's Wormhunter demo control scheme was a bit overwhelming at first look.

    As you can see...I'm not doing the movement in the Sprite.OnMove procedure... (sorry... I've only used Andorra 2d for about two weeks... and that was not non-stop..., it a lot of fun, but sometimes a bit overwhelming, but not giving up...)

    Complete code :

    Code:
    unit Main;
    interface
    uses
      Windows,Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AdDraws, AdClasses, AdTypes, AdPerformanceCounter, AdDevIL,AdSprites,Math;
      type
      TTileInfo = Record
      iswall : boolean;
      end;
      TCorners = record
        Up     : Integer; // object's top edge map tile index
        Down   : Integer; // object's bottom edge map tile index
        Left   : Integer; // object's left edge map tile index
        Right  : Integer; // object's right edge map tile index
        WallUL : Boolean; // is or isn't a wall at object's top left corner
        WallUR : Boolean; // is or isn't a wall at object's top right corner
        WallDL : Boolean; // is or isn't a wall at object's bottom left corner
        WallDR : Boolean; // is or isn't a wall at object's bottom right corner
      end;
     
      TPlatform = class(TImageSprite)
        private
        protected
          procedure DoMove(TimeGap: Double); override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean); override;
        public
          constructor Create(AParent:TSprite);override;
        end;
      TBlurp = class(TImageSprite)
        private
        protected
          procedure DoMove(TimeGap: Double);override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean);override;
        public
          constructor Create(AParent:Tsprite);override;
        end;
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
      private
        { Private declarations }
      public
        { Public declarations }
        AdDraw:TAdDraw;
        AdSpriteEngine:TSpriteEngine;
        AdImageList:TAdImageList;
        AdPerCounter:TAdPerformanceCounter;
        AdPixelCollisionTester: TAdSpritePixelCollisionTester;
        Blurp:TBlurp;
        procedure Idle(Sender:TObject; var Done:boolean);
        procedure LoadLevel;
        function GetCorners(aSpr: TSprite): TCorners;
        function WallAt(x,y: Integer): Boolean;
      end;
    var
      Form1: TForm1;
      TileInfo : array [1..39, 0..28 ] of TTileInfo;
      ActTime : double;
      szam : integer;
    implementation
    {$R *.dfm}
    procedure TForm1.LoadLevel;
    var
      level:TStringList;
      ax,ay:integer;
    begin
      level := TStringList.Create;
      level.LoadFromFile(ExtractFilePath(Application.ExeName)+'level2.txt');
      for ay := 0 to level.Count-1  do
      begin
        for ax := 1 to length(level[ay]) do
        begin
          case level[ay][ax] of
            'x':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatform.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            'X':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatForm.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka2');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            '-': TileInfo[ax,ay].iswall:=false;
          end;
        end;
      end;
      level.Free;
    end;
    
    constructor TPlatform.Create(AParent: TSprite);
    begin
      inherited;
    end;
    constructor TBlurp.Create(AParent: TSprite);
    begin
      inherited;
    end;
     
    procedure TBlurp.DoMove(TimeGap: Double);
    begin
      inherited;
      Collision;
    end;
    function TForm1.WallAt(x,y: Integer): Boolean;
    // tests for the presence of a wall at a tile location
    begin
      Result := True;
      Result := TileInfo[x,y].IsWall;
    end;
    function  TForm1.GetCorners(aSpr: TSprite): TCorners;
    // get object corners, includes velocity!
    begin
      // calculate tile index for each object corner
      Result.Left      := Math.Floor((aSpr.x -4) / 64);
      Result.Right     := Math.Floor((aSpr.x + aSpr.Width) / 64);
      Result.Up        := Math.Floor((aSpr.y -4) / 64);
      Result.Down      := Math.Floor((aSpr.y + aSpr.Height) / 64);
      // if true then there is a wall there
      Result.WallUL    := WallAt(Result.Left  ,Result.Up);
      Result.WallUR    := WallAt(Result.Right ,Result.Up);
      Result.WallDL    := WallAt(Result.Left  ,Result.Down);
      Result.WallDR    := WallAt(Result.Right ,Result.Down);
    end;
     
    
    procedure TPlatform.DoMove(TimeGap : Double);
    begin
      inherited;
      Collision;
    end;
    
    procedure TBlurp.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
    end;
    procedure TPlatform.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
    end;
     
    
    procedure TForm1.FormCreate(Sender: TObject);
    var i: integer;
    begin
      AdPerCounter := TAdPerformanceCounter.Create;
      AdDraw := TAdDraw.Create(self);
      AdDraw.DllName := 'AndorraDX93D.dll';
    
    if AdDraw.Initialize then
      begin
        Application.OnIdle := Idle;
        AdImageList := TAdImageList.Create(AdDraw);
        AdImageList.LoadFromFile('BackGround.ail');
    
        //create the SpriteEngine
         AdSpriteEngine := TSpriteEngine.Create(nil);
         AdSpriteEngine.Surface := AdDraw;
        //Create the collision tester
        AdPixelCollisionTester := TAdSpritePixelCollisionTester.Create(AdDraw);
        LoadLevel;
        //create TImageSprite
        Randomize;
            Blurp := TBlurp.Create(AdSpriteEngine);
            with Blurp.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Hero');
                X := 128;
                Y := 128;
                Z := 0;
                CollisionTester := AdPixelCollisionTester;
              end;
     
    
        // ************* hater *********************************
      end
     else
      begin
         ShowMessage('Error while initializing Andorra 2D. Try to use another display'+
                   'mode or use another video adapter.');
        halt; //<-- Completely shuts down the application
      end;
    end;
    procedure TForm1.Idle(Sender: TObject; var Done: boolean);
    var cnrs: TCorners;
        szar: boolean;
     begin
       if AdDraw.CanDraw then // Only continue, if drawing is possible
       begin
        AdPerCounter.Calculate;
        AdPerCounter.MaximumFrameRate:=60;
    
        AdDraw.ClearSurface(clBlack); // Fill the surface with black color
        AdDraw.BeginScene;
        // Here you need to perform all drawing operations later
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 25 then
        begin
             cnrs := GetCorners(Blurp);
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  if not cnrs.WallUL and not cnrs.WallDL then
                    begin
                      Blurp.X:=Blurp.X-4;
                      AdSpriteEngine.X:=AdSpriteEngine.X+4;
                    end;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  if not cnrs.WallUR and not cnrs.WallDR then
                    begin
                      Blurp.X:=Blurp.X+4;
                      AdSpriteEngine.X:=AdSpriteEngine.X-4;
                    end;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                  if not cnrs.WallUL and not cnrs.WallUR then
                    begin
                      Blurp.y := Blurp.y - 4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y+4;
                    end;
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  if not cnrs.WallDL and not cnrs.WallDR then
                    begin
                      Blurp.Y:=Blurp.Y+4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-4;
                    end;
                end;
    
          ActTime := 0;
        end;
    
        AdSpriteEngine.Draw;
        AdSpriteEngine.Move(25/1000);
        AdSpriteEngine.Dead;
        // debug
        AdDraw.Canvas.Textout(0,40,'Up left:    '+booltostr(cnrs.WallUL,true));
           AdDraw.Canvas.Textout(0,60,'Up right:    '+booltostr(cnrs.WallUR,true));
               AdDraw.Canvas.Textout(0,80,'Bottom left:    '+booltostr(cnrs.WallDL,true));
                   AdDraw.Canvas.Textout(0,100,'Bottom right:    '+booltostr(cnrs.WallDR,true));
        AdDraw.Canvas.TextOut(0,120,'Tile Tipus:' +inttostr(szam));
     
     
        AdDraw.EndScene;
        AdDraw.Flip; // Draws you result on the screen. Otherwise, you would not see anything
       end;
      Done := false; // Important, otherwise the function will not be called in every loop
     end;
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
       AdSpriteEngine.Free;
       AdImageList.Free;
       AdPerCounter.Free;
       AdDraw.Free;
    end;
    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key = VK_ESCAPE then Close;
    end;
     
    end.

  10. #20
    Can't sleep

    Changed my code...I think this is a bit more proper.... now I'm using the OnMove procedure.... it's a bit buggy ...cause it still stops a bit sooner then it should...and I'm stuck as well.... but I think this is the proper way to move my character...

    Code:
    unit Main;
    interface
    uses
      Windows,Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AdDraws, AdClasses, AdTypes, AdPerformanceCounter, AdDevIL,AdSprites,Math;
      type
      TTileInfo = Record
      iswall : boolean;
      end;
      TCorners = record
        Up     : Integer; // object's top edge map tile index
        Down   : Integer; // object's bottom edge map tile index
        Left   : Integer; // object's left edge map tile index
        Right  : Integer; // object's right edge map tile index
        WallUL : Boolean; // is or isn't a wall at object's top left corner
        WallUR : Boolean; // is or isn't a wall at object's top right corner
        WallDL : Boolean; // is or isn't a wall at object's bottom left corner
        WallDR : Boolean; // is or isn't a wall at object's bottom right corner
      end;
     
      TPlatform = class(TImageSprite)
        private
        protected
          procedure DoMove(TimeGap: Double); override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean); override;
        public
          constructor Create(AParent:TSprite);override;
        end;
      TBlurp = class(TImageSprite)
        private
        vx,vy : Single;  //current velocity in pixels/second
        protected
          procedure DoMove(TimeGap: Double);override;
          procedure DoCollision(Sprite:TSprite; var Done:boolean);override;
        public
          constructor Create(AParent:Tsprite);override;
        end;
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
      private
        { Private declarations }
      public
        { Public declarations }
        AdDraw:TAdDraw;
        AdSpriteEngine:TSpriteEngine;
        AdImageList:TAdImageList;
        AdPerCounter:TAdPerformanceCounter;
        AdPixelCollisionTester: TAdSpritePixelCollisionTester;
        Blurp:TBlurp;
        procedure Idle(Sender:TObject; var Done:boolean);
        procedure LoadLevel;
        function GetCorners(aSpr: TSprite): TCorners;
        function WallAt(x,y: Integer): Boolean;
      end;
    var
      Form1: TForm1;
      TileInfo : array [1..39, 0..28 ] of TTileInfo;
      ActTime : double;
      szam : integer;
    implementation
    {$R *.dfm}
    procedure TForm1.LoadLevel;
    var
      level:TStringList;
      ax,ay:integer;
    begin
      level := TStringList.Create;
      level.LoadFromFile(ExtractFilePath(Application.ExeName)+'level2.txt');
      for ay := 0 to level.Count-1  do
      begin
        for ax := 1 to length(level[ay]) do
        begin
          case level[ay][ax] of
            'x':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatform.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            'X':
            begin
              TileInfo[ax,ay].iswall:=true;
              with TPlatForm.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Kocka2');
                x := ax*64;
                y := ay*64;
                z := 0;
              end;
            end;
            '-': TileInfo[ax,ay].iswall:=false;
          end;
        end;
      end;
      level.Free;
    end;
    
    constructor TPlatform.Create(AParent: TSprite);
    begin
      inherited;
    end;
    constructor TBlurp.Create(AParent: TSprite);
    begin
      inherited;
    end;
     
    procedure TBlurp.DoMove(TimeGap: Double);
    var
      cnrs: TCorners;
    begin
      inherited;
      cnrs := Form1.GetCorners(self);
      if vy < 0 then
      // moving up
      begin
        if not cnrs.WallUL and not cnrs.WallUR then
        // not obstructed so move normally
          y := y + vy * TimeGap
        else
        // hit tile so move to edge of tile and stop
        begin
          vy := 0;
         // y  := cnrs.Up * 64 + 64 {+ Height};
        end;
      end
      else
      if vy > 0 then
      // moving down
      begin
        if not cnrs.WallDL and not cnrs.WallDR then
        // not obstructed so move normally
          y := y + vy * TimeGap
        else
        // hit tile so move to edge of tile and stop
        begin
          vy := 0;
        //  y  := cnrs.Down * 64 - Height;
        end;
      end;
      cnrs := Form1.GetCorners(self);
     if vx < 0 then
      // moving left
      begin
        if not cnrs.WallUL and not cnrs.WallDL then
        // not obstructed so move normally
          x := x + vx * TimeGap
        else
        // hit tile so move to edge of tile and stop
        begin
          vx := 0;
       //   x  := cnrs.Left * 64 + 64 + Width;
        end;
      end
      else
      if vx > 0 then
      // moving right
      begin
        if not cnrs.WallUR and not cnrs.WallDR then
        // not obstructed so move normally
          x := x + vx * TimeGap
        else
        // hit tile so move to edge of tile and stop
        begin
          vx := 0;
         // x  := cnrs.Right * 64 - Width;
        end;
      end;
     
    
    //  Collision;
    end;
    function TForm1.WallAt(x,y: Integer): Boolean;
    // tests for the presence of a wall at a tile location
    begin
      Result := True;
      Result := TileInfo[x,y].IsWall;
    end;
    function  TForm1.GetCorners(aSpr: TSprite): TCorners;
    // get object corners, includes velocity!
    begin
      // calculate tile index for each object corner
      Result.Left      := Math.Floor((aSpr.x -4) / 64);
      Result.Right     := Math.Floor((aSpr.x + aSpr.Width) / 64);
      Result.Up        := Math.Floor((aSpr.y -4) / 64);
      Result.Down      := Math.Floor((aSpr.y + aSpr.Height) / 64);
      // if true then there is a wall there
      Result.WallUL    := WallAt(Result.Left  ,Result.Up);
      Result.WallUR    := WallAt(Result.Right ,Result.Up);
      Result.WallDL    := WallAt(Result.Left  ,Result.Down);
      Result.WallDR    := WallAt(Result.Right ,Result.Down);
    end;
     
    
    procedure TPlatform.DoMove(TimeGap : Double);
    begin
      inherited;
      Collision;
    end;
    
    procedure TBlurp.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
    end;
    procedure TPlatform.DoCollision(Sprite:TSprite; var Done:boolean);
    begin
    end;
     
    
    procedure TForm1.FormCreate(Sender: TObject);
    var i: integer;
    begin
      AdPerCounter := TAdPerformanceCounter.Create;
      AdDraw := TAdDraw.Create(self);
      AdDraw.DllName := 'AndorraDX93D.dll';
    
    if AdDraw.Initialize then
      begin
        Application.OnIdle := Idle;
        AdImageList := TAdImageList.Create(AdDraw);
        AdImageList.LoadFromFile('BackGround.ail');
    
        //create the SpriteEngine
         AdSpriteEngine := TSpriteEngine.Create(nil);
         AdSpriteEngine.Surface := AdDraw;
        //Create the collision tester
        AdPixelCollisionTester := TAdSpritePixelCollisionTester.Create(AdDraw);
        LoadLevel;
        //create TImageSprite
        Randomize;
            Blurp := TBlurp.Create(AdSpriteEngine);
            with Blurp.Create(AdSpriteEngine) do
              begin
                Image := AdImageList.Find('Hero');
                X := 128;
                Y := 128;
                Z := 0;
                CollisionTester := AdPixelCollisionTester;
              end;
     
    
        // ************* hater *********************************
      end
     else
      begin
         ShowMessage('Error while initializing Andorra 2D. Try to use another display'+
                   'mode or use another video adapter.');
        halt; //<-- Completely shuts down the application
      end;
    end;
    procedure TForm1.Idle(Sender: TObject; var Done: boolean);
    var cnrs: TCorners;
        szar: boolean;
     begin
       if AdDraw.CanDraw then // Only continue, if drawing is possible
       begin
        AdPerCounter.Calculate;
        AdPerCounter.MaximumFrameRate:=60;
    
        AdDraw.ClearSurface(clBlack); // Fill the surface with black color
        AdDraw.BeginScene;
        // Here you need to perform all drawing operations later
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 100 then
        begin
              Blurp.vx:=0;
              Blurp.vy:=0;
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  Blurp.vx:=-14;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  Blurp.vx:=+14;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                  Blurp.vy:=-14
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  Blurp.vy:=14
                end;
    
          ActTime := 0;
        end;
    
        AdSpriteEngine.Draw;
        AdSpriteEngine.Move(25/1000);
        AdSpriteEngine.Dead;
        // debug
        cnrs:=GetCorners(Blurp);
        AdDraw.Canvas.Textout(0,40,'Up left:    '+booltostr(cnrs.WallUL,true));
           AdDraw.Canvas.Textout(0,60,'Up right:    '+booltostr(cnrs.WallUR,true));
               AdDraw.Canvas.Textout(0,80,'Bottom left:    '+booltostr(cnrs.WallDL,true));
                   AdDraw.Canvas.Textout(0,100,'Bottom right:    '+booltostr(cnrs.WallDR,true));
        AdDraw.Canvas.TextOut(0,120,'Tile Tipus:' +inttostr(szam));
     
     
        AdDraw.EndScene;
        AdDraw.Flip; // Draws you result on the screen. Otherwise, you would not see anything
       end;
      Done := false; // Important, otherwise the function will not be called in every loop
     end;
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
       AdSpriteEngine.Free;
       AdImageList.Free;
       AdPerCounter.Free;
       AdDraw.Free;
    end;
    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key = VK_ESCAPE then Close;
    end;
     
    end.

Page 2 of 4 FirstFirst 1234 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
  •