// chuyển từ Box sang Broadphase dùng để khoanh vùng đối tượng public Box BoxToBroadPhase(Box b) { return(SweptAABB.GetBroadPhaseBox(b)); }
public DirectCollision CheckCollision(CAnimationObject _Object) { #region . Thuật toán sweptAABB cũ //float DisMinX, DisMaxX; //float DisMinY, DisMaxY; //Vector2 tempVelocity; //tempVelocity = new Vector2(m_Velocity.X - _Object.Velocity.X, m_Velocity.Y - _Object.Velocity.Y); //if (tempVelocity.X > 0.0f) //{ // DisMinX = _Object.Position.X - (Position.X + m_Sprite.FrameWidht); // DisMaxX = (_Object.Position.X + _Object.Sprite.FrameWidht) - (Position.X); //} //else //{ // DisMinX = (_Object.Position.X + _Object.Sprite.FrameWidht) - (Position.X); // DisMaxX = _Object.Position.X - (Position.X + m_Sprite.FrameWidht); //} //if (tempVelocity.Y > 0.0f) //{ // DisMinY = _Object.Position.Y - (Position.Y + m_Sprite.FrameHeight); // DisMaxY = (_Object.Position.Y + _Object.Sprite.FrameHeight) - (Position.Y); //} //else //{ // DisMinY = (_Object.Position.Y + _Object.Sprite.FrameHeight) - (Position.Y); // DisMaxY = _Object.Position.Y - (Position.Y + m_Sprite.FrameHeight); //} //float EntryTimeX, ExitTimeX; //float EntryTimeY, ExitTimeY; //if (m_Velocity.X == 0.0f) //{ // EntryTimeX = float.NegativeInfinity; // ExitTimeX = float.PositiveInfinity; //} //else //{ // EntryTimeX = DisMinX / (tempVelocity.X * m_GameTime); // ExitTimeX = DisMaxX / (tempVelocity.X * m_GameTime); //} //if (m_Velocity.Y == 0.0f) //{ // EntryTimeY = float.NegativeInfinity; // ExitTimeY = float.PositiveInfinity; //} //else //{ // EntryTimeY = DisMinY / (tempVelocity.Y * m_GameTime); // ExitTimeY = DisMaxY / (tempVelocity.Y * m_GameTime); //} //if (m_Velocity.X == 0.0f && _Object.Velocity.X != 0) //{ // EntryTimeX = DisMinX / (tempVelocity.X * m_GameTime); // ExitTimeX = DisMaxX / (tempVelocity.X * m_GameTime); //} //if (m_Velocity.Y == 0.0f && _Object.Velocity.Y != 0) //{ // EntryTimeY = DisMinY / (tempVelocity.Y * m_GameTime); // ExitTimeY = DisMaxY / (tempVelocity.Y * m_GameTime); //} //float EntryTime; //float ExitTime; //EntryTime = Math.Max(EntryTimeX, EntryTimeY); //ExitTime = Math.Min(ExitTimeX, ExitTimeY); //if (EntryTime > ExitTime) // return DirectCollision.NONE; //if (EntryTimeX < 0.0f && EntryTimeY < 0.0f) // return DirectCollision.NONE; //if (EntryTimeX > 1.0f || EntryTimeY > 1.0f) // return DirectCollision.NONE; //if (EntryTimeX < 0.0f) //{ // if (Position.X + Sprite.FrameWidht < _Object.Position.X || Position.X > _Object.Position.X + _Object.Sprite.FrameWidht) // return DirectCollision.NONE; //} //if (EntryTimeY < 0.0f) //{ // if (Position.Y + Sprite.FrameHeight < _Object.Position.Y || Position.Y > _Object.Position.Y + _Object.Sprite.FrameHeight) // return DirectCollision.NONE; //} //if (EntryTimeX > EntryTimeY && Position.Y + Sprite.FrameHeight != _Object.Position.Y) //{ // if (DisMinX < 0.0f) // { // return DirectCollision.RIGHT; // } // else // { // return DirectCollision.LEFT; // } //} //else //{ // if (DisMinY < 0.0f) // { // return DirectCollision.BOTTOM; // } // else // { // return DirectCollision.TOP; // } //} #endregion float moveX = 0.0f; float moveY = 0.0f; float normalX = 0.0f; float normalY = 0.0f; float timeCollsion = 0.0f; Vector2 velocity = Vector2.Zero; // kiểm tra 2 vật có va chạm với nhau không (không tính trường hợp có vận tốc) if (SweptAABB.CheckAABB(this.GetBox(), _Object.GetBox(), ref moveX, ref moveY) == false) { // nếu vật thứ 2 có vận tốc thì ta trừ vận tốc với nhau, xem vật thứ 2 là vật tĩnh velocity = new Vector2(this.Velocity.X - _Object.Velocity.X, this.Velocity.Y - _Object.Velocity.Y); // kiểm tra xem vật thứ 2 có nằm trong vùng di chuyển của vật 1 hay không ? if (SweptAABB.CheckAABB(this.BoxToBroadPhase(GetBox(velocity)), _Object.GetBox(), ref moveX, ref moveY) == true) { // chạy sweptAABB, nếu có khả năng xảy ra va chạm timeCollsion = SweptAABB.Swept_AABB(GetBox(velocity), _Object.GetBox(), ref normalX, ref normalY); if (timeCollsion < 1.0f && timeCollsion > 0.0f) { if (Math.Abs(m_MoveX) >= Math.Abs(velocity.X * m_GameTime * timeCollsion + normalX)) { m_MoveX = velocity.X * m_GameTime * timeCollsion + normalX; } if (Math.Abs(m_MoveY) >= Math.Abs(velocity.Y * m_GameTime * timeCollsion + normalY)) { m_MoveY = velocity.Y * m_GameTime * timeCollsion + normalY; // trong collision tao lam += move Y ma, ko chuyên position } if (normalX != 0) { if (moveX != 0) { if (normalX == 1) { return(DirectCollision.RIGHT); } else if (normalX == -1) { return(DirectCollision.LEFT); } } } else { if (moveY != 0) { if (normalY == -1) { return(DirectCollision.TOP); } else if (normalY == 1) { return(DirectCollision.BOTTOM); } } } } } else { // làm cái gì đó tùy thích !!!!! } } else { m_MoveX = moveX; m_MoveY = moveY; //if (m_MoveX <= moveX) // m_MoveX = moveX; //if (m_MoveY <= moveY) // m_MoveY = moveY; if (moveX != 0) { if (moveX < 0.0f) { return(DirectCollision.LEFT); } else { return(DirectCollision.RIGHT); } } else if (moveY != 0) { if (moveY <= 0.0f) { return(DirectCollision.TOP); } else { return(DirectCollision.BOTTOM); } } else { if ((GetBound().X + GetBound().Width == _Object.GetBound().X&& GetBound().Y + GetBound().Height == _Object.GetBound().Y) || (GetBound().X == _Object.GetBound().X + _Object.GetBound().Width&& GetBound().Y + GetBound().Height == _Object.GetBound().Y)) { return(DirectCollision.NONE); } if (GetBound().Y + GetBound().Height == _Object.GetBound().Y) { m_Position.Y -= 0.0001f; return(DirectCollision.TOP); } else if (_Object.GetBound().Y + _Object.GetBound().Height == GetBound().Y) { m_Position.Y += 0.0001f; return(DirectCollision.BOTTOM); } else if (GetBound().X + GetBound().Width == _Object.GetBound().X) { m_Position.X -= 0.0001f; return(DirectCollision.LEFT); } else if (_Object.GetBound().X + _Object.GetBound().Width == GetBound().X) { m_Position.X += 0.0001f; return(DirectCollision.RIGHT); } } } return(DirectCollision.NONE); }
void Update() { _collided = false; _withColliderIndex = -1; if (debug_positions.Count > 1) { for (int i = 1; i < debug_positions.Count; i++) { Debug.DrawLine(debug_positions[i - 1], debug_positions[i], Color.yellow); } } var input = _inputMaster.Player.Movement.ReadValue <Vector2>(); var action = (short)_inputMaster.Player.MainAction.ReadValue <float>(); float3 position = transform.position; //var direction = new float2(input.x, input.y); if (input.sqrMagnitude < 0.01) { return; } //Debug.Log($"Input {input}"); //var vx = (input.x * Time.deltaTime * speed) * Time.realtimeSinceStartup; //var vy = (input.y * Time.deltaTime * speed) * Time.realtimeSinceStartup; var vx = input.x * Time.deltaTime * speed; var vy = input.y * Time.deltaTime * speed; var box = new Box(position.x - size * 0.5f, position.z - size * 0.5f, size, size, vx, vy); //var box = new Box(position.x, position.z, size, size, vx, vy ); float moveX = 0.0f; float moveY = 0.0f; float normalX = 0.0f; float normalY = 0.0f; float collisionTime = 1.0f; Vector2 velocity = Vector2.zero; for (var index = 0; index < colliders.Count; index++) { var collider = colliders[index]; if (collider.Type != ColliderType.Box) { continue; } var broadPhaseBox = SweptAABB.GetBroadPhaseBox(box); var block = collider.ToBox(); if (SweptAABB.CheckAABB(broadPhaseBox, block, ref normalX, ref normalY)) { _collided = true; _withColliderIndex = index; collisionTime = SweptAABB.Swept(box, block, ref normalX, ref normalY); // box.x += box.vx * collisiontime; // box.y += box.vy * collisiontime; Debug.Log($"Collided {collisionTime} {normalX} {normalY}"); break; } } var newPosition = Vector3.zero; if (_collided) { var remainingtime = 1.0f - collisionTime; if (collisionResolveType == PhysicsCollisionResolveType.Push) { float magnitude = math.sqrt((box.vx * box.vx + box.vy * box.vy)) * remainingtime; float dotprod = box.vx * normalY + box.vy * normalX; if (dotprod > 0.0f) { dotprod = 1.0f; } else if (dotprod < 0.0f) { dotprod = -1.0f; } box.vx = dotprod * normalY * magnitude; box.vy = dotprod * normalX * magnitude; newPosition = new Vector3(position.x + (box.vx), 0, position.z + (box.vy)); } else if (collisionResolveType == PhysicsCollisionResolveType.Slide) { float dotprod = (box.vx * normalY + box.vy * normalX) * remainingtime; box.vx = dotprod * normalY; box.vy = dotprod * normalX; newPosition = new Vector3(position.x + (box.vx), 0, position.z + (box.vy)); } } else { newPosition = new Vector3(position.x + (box.vx * collisionTime), 0, position.z + (box.vy * collisionTime)); } transform.position = newPosition; debug_positions.Add(newPosition); }