Hello Guest

Author Topic: Am I too stupid to get the collision to work?  (Read 2819 times)

0 Members and 1 Guest are viewing this topic.

thecherry94

  • Member
  • Posts: 2
    • View Profile
Am I too stupid to get the collision to work?
« on: March 03, 2014, 01:11:27 AM »
Hello,

I just started using Otter and am trying to play around with colliders.
Currently I want to do some tests for a tilemap system and am using a GridCollider for the tilemap and a BoxCollider for the player.
I set up the colliders using tags like Kyle did in the OtterPong video but somehow the collision won't register.

Wtf am I doing wrong? :(

I also uploaded the project in case the 3 code files provided below aren't sufficient.
https://www.dropbox.com/s/1wexbta2qcr4l3i/Otter2D%20Test.zip

PlayerEntity.cs
Code: [Select]
namespace Otter2D_Test
{
    public class PlayerEntity : Entity
    {
        private Vector2 mMoveSpeed;
        private Vector2 mVelocity;
        private BoxCollider mCollider;
        private Image mImage;
        private double jumpForce = 150;

        public bool AcceptInput { get; set; }
        public bool IsGrounded { get; set; }

        public PlayerEntity(float x, float y)
            : base(x, y)
        {
            AcceptInput = true;
            IsGrounded = false;

            mMoveSpeed = new Vector2(15, 0);
            mVelocity = new Vector2();

            mImage = Image.CreateRectangle(10, 15, Color.Red);
            mCollider = new BoxCollider(mImage.Width, mImage.Height, (int)ColliderTags.PlayerCollider);

            mImage.CenterOrigin();
            mCollider.CenterOrigin();

            SetGraphic(mImage);
            SetCollider(mCollider);
        }

        public override void Render()
        {
            base.Render();

            mCollider.Render();
        }

        public override void Update()
        {
            base.Update();

            float oldX = X;
            float oldY = Y;

            // Movement
            inputMovement();

            // Gravity influence to velocity
            applyGravity();

            // Apply velocity
            X += (float)mVelocity.X * Game.Instance.DeltaTime;
            Y += (float)mVelocity.Y * Game.Instance.DeltaTime;
       
            // Handle Collisions with the tilemap and if given reset positioning and velocity
            handleTilemapCollision(oldX, oldY);                   
        }

        private void inputMovement()
        {
            if(!AcceptInput)
                return;

            if (Game.Instance.Input.KeyDown(Key.A))
                X -= (float)mMoveSpeed.X * Game.Instance.DeltaTime;

            if (Game.Instance.Input.KeyDown(Key.D))
                X += (float)mMoveSpeed.X * Game.Instance.DeltaTime;

            // Only allow jumping if player touches ground
            if (IsGrounded)
            {
                if (Input.KeyDown(Key.Space))
                {
                    mVelocity.Y -= jumpForce;
                    IsGrounded = false;
                }
            }
        }

        private void applyGravity()
        {
            Vector2 gravity = Global.Gravity;
            mVelocity += gravity * Game.Instance.DeltaTime;
        }

        private void handleTilemapCollision(float oldX, float oldY)
        {
            Collider mapCollider = Collider.Collide(X, Y, (int)ColliderTags.TilemapCollider);
            if (mapCollider != null)
            {
                GridCollider gridCollider = (GridCollider)mapCollider;

                // X - Axis
                if (gridCollider.GetTileAtPosition(X - mImage.HalfWidth - 5, Y) ||
                    gridCollider.GetTileAtPosition(X + mImage.HalfWidth + 5, Y))
                {
                    X = oldX;
                }


                // Y - Axis
                if (gridCollider.GetTileAtPosition(X, Y - mImage.HalfHeight - 5) ||
                    gridCollider.GetTileAtPosition(X, Y + mImage.HalfHeight + 5))
                {
                    Y = oldY;
                    mVelocity.Y = 0;

                    // Set is grounded only if there are tiles below
                    if (gridCollider.GetTileAtPosition(X, Y + mImage.HalfHeight + 5))
                        IsGrounded = true;
                }
                else
                {
                    IsGrounded = false;
                }
            }
        }
    }
}


Tilemap.cs
Code: [Select]
namespace Otter2D_Test
{
    public class Tilemap : Entity
    {
        private GridCollider mCollider;

        public Tilemap()
            : base()
        {
            mCollider = new GridCollider(20*32, 10*32, 32, 32, (int)ColliderTags.TilemapCollider);
            SetCollider(mCollider);

            for (int i = 0; i < 20; i++)
                mCollider.SetTile(i, 0);
        }

        public override void Update()
        {
            base.Update();
        }

        public override void Render()
        {
            base.Render();

            mCollider.Render();
        }
    }
}


GridColliderTestScene.cs
Code: [Select]
namespace Otter2D_Test
{
    public class GridColliderTestScene : Scene
    {
        private Tilemap tilemap;
        private PlayerEntity player;

        public GridColliderTestScene()
            : base()
        {

        }

        public override void Begin()
        {
            base.Begin();

            tilemap = new Tilemap();
            tilemap.SetPosition(0, HalfHeight);

            player = new PlayerEntity(300, 100);
        }

        public override void Render()
        {
            base.Render();

            player.Render();
            tilemap.Render();
        }

        public override void Update()
        {
            base.Update();

            tilemap.Update();
            player.Update();
        }
    }
}

Kyle

  • Administrator
  • Member
  • Posts: 259
    • View Profile
Re: Am I too stupid to get the collision to work?
« Reply #1 on: March 04, 2014, 01:59:29 PM »
Hey! I'm going to take a look at this soon.  In the mean time I'm moving this to the help forum :)

