Page 3 of 4 FirstFirst 1234 LastLast
Results 21 to 30 of 31

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

  1. #21
    I just noticed here:

    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);
    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 - 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);
    Each sprite corner is the position (x or y) added to the sprite's half width or height (see ascii art):

    Code:
    TL      up     TR
     *       |      *
             |-h
    Left     |       Right
     --------*-------
        -w   |     +w
             |+h
             |
     *     down     *
    BL             BR
    This then needs to have the velocity added onto it so the correct tile index is being calculated for the new position being moved to

    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

  2. #22
    There is also this tutorial which uses the object corners and tile indices too
    http://www.metanetsoftware.com/technique/tutorialB.html

    cheers,
    Paul

  3. #23
    Hello

    I'm manipulating the vx and vy on TForm1.OnIDLE like this :


    Code:
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 100 then
        begin
              Blurp.vx:=0;
              Blurp.vy:=0;
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  Blurp.vx:=-16;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                  Blurp.vx:=+16;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                  Blurp.vy:=-16
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                  Blurp.vy:=16
                end;
    
          ActTime := 0;
        end;
    The DoMOVE procedure for the Character object...

    Code:
    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 * cTileH + cTileH + 16;
        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 * cTileH - 16;
        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 * cTileW + cTileW + 16;
        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 * cTileW - 16;
        end;
      end;
     
    
    //  Collision;
    end;
    I've also modified the code for getCorners, for some reason I did not notice HALF heihgt and HALF width, since my character is 32x32, I'm using 16 here. This part now should be ok, thanks to your ASCII art now I understand this part...

    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 -16 + Blurp.vx) / cTileW);
      Result.Right     := Math.Floor((aSpr.x + 16 + Blurp.vx) / cTileW);
      Result.Up        := Math.Floor((aSpr.y -16 + Blurp.vy) / cTileH);
      Result.Down      := Math.Floor((aSpr.y + 16 + Blurp.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;
    Problem : stops a bit further then it should LEFT and TOP, and to late RIGHT and BOTTOM, it's like the calulation is OK but Offset.

    During testing I've commented out the lines that "should" put my character right beside the wall if there is a hit... because that to is working in an unexpected way.

    Attached is my latest source code, meanwhile I'll play with it... hopefully I'm manipulating the vx and vy in a correct way.

    test.zip

    Greetings
    Rob

  4. #24
    I DID IT !!!!

    Without your help i wouldn't get this far this soon... but it still feels kinda good

    Code:
       Result.Left      := Math.Floor((x +(Image.Width/2) + vx) / cTileW);
      Result.Right     := Math.Floor((x + (Image.Width/2) + vx) / cTileW);
      Result.Up        := Math.Floor((y + (Image.Height/2) + vy) / cTileH);
      Result.Down      := Math.Floor((y + (Image.Height/2) + vy) / cTileH);
    for some reason, and I will need to figure it out why... Left and UP works if instead of - I do + Image.Widht/2 and + Image.Height/2

    Now I can go to the wall everywhere...there is one small bug... with any direction if I have a single WALL in center or anywhere...where I can move around it...
    my character can anter this WALL from LEFT or RIGHT if my character is HIGHER or LOWER then this WALL by more then my Characters own Height/2.

    C is character points , X is wall... can move inside wall... but only if I touch it like that... UP DOWN, LEFT and RIGHT works...
    Code:
       CC
       CCXX
        XXX
       CCXX
       CC



    Same thing happens for UP and DOWN... my Character can enter the WALL from UP and DOWN if it's LEFT or RIGHT side is free by more then its Width/2.
    (hopefully I've managed to write this down and someone understand's this... my english might be bad)

    Regarding the vx and vy ... I've studied a few demos..samples... I know it works...now, but was wondering if I'm doing this the right way, the way it was meant to be done in Andorra 2d (or if this is not specific to just this engine... then any other engine).

    Damn... was to soon to say... It seems if I change...vx or vy to other value... it does not work correctly...guess this only works cause I made a "lucky" bug

    Greetings
    Robert
    Last edited by robert83; 18-08-2011 at 03:33 PM. Reason: is vx and vy set correctly?

  5. #25
    You cannot simply change + and - anywhere when you like. Does it look logical? For that case Left and Up must be - . You can see this by looking at what the function returns. It returns the area where sprite is. If both were + it would result a simple dot that is located in down right corner of sprite, for + and - it is a rectangle all around player sprite what was wanted. So bugs are still elsewhere.

    Also, you are using vx and vy varibles in GetCorners() function without multiplying it with TimeGap.

  6. #26
    Quote Originally Posted by robert83 View Post
    I DID IT !!!!

    Without your help i wouldn't get this far this soon... but it still feels kinda good

    Code:
       Result.Left      := Math.Floor((x +(Image.Width/2) + vx) / cTileW);
      Result.Right     := Math.Floor((x + (Image.Width/2) + vx) / cTileW);
      Result.Up        := Math.Floor((y + (Image.Height/2) + vy) / cTileH);
      Result.Down      := Math.Floor((y + (Image.Height/2) + vy) / cTileH);
    for some reason, and I will need to figure it out why... Left and UP works if instead of - I do + Image.Widht/2 and + Image.Height/2
    That's great news

    I realised I forgot to mention these facts which are kind of crucial

    With the code I gave you, the world coordinate system I was working has the origin at the top left of the screen, so:

    left = -movement
    right = +movement
    up = -movement
    down = +movement

    so you need to match the +/- with your Adorra 2d screen coordinate system.

    Since you said left and up now seem to work using + instead of - as in my example then I would guess you need to use this now:

    Code:
       Result.Left      := Math.Floor((x +(Image.Width/2) + vx) / cTileW);
      Result.Right     := Math.Floor((x - (Image.Width/2) + vx) / cTileW);
      Result.Up        := Math.Floor((y + (Image.Height/2) + vy) / cTileH);
      Result.Down      := Math.Floor((y - (Image.Height/2) + vy) / cTileH);
    does this change things?

    cheers,
    Paul

  7. #27
    Hello,

    Thank you Paul for the suggestion... I guess in my confusion I confused you as well sorry... Andorra 2d also top left origin... anyway I was banging my head against the wall the whole day (probably overcomplicating something that is not that complex...) . I've decided I give a try to what Traveler said before... to include direction in my testforwall function. And this time (kinda like a wonder) it really works :

    TestWall function
    Code:
    function TBlurp.testForWall(spriteXpos,spriteYpos:single;spriteWidth,spriteHeight:integer;direction:string):boolean;
    begin
      testForWall := false;
      if direction = 'left' then
        begin
          if not (TileInfo[round(spriteXpos) div 64, round(spriteYpos) div 64].tilenr in [2]) or not
          (TileInfo[round(spriteXpos)div 64, (round(spriteYpos)+spriteHeight) div 64].tilenr in [2]) then testForWall := true;
        end;
      if direction = 'right' then
        begin
          if not(TileInfo[(round(spriteXpos)+spriteWidth) div 64, round(spriteYpos) div 64].tilenr in [2]) or not
          (TileInfo[(round(spriteXpos)+spriteWidth) div 64, (round(spriteYpos)+spriteHeight) div 64].tilenr in [2]) then testForWall :=true;
        end;
      if direction = 'up' then
        begin
          if not (TileInfo[round(spriteXpos) div 64, round(spriteYpos) div 64].tilenr in [2]) or not
          (TileInfo[(round(spriteXpos)+spriteWidth) div 64, round(spriteYpos) div 64].tilenr in [2]) then testForWall :=true;
        end;
      if direction = 'down' then
        begin
          if not (TileInfo[round(spriteXpos)div 64, (round(spriteYpos)+spriteHeight) div 64].tilenr in [2]) or not
          (TileInfo[(round(spriteXpos)+spriteWidth) div 64, (round(spriteYpos)+spriteHeight) div 64].tilenr in [2]) then testForWall :=true;
        end;
    end;
    controlling of character
    Code:
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 25 then
        begin
              if GetKeyState(VK_LEFT) < 0 then
                begin
                  if not Blurp.testForWall(Blurp.X-4,Blurp.Y,Blurp.Image.Width,Blurp.Image.Height-1,'left') 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,Blurp.Y,Blurp.Image.Width,Blurp.Image.Height-1,'right') 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,Blurp.Image.Width-1,Blurp.Image.Height,'up') 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,Blurp.Image.Width-1,Blurp.Image.Height,'down') then
                    begin
                      Blurp.Y:=Blurp.Y+4;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-4;
                    end;
                end;
          ActTime := 0;
        end;
    Right now I'm doing the movement onIdle of TFORM ... which means I'm not using TimeGap for movement... which is bad I know, I just wanted to make it real simple for now (so that I can sleep well, that atleast I've acomplished half of what I wanted).... tomorrow I'll modify my code so that the movement is done in the Sprites.OnMove , and I only give x or y velocity here...

    Anyway I've attached my code with the compiled executable, if I may ask you to please test it, it works. And I'm hoping it works just as well as the one you've suggested. (multiple solutions for the same problem).

    egyszeru 7 5-os maskepp.zip

    Greetings
    Rob

  8. #28
    It works for me just fine (after I downloaded the missing directx dll (d3dx9_33.dll)...the last version I tried needed the d3dx9_31.dll version for some reason?

    I was thinking...if go for the opengl version dll for Andorra 2d, then your game (when finished) could be cross-platform...just a thought, and my $0.02

    cheers,
    Paul

  9. #29

    Movement using the DoMove (not really a question) comments welcome if this is wrong

    Hi,

    I was playing a bit further with my program, and modified so I do the movement in the SpriteEngine.DoMove procedure , and it works fine regardles if velocity is 80, 95, or whatever... what I modified compared to my older source is :

    TForm1.OnIDLE

    Here is one obvious problem, which I did not even tried to solve... for now, somehow my Figure moves faster then the
    screen is scroll. ( I was hoping the speed would be the same...but there is a slight difference... will play with it later... was not
    the object here to solve that ... but rather to implement the movement more properly)

    Code:
        ActTime := ActTime + AdPerCounter.TimeGap;
        if ActTime > 25 then
        begin
          Blurp.vx:=0;
          Blurp.vy:=0;
              if GetKeyState(VK_LEFT) < 0 then
                begin
                      Blurp.vx:=-95;
                      AdSpriteEngine.X:=AdSpriteEngine.X-Blurp.vx*(AdPerCounter.TimeGap/1000);
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                      Blurp.vx:=95;
                      AdSpriteEngine.X:=AdSpriteEngine.X-Blurp.vx*(AdPerCounter.TimeGap/1000);
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                      Blurp.vy:=-95;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-Blurp.vy*(AdPerCounter.TimeGap/1000);
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                      Blurp.vy:=95;
                      AdSpriteEngine.Y:=AdSpriteEngine.Y-Blurp.vy*(AdPerCounter.TimeGap/1000);
                end;
          ActTime := 0;
        end;
    Here Is my modified DoMove , for now works great, been playing with it , using different velocity... always stops where it should yippeee

    Code:
    procedure TBlurp.DoMove(TimeGap: Double);
    begin
      inherited;
      // left
      if vx < 0 then
        begin
          if not testForWall(X+vx*TimeGap,Y,Image.Width,Image.Height-1,'left') then
            begin
              X:=X+round(vx*TimeGap) ;
            end;
        end;
      // right
      if vx > 0 then
        begin
         if not testForWall(X,Y,Image.Width,Image.Height-1,'right') then
           begin
             X:=X+round(vx*TimeGap);
           end;
        end;
      // up
      if vy < 0 then
        begin
          if not testForWall(X,Y+vy*TimeGap,Image.Width-1,Image.Height,'up') then
            begin
              Y:=Y+round(vy*TimeGap);
            end;
        end;
      // down
      if vy > 0 then
        begin
          if not testForWall(X,Y,Image.Width-1,Image.Height,'down') then
            begin
              Y:=Y+round(vy*TimeGap);
            end;
        end;
    
      Collision;
    end;
    Also one unexpected sidefect is ... before it was important where my Start position for my character was... now it's not , X can be 128,139,131 ... it works the same.

    Anyway I'll continue now with implementing gravity And checking the scrolling part.

    Greetings
    Rob

  10. #30

    Scrolling works now , ... and unfortunatelly gotta go get some sleep... :(

    Code:
        if ActTime > 10 then
        begin
          Blurp.vx:=0;
          Blurp.vy:=0;
              if GetKeyState(VK_LEFT) < 0 then
                begin
                      Blurp.vx:=-80;
                      if (Blurp.X > 320) and (Blurp.X < (40*64)-320) then
                        begin
                          AdSpriteEngine.X:=(Blurp.X*-1)+320;
                        end;
                end;
              if GetKeyState(VK_RIGHT) < 0 then
                begin
                      Blurp.vx:=80;
                      if (Blurp.X > 320) and (Blurp.X < (40*64)-320) then
                        begin
                          AdSpriteEngine.X:=(Blurp.X*-1)+320;
                        end;
                end;
              if GetKeyState(VK_UP) < 0 then
                begin
                      Blurp.vy:=-80;
                      if (Blurp.Y > 240) and (Blurp.Y < (29*64)-240) then
                        begin
                          AdSpriteEngine.Y:=(Blurp.Y*-1)+240;
                        end;
                end;
              if GetKeyState(VK_DOWN) < 0 then
                begin
                      Blurp.vy:=80;
                      if (Blurp.Y > 240) and (Blurp.Y < (29*64)-240) then
                        begin
                          AdSpriteEngine.Y:=(Blurp.Y*-1)+240;
                        end;
                end;
          ActTime := 0;
        end;
    Due to the fact that I use 60 FPS limit... had to decrease ACT TIME to 10... I don't know what to call this effect but when ACT TIME was 60... the screen was moving... I dunnot a bit erm... tear effect ... the outer lines of my character seemed to be jumping in and out of the character when it was redrawn...

    Anyway now it works great , and was pretty simple to do to. Only thing, gravity...tomorrow.

    Greetings
    Rob

    ps. : once I'm finished with my experiments...I'll use const and more variables instead of manually putting in numbers....
    Last edited by robert83; 21-08-2011 at 12:56 AM. Reason: changed source

Page 3 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
  •