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
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
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 :
and zipped is the entire project... egyszeru 6.zipCode: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.
greetings
Rob
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
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?
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?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;
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
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
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...Code:ActTime := ActTime + AdPerCounter.TimeGap; if ActTime > 25 then
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.
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.
I just noticed here:
this seems incorrect...I think it should be this:Code: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);
Each sprite corner is the position (x or y) added to the sprite's half width or height (see ascii art):Code: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 - 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);
This then needs to have the velocity added onto it so the correct tile index is being calculated for the new position being moved toCode:TL up TR * | * |-h Left | Right --------*------- -w | +w |+h | * down * BL BR
Does this make it any clearer?
Oh, also I can't see where you are setting the sprite's vx an vy properties in the code?
Note: I think you should use constants or similar for the tile width and height so it is all the same throughout the code and only needs to be changed once
PS. Maybe I will download Adorra so I can try fixing the code myself if you are still having troubles
Good luck
cheers.
Paul
Games:
Seafox
Pages:
Syntax Error Software
itch.io page
Online Chess
http://gameknot.com/#paul_nicholls
Bookmarks