XNA Creators Club Online
Page 1 of 1 (10 items)
Sort Posts: Previous Next

Question: Creating Sloped Block in Platformer Starter kit

Last post 2/26/2010 3:02 PM by SAIEx. 9 replies.
  • 2/10/2009 9:48 PM

    Question: Creating Sloped Block in Platformer Starter kit

    Hi Creators,

    I have a coding question that I can't seem to solve.
    I am working with the Platformer Starter kit, but unfortunately due to the way collision with blocks is detected, I am having trouble creating a slope for
    my character to walk up / down.

    I've created another enumerated collision type, upslope.

    In the Player.cs, I've attempted to code his collision with the block type, but I can't seem to get it to work

    I've attempted to calculate a slope to set the players position to :

    Position =

    new Vector2(Position.X, (slope * Position.X)   + 48);

     

    but that won't work.

    even when I attempt to run other types of collision, I end up using the physics position what causes the player sprite to stutter.
    I believe that this is because even though the player is trying to be placed up on a slope while the physics is informing he is not "on" a block, therefore, acceleration
    of gravity is pushing him downward.

    This happens even though the boolean "IsOnGround = true"

    I've heard suggestions of height Maps, drawing the player on a slope, even though physically, he is on the block.
    I'm curious if anyone else has currently solved this issue, or if they had to recode the Starter, and how.

    Thanks
    Kevin
  • 2/11/2009 5:08 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    I'm also trying to implement slopes in the xna platformer starter kit and haven't been able to get it working yet. I found an working algorithm here in C++ but I have yet to successfully integrate it into the platformer kit: http://jnrdev.72dpiarmy.com/en/jnrdev2/

    A lot of the jittering problems happen because of the position getting set more than once per call to HandleCollisons(). It might be easier to make a variable called xpos and ypos and set those to the distance the player needs to move on the next frame and add them to the position at the end of the function. That way you don't set the position more than once per function call. If anyone has found a solution for tiled slopes in xna please let us know.
  • 2/16/2009 6:16 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    Ok, here is what I've got so far.  It works as far as I can tell.

    platformer1.rar
  • 2/18/2009 8:08 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    Incredible. The would definitely help me. I slightly looked over the code and I think I understand how it works.

    Thanks for all the Help.
    Kevin O'Connell
  • 2/24/2009 7:45 AM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    Hi All,

    I'm new to XNA and game programming in general, so forgive me if I overlooked something, but I believe I've found a decent working solution to the slope issue that fits easily into the platformer starter kit:

    You want to create two new enumerations for Tile collision types: a left slope (meaning an uphill slope from left to right), and a right slope (meaning a downhill slope from left to right).  to calculate the Y position on a left slope, use

    slopeTop = (tileBounds.Bottom - ((bounds.Center.X - tileBounds.Left) * (float)Math.Sin(Math.Atan2(tileBounds.Height, (bounds.Center.X - tileBounds.Left)))));  
                                              
     

    and for a right slope use

    slopeTop = (tileBounds.Bottom - ((tileBounds.Right - bounds.Center.X) * (float)Math.Sin(Math.Atan2(tileBounds.Height, (tileBounds.Right - bounds.Center.X)))));  
     

    i got this formula from http://www.mathsisfun.com/polar-cartesian-coordinates.html if anyone's interested.  in the collision routine, before the nested y & x loops, you want to create your own x loop to check your bottom tiles for collision with a slope
    for (int x = leftTile; x <= rightTile; ++x)  
                    {  
                        TileCollision collision = Level.GetCollision(x, bottomTile);  
                        if (collision == TileCollision.SlopeLeft || collision == TileCollision.SlopeRight)  
                        {  
                            isOnSlope = true;  
                        }  
                    } 


    your left slope collision routine should be

    if ((bounds.Center.X - tileBounds.Left) == 0)  
                                        {  
                                            slopeTop = tileBounds.Bottom;  
                                        }  
                                        else if (bounds.Center.X - tileBounds.Left < 0)  
                                        {  
                                            if (IsOnSlope == true)  
                                            {  
                                                continue;  
                                            }  
                                            else 
                                                slopeTop = tileBounds.Bottom;  
                                        }  
                                        else 
                                            slopeTop = (tileBounds.Bottom - ((bounds.Center.X - tileBounds.Left) * (float)Math.Sin(Math.Atan2(tileBounds.Height, (bounds.Center.X - tileBounds.Left)))));  
                                              
                                      
                                        slopeTop -= 2.0f; 

                                    isOnSlope =

    true;

     

                                    isOnGround =

    true;

     



    follow the same idea for the right, but change it to reflect how the formula works for right slopes accordingly.  then for collision from X or Y do

    if (collision == TileCollision.SlopeLeft || collision == TileCollision.SlopeRight)  
                                    {  
                                        if (isJumping == false)  
                                        {  
                                            // Resolve the collision along the Y axis.  
                                            Position = new Vector2(Position.X, slopeTop);  
                                            Position = new Vector2((float)Math.Round(Position.X), (float)Math.Round(Position.Y));  
                                        }  
     
                                        // Perform further collisions with the new bounds.  
                                        bounds = BoundingRectangle;  
                                    } 

    and lastly, be sure isOnSlope is FALSE before entering any of the impassable collision routines.  hope this is helpful.
  • 6/9/2009 11:06 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    (months later).. in case anyone stumbles upon this, i realized i made a slight mistake in my calculation of slopeTop.  here is the correction:
    float dist = (float)Math.Sqrt(Math.Pow(MathHelper.Clamp(bounds.Center.X - tileBounds.Left, 0, Tile.Width), 2) + Math.Pow(MathHelper.Clamp(tileBounds.Bottom - bounds.Bottom, 0, Tile.Height), 2)); 
     
    slopeTop = (tileBounds.Bottom - (dist * (float)Math.Sin(Math.Atan2(tileBounds.Height, tileBounds.Width)))); 
                                         

  • 8/24/2009 7:47 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    I was just looking for some information on this, thanks. I am going to give it a go and see how it works.
  • 8/25/2009 5:47 AM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    There are two problems with this method that I would love to know how to iron out.

    First, moving up a large hill composed of multiple slope blocks is quirky.  By the time you get to the next slope in the series, the center bottom of your bounding rectangle may be too far into the next slope to create a fluid motion, which results in jitters.

    Second, as this collision method basically sticks you to the block when you aren't jumping, when you ARE jumping or try to jump off of a slope, the collision method makes the jump not always work quite right.


  • 9/11/2009 9:16 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    Could someone help with this,
    I need some direction on where to place this code in the Platformer Starter Kit.
    I tried to figure it out but I am still a beginner.
    Thanks in advance.
  • 2/26/2010 3:02 PM In reply to

    Re: Question: Creating Sloped Block in Platformer Starter kit

    hi,
    can anyone help me wth this?
    im new to XNA and i tried what mothball was saying but it doesn't work...i made a few changes to match my code and maybe i screwed it up in the process, i don't know....
    so, this is how i got it so far...
    private void HandleCollisions() 
            { 
                // Get the player's bounding rectangle and find neighboring tiles. 
                Rectangle bounds = BoundingRectangle; 
                int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width); 
                int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1; 
                int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height); 
                int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1; 
     
                float dist = 
                    (float)Math.Sqrt 
                    (Math.Pow 
                    (MathHelper.Clamp 
                    (bounds.Center.X - bounds.Left, 0, Tile.Width), 2) + 
                    Math.Pow 
                    (MathHelper.Clamp 
                    (bounds.Bottom - bounds.Bottom, 0, Tile.Height), 2)); 
     
                float slopeTopLeft = 
                    (bounds.Bottom - 
                    ((bounds.Center.X - bounds.Left) * 
                    (float)Math.Sin 
                    (Math.Atan2 
                    (bounds.Height, 
                    (bounds.Center.X - bounds.Left))))); 
     
                float slopeTopRight = 
                    (bounds.Bottom - 
                    ((bounds.Center.X - bounds.Right) * 
                    (float)Math.Sin 
                    (Math.Atan2 
                    (bounds.Height, 
                    (bounds.Center.X - bounds.Right))))); 
     
     
                // Reset flag to search for ground collision. 
                isOnGround = false
     
                // For each potentially colliding tile, 
                for (int y = topTile; y <= bottomTile; ++y) 
                { 
                    for (int x = leftTile; x <= rightTile; ++x) 
                    { 
                        // If this tile is collidable, 
                        TileCollision collision = Level.GetCollision(x, y); 
                        if (collision != TileCollision.Passable) 
                        { 
                            // Determine collision depth (with direction) and magnitude. 
                            Rectangle tileBounds = Level.GetBounds(x, y); 
                            Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds); 
                            if (depth != Vector2.Zero) 
                            { 
                                float absDepthX = Math.Abs(depth.X); 
                                float absDepthY = Math.Abs(depth.Y); 
     
                                // Resolve the collision along the shallow axis. 
                                if (absDepthY < absDepthX || collision == TileCollision.Platform) 
                                { 
                                    //if (!isOnSlope) 
                                    //{ 
                                        // If we crossed the top of a tile, we are on the ground. 
                                        if (previousBottom <= tileBounds.Top) 
                                            isOnGround = true
                                    //} 
     
                                    // Ignore platforms, unless we are on the ground. 
                                    if (collision == TileCollision.Impassable || IsOnGround) 
                                    { 
                                        //if (!isOnSlope) 
                                        //{ 
                                            // Resolve the collision along the Y axis. 
                                            Position = new Vector2(Position.X, Position.Y + depth.Y); 
     
                                            // Perform further collisions with the new bounds. 
                                            bounds = BoundingRectangle; 
                                        //} 
                                    } 
                                } 
                                else if (collision == TileCollision.Impassable) // Ignore platforms. 
                                { 
                                    if (!isOnSlope) 
                                    { 
                                        // Resolve the collision along the X axis. 
                                        Position = new Vector2(Position.X + depth.X, Position.Y); 
     
                                        // Perform further collisions with the new bounds. 
                                        bounds = BoundingRectangle; 
                                    } 
                                } 
                            } 
                            /*if (collision == TileCollision.RampUp)
                            {
                                Rectangle triangle = BoundingRectangle;
                                //int leftTri = (int)Math.Floor((float)bounds.Left / Tile.Width);
                                //int rightTri = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
                                //int topTri = (int)Math.Floor((float)bounds.Top / Tile.Height);
                                //int bottomTri = (int)Math.Ceiling(((float)triangle.Bottom / Tile.Height)) - 1;
                            }*/ 
                        } 
                        if (collision == TileCollision.SlopeLeft) 
                        { 
                            if (isOnSlope) 
                            { 
                                if (isJumping == false
                                { 
                                    // Resolve the collision along the Y axis.   
                                    Position = new Vector2 
                                        (Position.X, slopeTopLeft); 
                                    Position = new Vector2 
                                        ((float)Math.Round(Position.X), 
                                        (float)Math.Round(Position.Y)); 
     
                                    // Perform further collisions with the new bounds.   
                                    bounds = BoundingRectangle; 
                                } 
                            } 
                            else 
                            { 
                                isOnSlope = false
                            } 
                            if (collision == TileCollision.SlopeRight) 
                            { 
                                if (isOnSlope) 
                                { 
                                    if (isJumping == false
                                    { 
                                        // Resolve the collision along the Y axis.   
                                        Position = new Vector2 
                                            (Position.X, slopeTopRight); 
                                        Position = new Vector2 
                                            ((float)Math.Round(Position.X), 
                                            (float)Math.Round(Position.Y)); 
     
                                        // Perform further collisions with the new bounds.   
                                        bounds = BoundingRectangle; 
                                    } 
                                } 
                            } 
                            else 
                            { 
                                isOnSlope = false
                            } 
                        } 
                    } 
                    //slope loop 
                    for (int x = leftTile; x <= rightTile; ++x) 
                    { 
                        TileCollision collision = Level.GetCollision(x, bottomTile); 
                        if (collision == TileCollision.SlopeLeft || 
                            collision == TileCollision.SlopeRight) 
                        { 
                            isOnSlope = true
                        } 
                    } 
     
                    //left slope collision routine 
                    if ((bounds.Center.X - bounds.Left) == 0) 
                    { 
                        slopeTopLeft = bounds.Bottom; 
                    } 
                    else if (bounds.Center.X - bounds.Left < 0) 
                    { 
                        if (isOnSlope == true
                        { 
                            continue
                        } 
                        else 
                            slopeTopLeft = bounds.Bottom; 
                    } 
                    else 
                    { 
                        slopeTopLeft = 
                            (bounds.Bottom - 
                            (bounds.Center.X - bounds.Left) * 
                            (float)Math.Sin(Math.Atan2 
                            (bounds.Height, (bounds.Center.X - bounds.Left)))); 
     
     
                        slopeTopLeft -= 2.0f; 
     
                        isOnSlope = true
     
                        isOnGround = true
                    } 
     
                    //right slope collision routine 
                    if ((bounds.Center.X - bounds.Left) == 0) 
                    { 
                        slopeTopRight = bounds.Bottom; 
                    } 
                    else if (bounds.Center.X - bounds.Left < 0) 
                    { 
                        if (isOnSlope == true
                        { 
                            continue
                        } 
                        else 
                            slopeTopRight = bounds.Bottom; 
                    } 
                    else 
                    { 
                        slopeTopRight = 
                            (bounds.Bottom - 
                            (bounds.Center.X - bounds.Left) * 
                            (float)Math.Sin(Math.Atan2 
                            (bounds.Height, (bounds.Center.X - bounds.Left)))); 
     
     
                        slopeTopRight -= 2.0f; 
     
                        isOnSlope = true
     
                        isOnGround = true
                    } 
     
                    // Save the new bounds bottom. 
                    previousBottom = bounds.Bottom; 
                } 
            } 
    sorry...its kinda all over the method, so....

    any tips?pls?
    thanks!
Page 1 of 1 (10 items) Previous Next