Kyle

  • Administrator
  • Member
  • Posts: 259
    • View Profile
Re: Am I too stupid to get the collision to work?
« Reply #2 on: March 05, 2014, 02:37:03 PM »
Okay I'm looking into this, it looks like there might be a bug with the grid collider where it only likes to work correctly if it's still positioned at 0, 0.  I'll try fixing this today.

Edit: I might've fixed it, but before I push a new version of Otter I need to figure out the Spine stuff.  Until then, you can fix it in your local copy of Otter with this code:

Edit2: Fixed the function more, I think.

line 74 of GridCollider.cs
Code: [Select]
        /// <summary>
        /// Returns true if any tile in the rect is true.
        /// </summary>
        /// <param name="x">X of the rect in grid space.</param>
        /// <param name="y">Y of the rect in grid space.</param>
        /// <param name="width">Width of the rect in grid space.</param>
        /// <param name="height">Height of the rect in grid space.</param>
        /// <returns></returns>
        public bool GetRect(float x, float y, float x2, float y2, bool usingGrid = true) {
            //adjust for grid position
            x -= Left;
            x2 -= Left;
            y -= Top;
            y2 -= Top;

            if (!usingGrid) {
                x = (int)(Util.SnapToGrid(x, TileWidth) / TileWidth);
                y = (int)(Util.SnapToGrid(y, TileHeight) / TileHeight);
                x2 = (int)(Util.SnapToGrid(x2, TileWidth) / TileWidth);
                y2 = (int)(Util.SnapToGrid(y2, TileHeight) / TileHeight);
            }

            for (int i = (int)x; i <= x2; i++) {
                for (int j = (int)y; j <= y2; j++) {
                    if (GetTile(i, j)) {
                        return true;
                    }
                }
            }

            return false;
        }
« Last Edit: March 05, 2014, 07:26:17 PM by Kyle »

thecherry94

  • Member
  • Posts: 2
    • View Profile
Re: Am I too stupid to get the collision to work?
« Reply #3 on: March 07, 2014, 02:55:15 AM »
Sorry for posting this in the wrong section and thanks for the reply!

Also, the GetRect method was never called in my code.
I debugged thoroughly this time and found out that the Scene property of my entities (tilemap, player) was null.

Had to call the Add() method in the GridColliderTestScene class and add both entities to the scene to solve the problem.
It's working as expected now :)