Hello,

I'm just trying out multiple ways to do the same thing...at first this seemed unbelievable simple should it work, my original idea was this (this you will understand ... better) :

I'm moving my character on the onMOVE with vx, vy (velocity), then testing for Collision, if my character collides with TPlatForm... then I check if he was going up down left or right... and according to that I set my character position to be positioned next to wall , like this :
if my character is going up, and he hits the TPlatform right above I do the following , Y:=TPlatForm(Sprite).Y+TPlatForm(Sprite).Height; set my character's Y coordinate to
TPlatForm(Sprite) -> this is the Sprite I've hit Y+ it's Height, so I'm right bellow it, no empty space... no need to check speed or whatever since it's not possible to get inside it this way.

Anyway when I've tried this out I was amazed that it worked, and that it's such a simple solution ... the problem came when I was trying to do the following :
Pressed up to hit the wall... then I've kept pressing up... and then tried to move left and right along the upper part... my character was moving incorrectly (at very high speed)... so I've tried the following to make it good, if I hit upper or lover sprite I've set vx:=0, if I've hit left or right I've set vy:=0, now this fixed my problem or so I thought... when I've hit the sprite above me or bellow and kept pressing up or down and at the same time left and right I was moving along the wall nicely... but if there was some obstacle next to me and I've reached it... my character "magicaly" transported itself right in top of it or bellow, since the code was always placing my character just bellow or above a sprite should it collide.
error.jpg

In this case I was pressing up Constantly and right as well, I was moving fine allong the wall , until I've reached the corner... there what happened was my Characters Y position was updated to the Y position of the sprite I've hit from RIGHT side.

Code:
 unit Main;
interface
uses
  Windows,Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AdDraws, AdClasses, AdTypes, AdPerformanceCounter, AdDevIL,AdSprites,Math;
  const
  TileW = 32; // tile width
  TileH = 32; // tile height
  PlayerH = 60; // Player Height
  PlayerW = 30; // Player Width
  type
  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;
  end;
var
  Form1: TForm1;
  ActTime : double;
  // camera positions
  camera_x : double;
  camera_y : double;

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
          with TPlatform.Create(AdSpriteEngine) do
          begin
            Image := AdImageList.Find('WALL');
            x := ax*TileW;
            y := ay*TileH;
            z := 0;
          end;
        end;
        'X':
        begin
          with TPlatForm.Create(AdSpriteEngine) do
          begin
            Image := AdImageList.Find('WALL');
            x := ax*TileW;
            y := ay*TileH;
            z := 0;
          end;
        end;
      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;
  // setting the camera to follow our HERO
  if (X > 320) and (X < (40*TileW)-320-TileW) then
    begin
      // - 64 , because when loading the level my entire background is starting from 64 instead of 0
      // looks better if there is no black line at the edge of the level...
      camera_x:=(X*-1)+320-TileW;
    end;
  if (Y > 240) and (Y < (29*TileH)-240) then
    begin
      // 29 tiles down * 64 tile.height -240 half of the screen, only moving when at center of the screen
      // well not really the center...but close anyway :)
      camera_y:=(Y*-1)+240;
    end;

  if vy < 0 then
  // moving up
  begin
    // not obstructed so move normally
      y := y + vy * TimeGap
  end;
  if vy > 0 then
  // moving down
  begin
      y := y + vy * TimeGap
  end;
 if vx < 0 then
  // moving left
  begin
      x := x + vx * TimeGap
  end;
  if vx > 0 then
  // moving right
  begin
      x := x + vx * TimeGap
  end;
 

  Collision;
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
      //up
      if vy < 0 then
        begin
          Y:=TPlatForm(Sprite).Y+TPlatForm(Sprite).Height;
        end;
      // down
      if vy > 0 then
        begin
          Y:=TPlatForm(Sprite).Y-Height;
        end;
      // left
      if vx < 0 then
        begin
          X:=TPlatForm(Sprite).X+TPlatForm(Sprite).Width;
        end;
      // right
      if vx > 0 then
        begin
          X:=TPlatForm(Sprite).X-Width;        
        end;
    end;
end;
procedure TPlatform.DoCollision(Sprite:TSprite; var Done:boolean);
begin
end;
 

procedure TForm1.FormCreate(Sender: TObject);
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('TallHero2');
            X := 144;
            Y := 144;
            Z := 0;
            CollisionTester := AdPixelCollisionTester;
          end;
 
    // The Entire Engine is moved left by -64 , this is because of the Level Loader ...
    Camera_X:=-TileW;
    Camera_Y:=0;
    AdSpriteEngine.X:=camera_x;
    AdSpriteEngine.Y:=camera_y;

    // ************* 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);
 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 > 10 then
    begin
          Blurp.vx:=0;
          Blurp.vy:=0;
          if GetKeyState(VK_LEFT) < 0 then
            begin
              Blurp.vx:=-123;
            end;
          if GetKeyState(VK_RIGHT) < 0 then
            begin
              Blurp.vx:=+123;
            end;
          if GetKeyState(VK_UP) < 0 then
            begin
              Blurp.vy:=-123
            end;
          if GetKeyState(VK_DOWN) < 0 then
            begin
              Blurp.vy:=123
            end;

      AdSpriteEngine.X:=camera_x;
      AdSpriteEngine.Y:=camera_y;
      ActTime := 0;
    end;

    AdSpriteEngine.Draw;
    AdSpriteEngine.Move(AdPerCounter.TimeGap/1000);
    AdSpriteEngine.Dead;
    // debug
 

    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.
Attached the code so you can see it in work :
test.zip


Greetings
Rob

ps.: in the next post I'll try and explain what my newer improved code does...and the parts I don't understand...