Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: snapping sprite to tilemap

  1. #1

    snapping sprite to tilemap

    hi everybody,
    i'm new here, so go easy on me
    so the thing is, that i'm trying to create a game like zelda, but much simplier. i'm using an engine(made from Traveler's tutorial) which uses bmps to tile my map, and now i want the sprite to snap to each tile.
    i know it's easy, but it's new to me, so i'm stuck

    best regards, leniz

  2. #2
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    snapping sprite to tilemap

    Hi leniz, welcome to PGD!

    Well if you want to have a defined grid which the player will stick to you could change the X/Y value which he is not being moved in.

    ie.

    [pascal]if (Player.Moving = movingLeft) or (Player.Moving = movingRight) then
    Player.Y := FindClosestY(Player.X, Player.Y);[/pascal]

    FindClosestY would be a function that finds what the closest grid position the character is most closest to and returns it's value.

    I'll assume that you've already figured out how to draw the tiles properly. So remember how you had to multiply by the tilesize to get it to display on the spot you wanted? Well now you have to divide by that same size to convert from the character's real location to the grid location.

    The best way to do this is to create functions that will figure out what the real location is in the grid.

    Here are the functions that I use in Subject 33...

    [pascal]{Convert Location on Screen to Game Position}
    function XPos(X: Integer): Integer;
    begin
    XPos := Round(X / Game_TileSize - 0.4444);
    end;
    function YPos(Y: Integer): Integer;
    begin
    YPos := Round(Y / Game_TileSize - 0.4444);
    end;

    {Convert Game Position to Actual Screen Location}
    function XLoc(X: Integer): Integer;
    begin
    XLoc := X * Game_TileSize;
    end;
    function YLoc(Y: Integer): Integer;
    begin
    YLoc := Y * Game_TileSize;
    end;
    [/pascal]

    Game Position is what I've been calling the 'grid' location. Actual Screen Location is only actual if you don't scroll your map, otherwise think of it as the real map location instead. Same concept though.


    [size=9px]Seeing as this topic is more about game design in general, I'll move this thread to the General forum.[/size]
    Jason McMillen
    Pascal Game Development
    Co-Founder





  3. #3

    snapping sprite to tilemap

    This idea crossed my mind when I was writing the first post, but I'm embarassed to admit that I have no clue how to write the "FindClosestY/X" function ops:

  4. #4
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    snapping sprite to tilemap

    Just use XPos and YPos to find your grid location from actual location. Then use XLoc and YLoc on that returned value to do the actual 'snapping'.

    Think of it like rounding a decimal value.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  5. #5

    snapping sprite to tilemap

    Here is a simple sample:[pascal]function FindClosestY(WorldY : Real) : Integer;
    begin
    result := WorldY div TileHeight;
    result := result * TileHeight;
    end;

    function FindClosestX(WorldX : Real) : Integer;
    begin
    result := WorldX div TileWidth;
    result := result * TileWidth;
    end;

    function FindWorldTile(WorldPosition : TPoint) : TPoint;
    begin
    result.X := WorldPosition.X div TileWidth;
    result.X := result.X * TileWidth;
    result.Y := WorldPosition.Y div TileHeight;
    result.Y := result.Y * TileHeight;
    end;[/pascal]

    Depending on if your world position starts at tile 0 or 1 you might have to subtract 1 from the final result of the methods.

  6. #6

    snapping sprite to tilemap

    Ok, now that we're settled with this, another question came upon me, that I have completely forgoten(lack of sleep can do that):
    Apparently I need the sprite to move from tile to tile, but not a continuos movement like this:
    [pascal] sprite.x:= sprite.x + tilesize; [/pascal]
    No, I need it to walk somehow like this:
    Walk one tile and stop, walk one tile and stop.
    I really hope you understand.

    Best Regards, leniz

  7. #7
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    snapping sprite to tilemap

    Oh yeah, this is really common on the old NES games so I'm quite familiar with what you are trying to do.

    Basically what you want to do is to have your character or player object stop at the next tilespace.

    There are a few ways to do this, but I think the easiest might be to have a movement flag. (Boolean variable) When this flag is up (True) your character is moving, and when down (False) it is not.

    What this will allow you to do is keep track of when he is moving in the code that determines when to stop him. Also by using this flag instead of direct user input, you are allowing the person controlling the character to release the button while the character continues to move until it is time to stop. This will allow your character to stick to the tiles when not moving.


    The only thing left to figure out is how one figures out when to stop. Not too hard...

    One way is to keep track of the OldX/OldY grid location of your character and when they are different you allow him to stop by checking if the user's walk buttons are released. If so then he should stop so you set the Moving flag to false and snap the player into the new tile before it is drawn. It will look just like he walked into the tilespace and stopped.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  8. #8

    snapping sprite to tilemap

    So I've been offline for a while and decided to throw away the tile by tile moving idea, atleast for now. Right now I want my 'hero' to walk only on tiles of grass and path, so I used this for staying off water:
    [pascal]If (isRight in form20.DXInput1.keyboard.States) Then
    begin
    oldx:=hero.X;
    oldy:=hero.Y;
    hero.x:=hero.x + 4;
    tempy:=round(hero.Y/tilesize - 0.4444);
    hero.y:=tempy*tilesize;
    if tileinfo[rx, ry].tilenr = 2 then
    begin
    hero.X:=oldx;
    hero.Y:=oldy;
    end;
    end;
    [/pascal]
    Well, it does its thing with a minor glitch - after walking on water tile, my 'hero' stops responding to controls. Any other thoughts on how to solve this minor problem, because I hate it whan my 'hero' steps on water like Jesus Christ...
    BTW: I know this code of mine is totaly lame, but what can I do ops:

  9. #9

    snapping sprite to tilemap

    Before you let your hero move, check the tile that he is moving to to see if its valid. If not, then don't allow the move. The problem your having is that your checking after you move .

    Basically (psudo code):
    Code:
    If RightKeyPressed and OkToWalkOn(TileToRightOfHero) then
      ProcessMove()

  10. #10

    snapping sprite to tilemap

    Oh man, I'm so embarssed. Well thank you for your answer, I'll try it right away

Page 1 of 2 12 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
  •