private void HandleSimpleHorizontalCol <T>(ref Vector2 pos, ref Vector2 vel, Vector2 travelTime, Point gridLocation, T[,] grid) { if (ProssesCellColision != null) //if user has collision responce { Point colGrid = gridLocation; colGrid.X += Math.Sign(vel.X); Collision col = new Collisions.Collision() { Direction = CollisionDirection.Horizontal, GridLocation = colGrid, ObjectCoordinate = new Coordinate(pos, vel), Tile = grid[colGrid.X, colGrid.Y], Grid = grid, }; ProssesCellColision(col); } pos.X += vel.X * travelTime.X; pos.X -= Math.Sign(vel.X) * .5f; //take away 1 pixel so that we are not in the block vel.X *= -_amountOfBounce; }
private void HandleSimpleVerticallCol <T>(ref Vector2 pos, ref Vector2 vel, Vector2 travelTime, Point gridLocation, T[,] grid) { if (ProssesCellColision != null) //if user has collision responce { Point colGrid = gridLocation; colGrid.Y += Math.Sign(vel.Y); Collision col = new Collisions.Collision() { Direction = CollisionDirection.Vertical, GridLocation = colGrid, ObjectCoordinate = new Coordinate(pos, vel), Tile = grid[colGrid.X, colGrid.Y], Grid = grid, }; ProssesCellColision(col); } pos.Y += vel.Y * travelTime.Y; pos.Y -= Math.Sign(vel.Y) * .5f; vel.Y *= -_amountOfBounce; }
/// <summary> /// Handle colision for one update cycle /// </summary> /// <typeparam name="T">the tile type in your 2d array</typeparam> /// <param name="pos">the position of the object you want to check a colision with</param> /// <param name="vel">the velocity of the object you want to check a colision with</param> /// <param name="grid">the 2d array that represents you gameing grid</param> /// <returns>by default the collision detector will invert the velocity after a collision and also set the position. /// You can then set ether the pos and vel return to your object or you can handle it on your own /// </returns> public Coordinate HandleColision <T>(Vector2 pos, Vector2 vel, T[,] grid) { //first calculate distance to next cell Vector2 distance = new Vector2(CalculateDistance(pos.X, vel.X), CalculateDistance(pos.Y, vel.Y)); //now calculate travel time Vector2 travelTime = new Vector2(CalculateTravelTime(distance.X, vel.X), CalculateTravelTime(distance.Y, vel.Y)); Vector2 blockTraveTime = new Vector2(_cellSize / Math.Abs(vel.X), _cellSize / Math.Abs(vel.Y)); Point gridLocation = new Point((int)Math.Floor(pos.X / _cellSize), (int)Math.Floor(pos.Y / _cellSize)); List <CollisionDirection> dirs = new List <CollisionDirection>(); Vector2 deltaTime = Vector2.Zero; while (travelTime.X <= 1 || travelTime.Y <= 1) { updatenumber++; dirs.Clear(); bool HorCol = false, VerCol = false; if (travelTime.X <= 1) { HorCol = ValidateHorizontalColision(gridLocation, vel, travelTime.X, grid); if (!HorCol) { // deltaTraveTime += blockTraveTime; travelTime.X += blockTraveTime.X; // if (deltaTraveTime.Y > deltaTraveTime.X) gridLocation.X += Math.Sign(vel.X); deltaTime.X += blockTraveTime.X; } else { dirs.Add(CollisionDirection.Horizontal); } } if (travelTime.Y <= 1) { VerCol = ValidateVerticalColision(gridLocation, vel, travelTime.Y, grid); if (!VerCol) { //deltaTraveTime += blockTraveTime; travelTime.Y += blockTraveTime.Y; // if (deltaTraveTime.Y < deltaTraveTime.X) gridLocation.Y += Math.Sign(vel.Y); deltaTime.Y += blockTraveTime.Y; } else if (dirs.Count == 0) //if we already have a contact this time { dirs.Add(CollisionDirection.Vertical); } else if (travelTime.Y > travelTime.X) { dirs.Add(CollisionDirection.Vertical); } else { dirs.Insert(0, CollisionDirection.Vertical); } } if (dirs.Count == 0) { continue; } CollisionDirection dir = CollisionDirection.Horizontal; int count = 0; while (dirs.Count > 0) { dir = dirs[0]; dirs.RemoveAt(0); switch (dir) { case CollisionDirection.Horizontal: // Console.WriteLine($"Collisoin Horizontal > {updatenumber}"); //gridLocation.X += Math.Sign(vel.X); if (ProssesCellColision != null) //if user has collision responce { Point colGrid = gridLocation; colGrid.X += Math.Sign(vel.X); Collision col = new Collisions.Collision() { Direction = CollisionDirection.Horizontal, GridLocation = colGrid, ObjectCoordinate = new Coordinate(pos, vel), Tile = grid[colGrid.X, colGrid.Y], Grid = grid, }; ProssesCellColision(col); } pos += vel * travelTime.X; pos.X -= Math.Sign(vel.X) * .5f; //take away 1 pixel so that we are not in the block vel.X *= -_amountOfBounce; //first calculate distance to next cell distance.X = CalculateDistance(pos.X, vel.X); //now calculate travel time travelTime.X = CalculateTravelTime(distance.X, vel.X); // if (travelTime.Y <= 1) //ONLY If there was a collisoin to check // { distance.Y = CalculateDistance(pos.Y, vel.Y); travelTime.Y = CalculateTravelTime(distance.Y, vel.Y) + deltaTime.Y; // } break; case CollisionDirection.Vertical: // gridLocation.Y += Math.Sign(vel.Y); // Console.WriteLine($"Collisoin Vertical > {updatenumber}"); if (ProssesCellColision != null) //if user has collision responce { Point colGrid = gridLocation; colGrid.Y += Math.Sign(vel.Y); Collision col = new Collisions.Collision() { Direction = CollisionDirection.Vertical, GridLocation = colGrid, ObjectCoordinate = new Coordinate(pos, vel), Tile = grid[colGrid.X, colGrid.Y], Grid = grid, }; ProssesCellColision(col); } pos += vel * travelTime.Y; pos.Y -= Math.Sign(vel.Y) * .5f; vel.Y *= -_amountOfBounce; distance.Y = CalculateDistance(pos.Y, vel.Y); travelTime.Y = CalculateTravelTime(distance.Y, vel.Y); // if (travelTime.X <= 1) //ONLY If there was a collisoin to check { //first calculate distance to next cell distance.X = CalculateDistance(pos.X, vel.X); //now calculate travel time travelTime.X = CalculateTravelTime(distance.X, vel.X) + deltaTime.X; } break; } count++; } } return(new Collisions.Coordinate(pos, vel)); }