Пример #1
0
        public Vector2 Move(Vector2 deltaMovement)
        {
            prevCollisionState = new CollisionState(collisionState);
            collisionState.Reset();

            if (!ignoreCollisions)
            {
                center = position + offset;

                center.x += Horizontal(ref deltaMovement);
                center.y += Vertical(ref deltaMovement);
            }

            transform.Translate(deltaMovement, Space.World);

            if (collisionState.slope)
            {
                deltaMovement.y = 0;
            }

            velocity = deltaMovement / Time.deltaTime;

            if (collisionState.down && !prevCollisionState.down)
            {
                onLanded();
            }

            return(velocity);
        }
Пример #2
0
 private void OnCollisionExit2D(Collision2D collision)
 {
     if (collision.gameObject.GetComponent <WallCollision>() != null)
     {
         currentCollisionState = CollisionState.NONE;
     }
 }
Пример #3
0
 protected virtual void Awake()
 {
     rb             = GetComponent <Rigidbody>();
     player         = GetComponent <Player>();
     collisionState = GetComponent <CollisionState>();
     Wake();
 }
 protected virtual void Awake()
 {
     inputState = GetComponent <InputState>();
     rbdy2D     = GetComponent <Rigidbody2D>();
     collState  = GetComponent <CollisionState>();
     animator   = GetComponent <Animator>();
 }
Пример #5
0
    protected virtual void Awake() {
//        inputState = GetComponent<InputState>();
        abductBody2d = GetComponent<Rigidbody2D>();
        abductCollisionState = GetComponent<CollisionState>();
        boxCollider = GetComponent<BoxCollider2D>();

    }
Пример #6
0
        public void IgnoreCollisionWith(PhysicsComponent other, CollisionState state)
        {
            var otherNative = other.NativeCollisionObject;

            switch (state)
            {
            // Note that we're calling 'SetIgnoreCollisionCheck' on both objects as bullet doesn't
            // do it itself ; One of the object in the pair will report that it doesn't ignore
            // collision with the other even though you set the other as ignoring the former.
            case CollisionState.Ignore:
            {
                // Bullet uses an array per collision object to store all of the objects to ignore,
                // when calling this method it adds the referenced object without checking for duplicates,
                // so if a user where to call 'Ignore' of this function on this object n-times he'll have to call it
                // that same amount of time to re-detect them instead of just once.
                // We're calling false here to remove a previous ignore if there was any and re-ignoring
                // to force it to have only a single instance.
                otherNative.SetIgnoreCollisionCheck(NativeCollisionObject, false);
                NativeCollisionObject.SetIgnoreCollisionCheck(otherNative, false);
                otherNative.SetIgnoreCollisionCheck(NativeCollisionObject, true);
                NativeCollisionObject.SetIgnoreCollisionCheck(otherNative, true);
                break;
            }

            case CollisionState.Detect:
            {
                otherNative.SetIgnoreCollisionCheck(NativeCollisionObject, false);
                NativeCollisionObject.SetIgnoreCollisionCheck(otherNative, false);
                break;
            }
            }
        }
Пример #7
0
        protected virtual void ForwardSense(List <GameObject> objectList, CollisionState collisionState)
        {
            var newListeners = new HashSet <HashedWeakReference <SomeSensorListener> >();

            foreach (HashedWeakReference <SomeSensorListener> listener in sensorListeners)
            {
                if (listener.Reference.TryGetTarget(out SomeSensorListener target))
                {
                    // Keep listeners that were not disposed
                    newListeners.Add(listener);

                    switch (collisionState)
                    {
                    case CollisionState.Enter:
                        target.OnSense(objectList, SenseState.Enter);
                        break;

                    case CollisionState.Stay:
                        target.OnSense(objectList, SenseState.Stay);
                        break;

                    case CollisionState.Exit:
                        target.OnSense(objectList, SenseState.Exit);
                        break;
                    }
                }
            }

            // Clean up any old weak references with null targets
            sensorListeners = newListeners;
        }
Пример #8
0
        private void OnCollisionEnter2D(Collision2D collision)
        {
            WallCollision wall = collision.gameObject.GetComponent <WallCollision>();

            if (wall != null)
            {
                // Determine the direction of the collision to know what our wall collision is.
                if (collision.transform.position.x > transform.position.x)
                {
                    currentCollisionState = CollisionState.RIGHT;

                    Vector3 updatedPosition = transform.position;
                    updatedPosition.x = wall.transform.position.x -
                                        wall.boxCollider.bounds.extents.x -
                                        _boxCollider.bounds.extents.x;

                    transform.position = updatedPosition;
                }
                else
                {
                    currentCollisionState = CollisionState.LEFT;

                    Vector3 updatedPosition = transform.position;

                    updatedPosition.x = wall.transform.position.x +
                                        wall.boxCollider.bounds.extents.x +
                                        _boxCollider.bounds.extents.x;

                    transform.position = updatedPosition;
                }
            }
        }
Пример #9
0
 /// <summary>
 /// Internal quick constructor
 /// </summary>
 public CollisionHit4(CollisionState state, Contact c, bool isForA)
 {
     this.state = state;
     sensor     = c.sensor;
     manifold   = c.manifold;
     other      = (Collider4)(isForA ? c.B.Tag : c.A.Tag);
 }
    public void CallOnUpdate(CollisionState collisionState)
    {
        if (m_ladderState == LadderState.JumpOff)
        {
            return;
        }

        if (m_ladderState != LadderState.None)
        {
            float climb = Input.GetAxis("Vertical");
            Offset = (climb * 0.02f);
        }
        else
        {
            Offset = 0.0f;
        }

        if (m_ladderState == LadderState.AtTop && Offset > 0.0f)
        {
            Offset = 0.0f;
        }

        if (collisionState == CollisionState.OnFloor && Offset < 0.0f)
        {
            Offset = 0.0f;
        }

        if (Input.GetButton("Jump") && m_ladderState != LadderState.None)
        {
            m_ladderState = LadderState.JumpOff;
            Offset        = 0.0f;
        }
    }
    public void CallOnUpdate(CollisionState collisionState)
    {
        if (m_ladderState == LadderState.JumpOff)
            return;

        if (m_ladderState != LadderState.None)
        {
            float climb = Input.GetAxis("Vertical");
            Offset = (climb * 0.02f);
        }
        else {
            Offset = 0.0f;
        }

        if (m_ladderState == LadderState.AtTop && Offset > 0.0f) {
            Offset = 0.0f;
        }

        if (collisionState == CollisionState.OnFloor && Offset < 0.0f) {
            Offset = 0.0f;
        }

        if (Input.GetButton("Jump") && m_ladderState != LadderState.None) {
            m_ladderState = LadderState.JumpOff;
            Offset = 0.0f;
        }
    }
Пример #12
0
 private void Awake()
 {
     _inputState     = GetComponent <InputState> ();
     _walkBehavior   = GetComponent <WalkBehavior> ();
     _animator       = GetComponent <Animator> ();
     _collisionState = GetComponent <CollisionState> ();
 }
Пример #13
0
    /*
     * \brief Works out if a value is almost another value (for floating point accuracy)
     */
    public void CallOnCollisionEnter(Collision collision)
    {
        m_collisionState = CollisionState.None;

        foreach (ContactPoint contact in collision)
        {
            if (isNearly(contact.normal.y, 1.0f, 0.2f))
            {
                m_collisionState = CollisionState.OnFloor;
            }
            else if (isNearly(contact.normal.y, -1.0f, 0.2f))
            {
                m_collisionState = CollisionState.OnRoof;
            }
            else
            {
                m_collisionState = CollisionState.OnWall;
            }
        }

        if (m_collisionState == CollisionState.OnFloor)
        {
            m_jumpState = JumpState.Landed;
        }
    }
Пример #14
0
//    private Duck duckBehavior;


    void Awake() {
        inputState = GetComponent<InputState>();
        flyBehavior = GetComponent<Fly>();
        animator = GetComponent<Animator>();
        collisionState = GetComponent<CollisionState>();
//        duckBehavior = GetComponent<Duck>();
    }
Пример #15
0
 private void Start()
 {
     inputState     = GetComponent <InputState>();
     walkBehaviour  = GetComponent <Walk>();
     animator       = GetComponent <Animator>();
     collisionState = GetComponent <CollisionState>();
 }
Пример #16
0
        // Unity continual collision callback
        protected virtual void OnCollisionStay(Collision collision)
        {
            // if this method has been called, we're in some kind of collision state
            collisionState = CollisionState.Grounded;
            float max = WaistPosition.y;
            float min = WaistPosition.y;

            // check collision points
            foreach (ContactPoint m in collision.contacts)
            {
                // how steep is the point with which we collided?
                float slope = Mathf.Acos(Mathf.Clamp(m.normal.y, -1f, 1f)) * Mathf.Rad2Deg;

                // if it's fairly steep, flag stuck and we may be trying to jump
                stuck = (slope > maxSlope / 2f);

                // max collision extrema
                if (m.point.y >= max)
                {
                    maxCollisionPoint = m;
                    max = m.point.y;
                    // if greater than our max grade AND the point's height is higher than the actor's waist
                    if (slope > maxSlope)
                    {
                        collisionState = CollisionState.Blocked;
                    }
                }
                // min collision extrema
                if (m.point.y <= min)
                {
                    minCollisionPoint = m;
                    min = m.point.y;
                }
            }
        }
Пример #17
0
        public void UpdateProjectile(Projectile projectile, Game1 game)
        {
            projectile.life++;
            if (projectile.life == GetLifeSpan())
            {
                DestroyProjectile(projectile);
            }
            projectile.worldX += projectile.GetData().GetXVel(projectile);
            projectile.worldY += projectile.GetData().GetYVel(projectile);
            projectile.UpdateSprite(game.worldMap[game.currentRoom]);
            CollisionState result = CollisionDetector.PerPixelSprite(projectile, game.player, game.graphics);

            if ((result == CollisionState.Hurtbox || result == CollisionState.Standard) && game.worldMap[game.currentRoom].enemyProjectiles.Contains(projectile))
            {
                game.player.TakeDamage(projectile);
                DestroyProjectile(projectile);
            }
            if (CollisionDetector.CheckMapCollision(0, 0, projectile, game.worldMap[game.currentRoom]) == false)
            {
                if (projectile.onScreen && projectile.nearScreen)
                {
                    game.AddObjectToDraw(projectile);
                }
                else
                {
                    projectile.Delete();
                }
            }
            else
            {
                DestroyProjectile(projectile);
            }
        }
Пример #18
0
        protected override void OnSense(GameObject target, CollisionState collisionState)
        {
            if (!this.sensorDelegate.TryGetTarget(out SensorDelegate sensorDelegate))
            {
                return;
            }
            if (!sensorDelegate.IsSenseTarget(target))
            {
                return;
            }

            var orientAngle = 360.0f - transform.eulerAngles.z;
            var minAngle    = orientAngle - degreeAngleScan / 2.0f;
            var maxAngle    = orientAngle + degreeAngleScan / 2.0f;

            //if (collisionState == CollisionState.Enter) {
            //    Debug.Log("Scan angle to Target: " + angleToTarget.ToString() + " orientAngle: " + orientAngle.ToString());
            //}
            List <GameObject> objectList = new List <GameObject>()
            {
                target
            };

            // FUTURE: this can be optimized further by using a PolygonCollider2D, which reduces the number of false positives
            if (CheckOccluders(orientAngle, degreeAngleScan / 2.0f, target, false))
            {
                return;
            }

            ForwardSense(objectList, collisionState);
        }
Пример #19
0
	void Awake () {
		inputState = GetComponent<InputState> ();
		walkBehaviour = GetComponent<Walk> ();
		duckBehaviour = GetComponent<Duck> ();
		animator = GetComponent<Animator> ();
		collisionState = GetComponent<CollisionState> ();
	}
Пример #20
0
        public void CheckCollsion(GameObject obj, out CollisionState _state)
        {
            _state = new CollisionState(false);
            foreach (GameObject obj2 in blocks)
            {
                if (obj2 != obj)
                {
                    if (obj.HitBox.Rect.Intersects(obj2.HitBox.Rect))
                    {
                        ObjectsCollided(obj, obj2, out _state);
                    }
                }
            }

            foreach (GameObject obj2 in entities)
            {
                if (obj2 != obj)
                {
                    if (obj.HitBox.Rect.Intersects(obj2.HitBox.Rect))
                    {
                        ObjectsCollided(obj, obj2, out _state);
                    }
                }
            }
        }
Пример #21
0
        private void OnUpdate()
        {
            if (Object.op_Equality((Object)this.animal, (Object)null))
            {
                return;
            }
            ((Component)this.animal).get_transform();
            foreach (AnimalActionPoint searchPoint in this.SearchPoints)
            {
                if (!Object.op_Equality((Object)searchPoint, (Object)null))
                {
                    int            instanceId = searchPoint.InstanceID;
                    CollisionState collisionState1;
                    if (!this.collisionStateTable.TryGetValue(instanceId, out collisionState1))
                    {
                        CollisionState collisionState2 = CollisionState.None;
                        this.collisionStateTable[instanceId] = collisionState2;
                        collisionState1 = collisionState2;
                    }
                    if (((Component)searchPoint).get_gameObject().get_activeSelf() && this.animal.CheckTargetOnArea(searchPoint.Destination, this._visibleDistance, this._visibleHeight, this._visibleAngle))
                    {
                        switch (collisionState1)
                        {
                        case CollisionState.None:
                        case CollisionState.Exit:
                            this.collisionStateTable[instanceId] = CollisionState.Enter;
                            this.OnEnter(searchPoint);
                            continue;

                        case CollisionState.Enter:
                        case CollisionState.Stay:
                            this.collisionStateTable[instanceId] = CollisionState.Stay;
                            continue;

                        default:
                            continue;
                        }
                    }
                    else
                    {
                        switch (collisionState1)
                        {
                        case CollisionState.None:
                        case CollisionState.Exit:
                            this.collisionStateTable[instanceId] = CollisionState.None;
                            continue;

                        case CollisionState.Enter:
                        case CollisionState.Stay:
                            this.collisionStateTable[instanceId] = CollisionState.Exit;
                            this.OnExit(searchPoint);
                            continue;

                        default:
                            continue;
                        }
                    }
                }
            }
        }
Пример #22
0
 protected virtual void Awake()
 {
     inputState     = GetComponent <InputState>();
     body2d         = GetComponent <Rigidbody2D>();
     collisionState = GetComponent <CollisionState>();
     AManager       = GetComponent <AudioManager>();
 }
Пример #23
0
 /// <summary>
 /// Assumptions: Either On the ground and beginning to jump with no wall collision, or on the ground and beginning to jump with wall collision, or no collision
 /// </summary>
 /// <param name="collision"></param>
 /// <param name="isEntering"></param>
 public void CollisionChange(Collision2D collision, CollisionState collisionState)
 {
     if (collisionState == CollisionState.ENTERING)
     {
         if (collision.contacts[0].normal.y > 0.4f)
         {
             manager.ChangeState(MovementState.STOPPED);
         }
         else if (collision.contacts[0].normal.y < -0.4f)
         {
             manager.ChangeState(MovementState.FALLING);
         }
         else if (collision.contacts[0].normal.x > 0.4f)
         {
             manager.ChangeState(MovementState.HUGGING_WALL);
         }
     }
     else if (collisionState == CollisionState.EXITING)
     {
         if (manager.CurrentCollisions.Count == 1 && Mathf.Abs(manager.WallHugDirection) > 0.4f)
         {
             transitionToHugging = true;
             //manager.ChangeState( MovementState.HUGGING_WALL );
         }
         else
         {
             transitionToHugging = false;
         }
     }
 }
    public void CallOnTriggerStay(Collider collider, ref PlayerState playerState)
    {
        CSceneObject obj = collider.gameObject.GetComponent <CSceneObject>();

        if (obj == null && collider.gameObject != null && collider.gameObject.transform.parent != null)
        {
            GameObject parent = collider.gameObject.transform.parent.gameObject;
            if (parent != null)
            {
                obj = parent.GetComponent <CSceneObject>();
            }
        }

        if (obj != null && obj.IsLadder && (m_ladderClimb.State != LadderState.JumpOff))
        {
            m_ladderClimb.CallOnTriggerStay(collider, ref playerState);
            if (m_ladderClimb.State != LadderState.None)
            {
                m_body.constraints = RigidbodyConstraints.FreezeAll;
            }
            else
            {
                m_collisionState = CollisionState.OnFloor;
            }
            return;
        }
    }
Пример #25
0
        public void OnCollisionEvent(CollisionState state)
        {
            if (cState == state)
            {
                return;
            }
            cState = state;

            // On surface?
            switch (cState)
            {
            case CollisionState.AIR:
                break;

            case CollisionState.GROUND:
            case CollisionState.WALL:
            case CollisionState.LEDGE:
                ResetJump();
                break;

            case CollisionState.CEILING:
                ResetVelocity();
                break;
            }

            //Debug.Log($"Collision State: {cState}");
        }
 void Awake()
 {
     inputState     = GetComponent <InputState> ();
     walkBehavior   = GetComponent <Walk> ();
     animator       = GetComponent <Animator> ();
     collisionState = GetComponent <CollisionState> ();
 }
Пример #27
0
 protected virtual void Awake()
 {
     inputState     = GetComponent <InputState> ();
     body2d         = GetComponent <Rigidbody2D> ();
     collisionState = GetComponent <CollisionState> ();
     //objectPooler = GameObject.Find("PlayerBulletObjectPool").GetComponent<ObjectPooler> ();
 }
Пример #28
0
    public void OnUpdate(ref GruntState playerState)
    {
        if (playerState == GruntState.Standing)
        {
            m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
        }


        m_isJumpDown = false;         //= Input.GetButton("Jump");
        //if (Application.platform == RuntimePlatform.Android)
        //	m_isJumpDown = Input.touchCount != 0;

        if (m_isJumpDown && m_jumpState == JumpState.Landed && CanJump(playerState))
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > JumpDelayMS)
            {
                m_jumpTimer = (Time.time * 1000.0f);
                m_body.AddForce(new Vector3(0, PlayerJumpHeight, 0), ForceMode.Impulse);
                m_jumpState      = JumpState.Jumping;
                playerState      = GruntState.Jumping;
                m_collisionState = CollisionState.None;
            }
        }

        if (m_jumpState == JumpState.Jumping && playerState == GruntState.Jumping)
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > 2000.0f)
            {
                playerState = GruntState.FallJumping;
            }
        }
    }
Пример #29
0
 protected virtual void Awake()
 {
     inputState = GetComponent<InputState> ();
     body2d = GetComponent<Rigidbody2D> ();
     collisionState = GetComponent<CollisionState> ();
     spriteRenderer = GetComponent<SpriteRenderer> ();
 }
Пример #30
0
        bool TestMapCollision(Rectangle collisionRect, Edge direction, CollisionState collisionState,
                              out int collisionResponse)
        {
            collisionResponse = 0;
            var side = direction.OppositeEdge();
            var perpindicularPosition = side.IsVertical() ? collisionRect.Center.X : collisionRect.Center.Y;
            var leadingPosition       = collisionRect.GetSide(direction);
            var shouldTestSlopes      = side.IsVertical();

            PopulateCollidingTiles(collisionRect, direction);

            for (var i = 0; i < _collidingTiles.Count; i++)
            {
                if (_collidingTiles[i] == null)
                {
                    continue;
                }

                // disregard horizontal collisions with tiles on the same row as a slope if the last tile we were grounded on was a slope.
                // the y collision response will push us up on the slope.
                if (direction.IsHorizontal() && collisionState._lastGroundTile != null &&
                    collisionState._lastGroundTile.IsSlope() && IsSlopeCollisionRow(_collidingTiles[i].Y))
                {
                    continue;
                }

                if (TestTileCollision(_collidingTiles[i], side, perpindicularPosition, leadingPosition,
                                      shouldTestSlopes, out collisionResponse))
                {
                    // store off our last ground tile if we collided below
                    if (direction == Edge.Bottom)
                    {
                        collisionState._lastGroundTile            = _collidingTiles[i];
                        collisionState.IsGroundedOnOneWayPlatform = collisionState._lastGroundTile.IsOneWayPlatform();
                    }

                    return(true);
                }

                // special case for sloped ground tiles
                if (collisionState._lastGroundTile != null && direction == Edge.Bottom)
                {
                    // if grounded on a slope and intersecting a slope or if grounded on a wall and intersecting a tall slope we go sticky.
                    // tall slope here means one where the the slopeTopLeft/Right is 0, i.e. it connects to a wall
                    var isHighSlopeNearest = _collidingTiles[i].IsSlope() &&
                                             _collidingTiles[i].GetNearestEdge(perpindicularPosition) ==
                                             _collidingTiles[i].GetHighestSlopeEdge();
                    if ((collisionState._lastGroundTile.IsSlope() && _collidingTiles[i].IsSlope()) ||
                        (!collisionState._lastGroundTile.IsSlope() && isHighSlopeNearest))
                    {
                        // store off our last ground tile if we collided below
                        collisionState._lastGroundTile = _collidingTiles[i];
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #31
0
        private void OnUpdate()
        {
            if (Object.op_Equality((Object)this._agent, (Object)null))
            {
                return;
            }
            foreach (ActionPoint searchPoint in this._searchPoints)
            {
                if (!Object.op_Equality((Object)searchPoint, (Object)null))
                {
                    int            instanceId = searchPoint.InstanceID;
                    CollisionState collisionState1;
                    if (!this._collisionStateTable.TryGetValue(instanceId, out collisionState1))
                    {
                        CollisionState collisionState2 = CollisionState.None;
                        this._collisionStateTable[instanceId] = collisionState2;
                        collisionState1 = collisionState2;
                    }
                    if ((double)Vector3.Distance(((Component)this).get_transform().get_position(), searchPoint.CommandCenter) < (double)this._radius + (double)searchPoint.Radius)
                    {
                        switch (collisionState1)
                        {
                        case CollisionState.None:
                        case CollisionState.Exit:
                            this._collisionStateTable[instanceId] = CollisionState.Enter;
                            this.OnEnter(searchPoint);
                            continue;

                        case CollisionState.Enter:
                        case CollisionState.Stay:
                            this._collisionStateTable[instanceId] = CollisionState.Stay;
                            continue;

                        default:
                            continue;
                        }
                    }
                    else
                    {
                        switch (collisionState1)
                        {
                        case CollisionState.None:
                        case CollisionState.Exit:
                            this._collisionStateTable[instanceId] = CollisionState.None;
                            continue;

                        case CollisionState.Enter:
                        case CollisionState.Stay:
                            this._collisionStateTable[instanceId] = CollisionState.Exit;
                            this.OnExit(searchPoint);
                            continue;

                        default:
                            continue;
                        }
                    }
                }
            }
        }
Пример #32
0
 private void TryToEscape()
 {
     if (++escapeAttempts == EscapeAttemptPeriod)
     {
         escapeAttempts = 0;
         state          = CollisionState.Plane;
     }
 }
Пример #33
0
 void Awake()
 {
     inputState = GetComponent<InputState> ();
     walkBehavior = GetComponent<Walk> ();
     animator = GetComponent<Animator> ();
     collisionState = GetComponent<CollisionState> ();
     shootBehavior = GetComponent<Shoot> ();
 }
 void TryToEscape(TriangleShape triangle, ref Vector3 position)
 {
     if (++escapeAttempts == EscapeAttemptPeriod && GetVoronoiRegion(triangle, ref position) == VoronoiRegion.ABC)
     {
         escapeAttempts = 0;
         state          = CollisionState.Plane;
     }
 }
Пример #35
0
        // Comcast New Self Department: 1-877-405-2298

        //void AirControl()
        //{
        //    float xInput   = Input.GetAxis("Horizontal");
        //    float tarSpeed = xInput * Speed;
        //    float airAcc   = AirControlSpeed * Time.deltaTime;
        //    float tarX     = Mathf.MoveTowards(MoveDir.x, tarSpeed, airAcc);

        //    bool dif = Mathf.Sign(xInput) != Mathf.Sign(MoveDir.x);
        //    bool areZeroes = MoveDir.x == 0 || xInput == 0;
        //    bool isSpeedUP = Mathf.Abs(tarX) > Mathf.Abs(MoveDir.x);

        //    if (areZeroes || dif || isSpeedUP) { MoveDir.x = tarX; }
        //}

        public void OnCollisionEvent(CollisionState state)
        {
            if (cState == state)
            {
                return;
            }
            cState = state;
        }
 /// <summary>
 /// Cleans up the pair tester.
 /// </summary>
 public override void CleanUp()
 {
     convex = null;
     state = CollisionState.Plane;
     escapeAttempts = 0;
     localSeparatingAxis = new System.Numerics.Vector3();
     Updated = false;
 }
Пример #37
0
 /// <summary>
 /// Cleans up the pair tester.
 /// </summary>
 public override void CleanUp()
 {
     convex              = null;
     state               = CollisionState.Plane;
     escapeAttempts      = 0;
     localSeparatingAxis = new Vector3();
     Updated             = false;
 }
Пример #38
0
 protected virtual void Awake()
 {
     health = GetComponent<Health> ();
     inputState = GetComponent<InputState> ();
     body2d = GetComponent<Rigidbody2D> ();
     collisionState = GetComponent<CollisionState> ();
     objectPooler = GameObject.Find("PlayerBulletObjectPool").GetComponent<ObjectPooler> ();
 }
 /// <summary>
 /// Cleans up the pair tester.
 /// </summary>
 public override void CleanUp()
 {
     triangle = null;
     convex = null;
     state = CollisionState.Plane;
     escapeAttempts = 0;
     localSeparatingAxis = new Vector3();
     Updated = false;
 }
 ///<summary>
 /// Cleans up the pair tester.
 ///</summary>
 public void CleanUp()
 {
     state = CollisionState.Separated;
     previousState = CollisionState.Separated;
     cachedSimplex = new CachedSimplex();
     localSeparatingAxis = new Vector3();
     collidableA = null;
     collidableB = null;
 }
Пример #41
0
        ///<summary>
        /// Generates a contact between the objects, if possible.
        ///</summary>
        ///<param name="contact">Contact created between the pair, if possible.</param>
        ///<returns>Whether or not the objects were colliding.</returns>
        public bool GenerateContactCandidate(out ContactData contact)
        {
            //Generate contacts.  This will just find one closest point using general supportmapping based systems like MPR and GJK.

            //The collision system moves through a state machine depending on the latest collision generation result.
            //At first, assume that the pair is completely separating.  This is almost always the correct guess for new pairs.
            //An extremely fast, warm-startable boolean GJK test can be performed.  If it returns with nonintersection, we can quit and do nothing.
            //If the initial boolean GJK test finds intersection, move onto a shallow contact test.
            //The shallow contact test is a different kind of GJK test that finds the closest points between the shape pair.  It's not as speedy as the boolean version.
            //The algorithm is run between the marginless versions of the shapes, so that the closest points will form a contact somewhere in the space separating the cores.
            //If the closest point system finds no intersection and returns the closest points, the state is changed to ShallowContact.
            //If the closest point system finds intersection of the core shapes, then the state is changed to DeepContact, and MPR is run to determine contact information.
            //The system tries to escape from deep contact to shallow contact, and from shallow contact to separated whenever possible.

            //Here's the state flow:
            //On Separated: BooleanGJK
            //  -Intersecting -> Go to ShallowContact.
            //  -Nonintersecting -> Do nothing.
            //On ShallowContact: ClosestPointsGJK
            //  -Intersecting -> Go to DeepContact.
            //  -Nonintersecting: Go to Separated (without test) if squared distance > margin squared, otherwise use closest points to make contact.
            //On DeepContact: MPR
            //  -Intersecting -> Go to ShallowContact if penetration depth < margin
            //  -Nonintersecting -> This case is rare, but not impossible.  Go to Separated (without test).

            previousState = state;
            switch (state)
            {
                case CollisionState.Separated:
                    if (GJKToolbox.AreShapesIntersecting(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, ref localSeparatingAxis))
                    {
                        state = CollisionState.ShallowContact;
                        return DoShallowContact(out contact);
                    }
                    contact = new ContactData();
                    return false;
                case CollisionState.ShallowContact:
                    return DoShallowContact(out contact);
                case CollisionState.DeepContact:
                    return DoDeepContact(out contact);
            }

            contact = new ContactData();
            return false;
        }
Пример #42
0
        protected Matrix transformation; // initial transformation

        #endregion Fields

        #region Constructors

        public GameObject(Game1 game, Vector3 pos)
        {
            this.game = game;

            Type = GameObjectType.None;

            HitPoints = 0;
            AttackSpeed = 0;
            Damage = 0;

            model = null;
            modelName = "";
            Scale = 1.0f;
            transformation = Matrix.Identity;
            color = Color.Transparent;
            isCollidable = true;
            isAlive = true;
            collisionState = CollisionState.None;
            attackCounter = 0;

            this.pos = pos;
            game.Add(this);
        }
Пример #43
0
 void TryToEscape(ref Vector3 position)
 {
     if (++escapeAttempts == EscapeAttemptPeriod && GetVoronoiRegion(ref position) == VoronoiRegion.ABC)
     {
         escapeAttempts = 0;
         state = CollisionState.Plane;
     }
 }
Пример #44
0
 void TryToEscape()
 {
     if (++escapeAttempts == EscapeAttemptPeriod)
     {
         escapeAttempts = 0;
         state = CollisionState.Plane;
     }
 }
Пример #45
0
        private bool DoPlaneTest(out TinyStructList<ContactData> contactList)
        {


            //Find closest point between object and plane.
            Vector3 reverseNormal;
            Vector3 ab, ac;
            Vector3.Subtract(ref triangle.vB, ref triangle.vA, out ab);
            Vector3.Subtract(ref triangle.vC, ref triangle.vA, out ac);
            Vector3.Cross(ref ac, ref ab, out reverseNormal);
            //Convex position dot normal is ALWAYS zero.  The thing to look at is the plane's 'd'.
            //If the distance along the normal is positive, then the convex is 'behind' that normal.
            float dotA;
            Vector3.Dot(ref triangle.vA, ref reverseNormal, out dotA);

            contactList = new TinyStructList<ContactData>();
            switch (triangle.sidedness)
            {
                case TriangleSidedness.DoubleSided:
                    if (dotA < 0)
                    {
                        //The reverse normal is pointing towards the convex.
                        //It needs to point away from the convex so that the direction
                        //will get the proper extreme point.
                        Vector3.Negate(ref reverseNormal, out reverseNormal);
                        dotA = -dotA;
                    }
                    break;
                case TriangleSidedness.Clockwise:
                    //if (dotA < 0)
                    //{
                    //    //The reverse normal is pointing towards the convex.
                    //    return false;
                    //}
                    break;
                case TriangleSidedness.Counterclockwise:
                    //if (dotA > 0)
                    //{
                    //    //The reverse normal is pointing away from the convex.
                    //    return false;
                    //}

                    //The reverse normal is pointing towards the convex.
                    //It needs to point away from the convex so that the direction
                    //will get the proper extreme point.
                    Vector3.Negate(ref reverseNormal, out reverseNormal);
                    dotA = -dotA;
                    break;
            }
            Vector3 extremePoint;
            convex.GetLocalExtremePointWithoutMargin(ref reverseNormal, out extremePoint);


            //See if the extreme point is within the face or not.
            //It might seem like the easy "depth" test should come first, since a barycentric
            //calculation takes a bit more time.  However, transferring from plane to depth is 'rare' 
            //(like all transitions), and putting this test here is logically closer to its requirements'
            //computation.

            if (GetVoronoiRegion(ref extremePoint) != VoronoiRegion.ABC)
            {
                state = CollisionState.ExternalSeparated;
                return DoExternalSeparated(out contactList);
            }



            float dotE;
            Vector3.Dot(ref extremePoint, ref reverseNormal, out dotE);
            float t = (dotA - dotE) / reverseNormal.LengthSquared();



            Vector3 offset;
            Vector3.Multiply(ref reverseNormal, t, out offset);

            //Compare the distance from the plane to the convex object.
            float distanceSquared = offset.LengthSquared();

            float marginSum = triangle.collisionMargin + convex.collisionMargin;
            //TODO: Could just normalize early and avoid computing point plane before it's necessary.  
            //Exposes a sqrt but...
            if (t <= 0 || distanceSquared < marginSum * marginSum)
            {
                //The convex object is in the margin of the plane.
                //All that's left is to create the contact.


                var contact = new ContactData();
                //Displacement is from A to B.  point = A + t * AB, where t = marginA / margin.
                if (marginSum > Toolbox.Epsilon) //This can be zero! It would cause a NaN is unprotected.
                    Vector3.Multiply(ref offset, convex.collisionMargin / marginSum, out contact.Position); //t * AB
                else contact.Position = new Vector3();
                Vector3.Add(ref extremePoint, ref contact.Position, out contact.Position); //A + t * AB.

                float normalLength = reverseNormal.Length();
                Vector3.Divide(ref reverseNormal, normalLength, out contact.Normal);
                float distance = normalLength * t;



                contact.PenetrationDepth = marginSum - distance;

                if (contact.PenetrationDepth > marginSum)
                {
                    //Check to see if the inner sphere is touching the plane.
                    //This does not override other tests; there can be more than one contact from a single triangle.

                    ContactData alternateContact;
                    if (TryInnerSphereContact(out alternateContact))// && alternateContact.PenetrationDepth > contact.PenetrationDepth)
                    {
                        contactList.Add(ref alternateContact);
                    }

                    //The convex object is stuck deep in the plane!
                    //The most problematic case for this is when
                    //an object is right on top of a cliff.
                    //The lower, vertical triangle may occasionally detect
                    //a contact with the object, but would compute an extremely
                    //deep depth if the normal plane test was used.




                    //Verify that the depth is correct by trying another approach.
                    CollisionState previousState = state;
                    state = CollisionState.ExternalNear;
                    TinyStructList<ContactData> alternateContacts;
                    if (DoExternalNear(out alternateContacts))
                    {
                        alternateContacts.Get(0, out alternateContact);
                        if (alternateContact.PenetrationDepth + .01f < contact.PenetrationDepth) //Bias against the subtest's result, since the plane version will probably have a better position.
                        {
                            //It WAS a bad contact.
                            contactList.Add(ref alternateContact);
                            //DoDeepContact (which can be called from within DoExternalNear) can generate two contacts, but the second contact would just be an inner sphere (which we already generated).
                            //DoExternalNear can only generate one contact.  So we only need the first contact!
                            //TODO: This is a fairly fragile connection between the two stages.  Consider robustifying. (Also, the TryInnerSphereContact is done twice! This process is very rare for marginful pairs, though)
                        }
                        else
                        {
                            //Well, it really is just that deep.
                            contactList.Add(ref contact);
                            state = previousState;
                        }
                    }
                    else
                    {
                        //If the external near test finds that there was no collision at all, 
                        //just return to plane testing.  If the point turns up outside the face region
                        //next time, the system will adapt.
                        state = previousState;
                        return false;
                    }
                }
                else
                {
                    contactList.Add(ref contact);
                }
                return true;

            }
            return false;


        }
Пример #46
0
        private bool DoDeepContact(out TinyStructList<ContactData> contactList)
        {


            //Find the origin to triangle center offset.
            Vector3 center;
            Vector3.Add(ref triangle.vA, ref triangle.vB, out center);
            Vector3.Add(ref center, ref triangle.vC, out center);
            Vector3.Multiply(ref center, 1f / 3f, out center);

            ContactData contact;

            contactList = new TinyStructList<ContactData>();

            if (MPRToolbox.AreLocalShapesOverlapping(convex, triangle, ref center, ref Toolbox.RigidIdentity))
            {

                float dot;


                Vector3 triangleNormal, ab, ac;
                Vector3.Subtract(ref triangle.vB, ref triangle.vA, out ab);
                Vector3.Subtract(ref triangle.vC, ref triangle.vA, out ac);
                Vector3.Cross(ref ab, ref ac, out triangleNormal);
                float lengthSquared = triangleNormal.LengthSquared();
                if (lengthSquared < Toolbox.Epsilon * .01f)
                {
                    //Degenerate triangle! That's no good.
                    //Just use the direction pointing from A to B, "B" being the triangle.  That direction is center - origin, or just center.
                    MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref center, out contact.PenetrationDepth, out contact.Normal, out contact.Position);
                }
                else
                {
                    //Normalize the normal.
                    Vector3.Divide(ref triangleNormal, (float)Math.Sqrt(lengthSquared), out triangleNormal);


                    ////The first direction to check is one of the triangle's edge normals.  Choose the one that is most aligned with the offset from A to B.
                    ////Project the direction onto the triangle plane.
                    //Vector3.Dot(ref triangleNormal, ref center, out dot);
                    //Vector3 trianglePlaneDirection;
                    //Vector3.Multiply(ref triangleNormal, dot, out trianglePlaneDirection);
                    //Vector3.Subtract(ref trianglePlaneDirection, ref center, out trianglePlaneDirection);

                    ////To find out which edge to use, compute which region the direction is in.
                    ////This is done by constructing three planes which segment the triangle into three sub-triangles.

                    ////These planes are defined by A, origin, center; B, origin, center; C, origin, center.
                    ////The plane tests against the direction can be reordered to:
                    ////(center x direction) * A
                    ////(center x direction) * B
                    ////(center x direction) * C
                    //Vector3 OxD;
                    //Vector3.Cross(ref trianglePlaneDirection, ref center, out OxD);
                    //Vector3 p;

                    //float dotA, dotB, dotC;
                    //Vector3.Dot(ref triangle.vA, ref OxD, out dotA);
                    //Vector3.Dot(ref triangle.vB, ref OxD, out dotB);
                    //Vector3.Dot(ref triangle.vC, ref OxD, out dotC);

                    //if (dotA >= 0 && dotB <= 0)
                    //{
                    //    //Direction is in the AB edge zone.
                    //    //Compute the edge normal using AB x (AO x AB).
                    //    Vector3 AB, AO;
                    //    Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                    //    Vector3.Subtract(ref center, ref triangle.vA, out AO);
                    //    Vector3.Cross(ref AO, ref AB, out p);
                    //    Vector3.Cross(ref AB, ref p, out trianglePlaneDirection);
                    //}
                    //else if (dotB >= 0 && dotC <= 0)
                    //{
                    //    //Direction is in the BC edge zone.
                    //    //Compute the edge normal using BC x (BO x BC).
                    //    Vector3 BC, BO;
                    //    Vector3.Subtract(ref triangle.vC, ref triangle.vB, out BC);
                    //    Vector3.Subtract(ref center, ref triangle.vB, out BO);
                    //    Vector3.Cross(ref BO, ref BC, out p);
                    //    Vector3.Cross(ref BC, ref p, out trianglePlaneDirection);

                    //}
                    //else // dotC > 0 && dotA < 0
                    //{
                    //    //Direction is in the CA edge zone.
                    //    //Compute the edge normal using CA x (CO x CA).
                    //    Vector3 CA, CO;
                    //    Vector3.Subtract(ref triangle.vA, ref triangle.vC, out CA);
                    //    Vector3.Subtract(ref center, ref triangle.vC, out CO);
                    //    Vector3.Cross(ref CO, ref CA, out p);
                    //    Vector3.Cross(ref CA, ref p, out trianglePlaneDirection);
                    //}



                    //dot = trianglePlaneDirection.LengthSquared();
                    //if (dot > Toolbox.Epsilon)
                    //{
                    //    Vector3.Divide(ref trianglePlaneDirection, (float)Math.Sqrt(dot), out trianglePlaneDirection);
                    //    MPRTesting.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref trianglePlaneDirection, out contact.PenetrationDepth, out contact.Normal);
                    //    //Check to see if the normal is facing in the proper direction, considering that this may not be a two-sided triangle.
                    //    Vector3.Dot(ref triangleNormal, ref contact.Normal, out dot);
                    //    if ((triangle.sidedness == TriangleSidedness.Clockwise && dot > 0) || (triangle.sidedness == TriangleSidedness.Counterclockwise && dot < 0))
                    //    {
                    //        //Normal was facing the wrong way.
                    //        //Instead of ignoring it entirely, correct the direction to as close as it can get by removing any component parallel to the triangle normal.
                    //        Vector3 previousNormal = contact.Normal;
                    //        Vector3.Dot(ref contact.Normal, ref triangleNormal, out dot);

                    //        Vector3.Multiply(ref contact.Normal, dot, out p);
                    //        Vector3.Subtract(ref contact.Normal, ref p, out contact.Normal);
                    //        float length = contact.Normal.LengthSquared();
                    //        if (length > Toolbox.Epsilon)
                    //        {
                    //            //Renormalize the corrected normal.
                    //            Vector3.Divide(ref contact.Normal, (float)Math.Sqrt(length), out contact.Normal);
                    //            Vector3.Dot(ref contact.Normal, ref previousNormal, out dot);
                    //            contact.PenetrationDepth *= dot;
                    //        }
                    //        else
                    //        {
                    //            contact.PenetrationDepth = float.MaxValue;
                    //            contact.Normal = new Vector3();
                    //        }
                    //    }
                    //}
                    //else
                    //{
                    //    contact.PenetrationDepth = float.MaxValue;
                    //    contact.Normal = new Vector3();
                    //}

                    //TODO: This tests all three edge axes with a full MPR raycast.  That's not really necessary; the correct edge normal should be discoverable, resulting in a single MPR raycast.

                    //Find the edge directions that will be tested with MPR.
                    Vector3 AO, BO, CO;
                    Vector3 AB, BC, CA;
                    Vector3.Subtract(ref center, ref triangle.vA, out AO);
                    Vector3.Subtract(ref center, ref triangle.vB, out BO);
                    Vector3.Subtract(ref center, ref triangle.vC, out CO);
                    Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB);
                    Vector3.Subtract(ref triangle.vC, ref triangle.vB, out BC);
                    Vector3.Subtract(ref triangle.vA, ref triangle.vC, out CA);


                    //We don't have to worry about degenerate triangles here because we've already handled that possibility above.
                    Vector3 ABnormal, BCnormal, CAnormal;

                    //Project the center onto the edge to find the direction from the center to the edge AB.
                    Vector3.Dot(ref AO, ref AB, out dot);
                    Vector3.Multiply(ref AB, dot / AB.LengthSquared(), out ABnormal);
                    Vector3.Subtract(ref AO, ref ABnormal, out ABnormal);
                    ABnormal.Normalize();

                    //Project the center onto the edge to find the direction from the center to the edge BC.
                    Vector3.Dot(ref BO, ref BC, out dot);
                    Vector3.Multiply(ref BC, dot / BC.LengthSquared(), out BCnormal);
                    Vector3.Subtract(ref BO, ref BCnormal, out BCnormal);
                    BCnormal.Normalize();

                    //Project the center onto the edge to find the direction from the center to the edge BC.
                    Vector3.Dot(ref CO, ref CA, out dot);
                    Vector3.Multiply(ref CA, dot / CA.LengthSquared(), out CAnormal);
                    Vector3.Subtract(ref CO, ref CAnormal, out CAnormal);
                    CAnormal.Normalize();


                    MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref ABnormal, out contact.PenetrationDepth, out contact.Normal);
                    //Check to see if the normal is facing in the proper direction, considering that this may not be a two-sided triangle.
                    Vector3.Dot(ref triangleNormal, ref contact.Normal, out dot);
                    if ((triangle.sidedness == TriangleSidedness.Clockwise && dot > 0) || (triangle.sidedness == TriangleSidedness.Counterclockwise && dot < 0))
                    {
                        //Normal was facing the wrong way.
                        //Instead of ignoring it entirely, correct the direction to as close as it can get by removing any component parallel to the triangle normal.
                        Vector3 previousNormal = contact.Normal;
                        Vector3.Dot(ref contact.Normal, ref triangleNormal, out dot);

                        Vector3 p;
                        Vector3.Multiply(ref contact.Normal, dot, out p);
                        Vector3.Subtract(ref contact.Normal, ref p, out contact.Normal);
                        float length = contact.Normal.LengthSquared();
                        if (length > Toolbox.Epsilon)
                        {
                            //Renormalize the corrected normal.
                            Vector3.Divide(ref contact.Normal, (float)Math.Sqrt(length), out contact.Normal);
                            Vector3.Dot(ref contact.Normal, ref previousNormal, out dot);
                            contact.PenetrationDepth *= dot;
                        }
                        else
                        {
                            contact.PenetrationDepth = float.MaxValue;
                            contact.Normal = new Vector3();
                        }
                    }



                    Vector3 candidateNormal;
                    float candidateDepth;

                    MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref BCnormal, out candidateDepth, out candidateNormal);
                    //Check to see if the normal is facing in the proper direction, considering that this may not be a two-sided triangle.
                    Vector3.Dot(ref triangleNormal, ref candidateNormal, out dot);
                    if ((triangle.sidedness == TriangleSidedness.Clockwise && dot > 0) || (triangle.sidedness == TriangleSidedness.Counterclockwise && dot < 0))
                    {
                        //Normal was facing the wrong way.
                        //Instead of ignoring it entirely, correct the direction to as close as it can get by removing any component parallel to the triangle normal.
                        Vector3 previousNormal = candidateNormal;
                        Vector3.Dot(ref candidateNormal, ref triangleNormal, out dot);

                        Vector3 p;
                        Vector3.Multiply(ref candidateNormal, dot, out p);
                        Vector3.Subtract(ref candidateNormal, ref p, out candidateNormal);
                        float length = candidateNormal.LengthSquared();
                        if (length > Toolbox.Epsilon)
                        {
                            //Renormalize the corrected normal.
                            Vector3.Divide(ref candidateNormal, (float)Math.Sqrt(length), out candidateNormal);
                            Vector3.Dot(ref candidateNormal, ref previousNormal, out dot);
                            candidateDepth *= dot;
                        }
                        else
                        {
                            contact.PenetrationDepth = float.MaxValue;
                            contact.Normal = new Vector3();
                        }
                    }
                    if (candidateDepth < contact.PenetrationDepth)
                    {
                        contact.Normal = candidateNormal;
                        contact.PenetrationDepth = candidateDepth;
                    }



                    MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref CAnormal, out candidateDepth, out candidateNormal);
                    //Check to see if the normal is facing in the proper direction, considering that this may not be a two-sided triangle.
                    Vector3.Dot(ref triangleNormal, ref candidateNormal, out dot);
                    if ((triangle.sidedness == TriangleSidedness.Clockwise && dot > 0) || (triangle.sidedness == TriangleSidedness.Counterclockwise && dot < 0))
                    {
                        //Normal was facing the wrong way.
                        //Instead of ignoring it entirely, correct the direction to as close as it can get by removing any component parallel to the triangle normal.
                        Vector3 previousNormal = candidateNormal;
                        Vector3.Dot(ref candidateNormal, ref triangleNormal, out dot);

                        Vector3 p;
                        Vector3.Multiply(ref candidateNormal, dot, out p);
                        Vector3.Subtract(ref candidateNormal, ref p, out candidateNormal);
                        float length = candidateNormal.LengthSquared();
                        if (length > Toolbox.Epsilon)
                        {
                            //Renormalize the corrected normal.
                            Vector3.Divide(ref candidateNormal, (float)Math.Sqrt(length), out candidateNormal);
                            Vector3.Dot(ref candidateNormal, ref previousNormal, out dot);
                            candidateDepth *= dot;
                        }
                        else
                        {
                            contact.PenetrationDepth = float.MaxValue;
                            contact.Normal = new Vector3();
                        }
                    }
                    if (candidateDepth < contact.PenetrationDepth)
                    {
                        contact.Normal = candidateNormal;
                        contact.PenetrationDepth = candidateDepth;
                    }



                    //Try the depth along the positive triangle normal.

                    //If it's clockwise, this direction is unnecessary (the resulting normal would be invalidated by the onesidedness of the triangle).
                    if (triangle.sidedness != TriangleSidedness.Clockwise)
                    {
                        MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref triangleNormal, out candidateDepth, out candidateNormal);
                        if (candidateDepth < contact.PenetrationDepth)
                        {
                            contact.Normal = candidateNormal;
                            contact.PenetrationDepth = candidateDepth;
                        }
                    }

                    //Try the depth along the negative triangle normal.

                    //If it's counterclockwise, this direction is unnecessary (the resulting normal would be invalidated by the onesidedness of the triangle).
                    if (triangle.sidedness != TriangleSidedness.Counterclockwise)
                    {
                        Vector3.Negate(ref triangleNormal, out triangleNormal);
                        MPRToolbox.LocalSurfaceCast(convex, triangle, ref Toolbox.RigidIdentity, ref triangleNormal, out candidateDepth, out candidateNormal);
                        if (candidateDepth < contact.PenetrationDepth)
                        {
                            contact.Normal = candidateNormal;
                            contact.PenetrationDepth = candidateDepth;
                        }
                    }




                }



                MPRToolbox.RefinePenetration(convex, triangle, ref Toolbox.RigidIdentity, contact.PenetrationDepth, ref contact.Normal, out contact.PenetrationDepth, out contact.Normal, out contact.Position);

                //It's possible for the normal to still face the 'wrong' direction according to one sided triangles.
                if (triangle.sidedness != TriangleSidedness.DoubleSided)
                {
                    Vector3.Dot(ref triangleNormal, ref contact.Normal, out dot);
                    if (dot < 0)
                    {
                        //Skip the add process.
                        goto InnerSphere;
                    }
                }


                contact.Id = -1;

                if (contact.PenetrationDepth < convex.collisionMargin + triangle.collisionMargin)
                {
                    state = CollisionState.ExternalNear; //If it's emerged from the deep contact, we can go back to using the preferred GJK method.
                }
                contactList.Add(ref contact);
            }

        InnerSphere:

            if (TryInnerSphereContact(out contact))
            {
                contactList.Add(ref contact);
            }
            if (contactList.Count > 0)
                return true;

            state = CollisionState.ExternalSeparated;
            return false;












        }
Пример #47
0
        private bool DoExternalNear(out TinyStructList<ContactData> contactList)
        {

            Vector3 closestA, closestB;


            //Don't bother trying to do any clever caching.  The continually transforming simplex makes it very rarely useful.
            //TODO: Initialize the simplex of the GJK method using the 'true' center of the triangle.
            //If left unmodified, the simplex that is used in GJK will just be a point at 0,0,0, which of course is at the origin.
            //This causes an instant-out, always.  Not good!
            //By giving the contributing simplex the average centroid, it has a better guess.
            Vector3 triangleCentroid;
            Vector3.Add(ref triangle.vA, ref triangle.vB, out triangleCentroid);
            Vector3.Add(ref triangleCentroid, ref triangle.vC, out triangleCentroid);
            Vector3.Multiply(ref triangleCentroid, .33333333f, out triangleCentroid);

            var initialSimplex = new CachedSimplex { State = SimplexState.Point, LocalSimplexB = { A = triangleCentroid } };
            if (GJKToolbox.GetClosestPoints(convex, triangle, ref Toolbox.RigidIdentity, ref Toolbox.RigidIdentity, ref initialSimplex, out closestA, out closestB))
            {
                state = CollisionState.Deep;
                return DoDeepContact(out contactList);
            }
            Vector3 displacement;
            Vector3.Subtract(ref closestB, ref closestA, out displacement);
            float distanceSquared = displacement.LengthSquared();
            float margin = convex.collisionMargin + triangle.collisionMargin;

            contactList = new TinyStructList<ContactData>();
            if (distanceSquared < margin * margin)
            {
                //Try to generate a contact.
                var contact = new ContactData();

                //Determine if the normal points in the appropriate direction given the sidedness of the triangle.
                if (triangle.sidedness != TriangleSidedness.DoubleSided)
                {
                    Vector3 triangleNormal, ab, ac;
                    Vector3.Subtract(ref triangle.vB, ref triangle.vA, out ab);
                    Vector3.Subtract(ref triangle.vC, ref triangle.vA, out ac);
                    Vector3.Cross(ref ab, ref ac, out triangleNormal);
                    float dot;
                    Vector3.Dot(ref triangleNormal, ref displacement, out dot);
                    if (triangle.sidedness == TriangleSidedness.Clockwise && dot > 0)
                        return false;
                    if (triangle.sidedness == TriangleSidedness.Counterclockwise && dot < 0)
                        return false;
                }


                //Displacement is from A to B.  point = A + t * AB, where t = marginA / margin.
                if (margin > Toolbox.Epsilon) //This can be zero! It would cause a NaN if unprotected.
                    Vector3.Multiply(ref displacement, convex.collisionMargin / margin, out contact.Position); //t * AB
                else contact.Position = new Vector3();
                Vector3.Add(ref closestA, ref contact.Position, out contact.Position); //A + t * AB.



                contact.Normal = displacement;
                float distance = (float)Math.Sqrt(distanceSquared);
                Vector3.Divide(ref contact.Normal, distance, out contact.Normal);
                contact.PenetrationDepth = margin - distance;



                contactList.Add(ref contact);
                TryToEscape(ref contact.Position);
                return true;

            }
            //Too far to make a contact- move back to separation.
            state = CollisionState.ExternalSeparated;
            return false;
        }
    public void OnUpdate(ref PlayerState playerState)
    {
        if (playerState == PlayerState.Standing)
            m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;

        m_isJumpDown = Input.GetButton("Jump");
        if (Application.platform == RuntimePlatform.Android)
            m_isJumpDown = Input.touchCount != 0;

        if (m_isJumpDown && m_jumpState == JumpState.Landed && CanJump(playerState))
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > JumpDelayMS)
            {
                m_jumpTimer = (Time.time * 1000.0f);
                m_body.AddForce(new Vector3(0, PlayerJumpHeight, 0), ForceMode.Impulse);
                m_jumpState = JumpState.Jumping;
                playerState = PlayerState.Jumping;
                m_collisionState = CollisionState.None;
            }
        }

        if (m_jumpState == JumpState.Jumping && playerState == PlayerState.Jumping)
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > 2000.0f)
            {
                playerState = PlayerState.FallJumping;
            }
        }

        if (m_ladderClimb.State != LadderState.None)
        {
            if (m_ladderClimb.State != LadderState.JumpOff)
            {
                playerState = PlayerState.UpALadder;
                m_collisionState = CollisionState.None;
                m_ladderClimb.CallOnUpdate(m_collisionState);
            }
            else
                playerState = PlayerState.Jumping;

            if (m_ladderClimb.State == LadderState.JumpOff && m_jumpState != JumpState.Jumping)
            {
                if (Input.GetAxis("Horizontal") == 0.0f)
                {
                    m_ladderClimb.State = LadderState.AtMiddle;
                    m_collisionState = CollisionState.None;
                    playerState = PlayerState.UpALadder;
                    return;
                }

                m_jumpTimer = (Time.time * 1000.0f);
                m_body.AddForce(new Vector3(0, PlayerJumpHeight, 0), ForceMode.Impulse);
                m_jumpState = JumpState.Jumping;
                playerState = PlayerState.Jumping;
                m_velocity = Input.GetAxis("Horizontal") * -2.0f;
                m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
                m_velocityLockTimer = (Time.time * 1000.0f);
            }
        }
    }
Пример #49
0
        private bool DoDeepContact(out ContactData contact)
        {
           
            #region Informed search
            if (previousState == CollisionState.Separated) //If it was shallow before, then its closest points will be used to find the normal.
            {
                //It's overlapping! Find the relative velocity at the point relative to the two objects.  The point is still in local space!
                //Vector3 velocityA;
                //Vector3.Cross(ref contact.Position, ref collidableA.entity.angularVelocity, out velocityA);
                //Vector3.Add(ref velocityA, ref collidableA.entity.linearVelocity, out velocityA);
                //Vector3 velocityB;
                //Vector3.Subtract(ref contact.Position, ref localTransformB.Position, out velocityB);
                //Vector3.Cross(ref velocityB, ref collidableB.entity.angularVelocity, out velocityB);
                //Vector3.Add(ref velocityB, ref collidableB.entity.linearVelocity, out velocityB);
                ////The velocity is negated because the direction so point backwards along the velocity.
                //Vector3.Subtract(ref velocityA, ref velocityB, out localDirection);

                //The above takes into account angular velocity, but linear velocity alone is a lot more stable and does the job just fine.
                if (collidableA.entity != null && collidableB.entity != null)
                    Vector3.Subtract(ref collidableA.entity.linearVelocity, ref collidableB.entity.linearVelocity, out localDirection);
                else
                    localDirection = localSeparatingAxis;

                if (localDirection.LengthSquared() < Toolbox.Epsilon)
                {
                    localDirection = Vector3.Up;
                }

            }
            if (MPRToolbox.GetContact(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, ref localDirection, out contact))
            {
                if (contact.PenetrationDepth < collidableA.Shape.collisionMargin + collidableB.Shape.collisionMargin)
                    state = CollisionState.ShallowContact;
                return true;
            }
            //This is rare, but could happen.
            state = CollisionState.Separated;
            return false;

            //if (MPRTesting.GetLocalOverlapPosition(collidableA.Shape, collidableB.Shape, ref localTransformB, out contact.Position))
            //{


            //    //First, try to use the heuristically found direction.  This comes from either the GJK shallow contact separating axis or from the relative velocity.
            //    Vector3 rayCastDirection;
            //    float lengthSquared = localDirection.LengthSquared();
            //    if (lengthSquared > Toolbox.Epsilon)
            //    {
            //        Vector3.Divide(ref localDirection, (float)Math.Sqrt(lengthSquared), out rayCastDirection);// (Vector3.Normalize(localDirection) + Vector3.Normalize(collidableB.worldTransform.Position - collidableA.worldTransform.Position)) / 2;
            //        MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref rayCastDirection, out contact.PenetrationDepth, out contact.Normal);
            //    }
            //    else
            //    {
            //        contact.PenetrationDepth = float.MaxValue;
            //        contact.Normal = Toolbox.UpVector;
            //    }
            //    //Try the offset between the origins as a second option.  Sometimes this is a better choice than the relative velocity.
            //    //TODO: Could use the position-finding MPR iteration to find the A-B direction hit by continuing even after the origin has been found (optimization).
            //    Vector3 normalCandidate;
            //    float depthCandidate;
            //    lengthSquared = localTransformB.Position.LengthSquared();
            //    if (lengthSquared > Toolbox.Epsilon)
            //    {
            //        Vector3.Divide(ref localTransformB.Position, (float)Math.Sqrt(lengthSquared), out rayCastDirection);
            //        MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref rayCastDirection, out depthCandidate, out normalCandidate);
            //        if (depthCandidate < contact.PenetrationDepth)
            //        {
            //            contact.Normal = normalCandidate;
            //        }
            //    }


            //    //Correct the penetration depth.
            //    MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref contact.Normal, out contact.PenetrationDepth, out rayCastDirection);


            //    ////The local casting can optionally continue.  Eventually, it will converge to the local minimum.
            //    //while (true)
            //    //{
            //    //    MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref contact.Normal, out depthCandidate, out normalCandidate);
            //    //    if (contact.PenetrationDepth - depthCandidate <= Toolbox.BigEpsilon)
            //    //        break;

            //    //    contact.PenetrationDepth = depthCandidate;
            //    //    contact.Normal = normalCandidate;
            //    //}

            //    contact.Id = -1;
            //    //we're still in local space! transform it all back.
            //    Matrix3X3 orientation;
            //    Matrix3X3.CreateFromQuaternion(ref collidableA.worldTransform.Orientation, out orientation);
            //    Matrix3X3.Transform(ref contact.Normal, ref orientation, out contact.Normal);
            //    //Vector3.Negate(ref contact.Normal, out contact.Normal);
            //    Matrix3X3.Transform(ref contact.Position, ref orientation, out contact.Position);
            //    Vector3.Add(ref contact.Position, ref collidableA.worldTransform.Position, out contact.Position);
            //    if (contact.PenetrationDepth < collidableA.Shape.collisionMargin + collidableB.Shape.collisionMargin)
            //        state = CollisionState.ShallowContact;
            //    return true;
            //}

            ////This is rare, but could happen.
            //state = CollisionState.Separated;
            //contact = new ContactData();
            //return false;
            #endregion

            #region Testing
            //RigidTransform localTransformB;
            //MinkowskiToolbox.GetLocalTransform(ref collidableA.worldTransform, ref collidableB.worldTransform, out localTransformB); 
            //contact.Id = -1;
            //if (MPRTesting.GetLocalOverlapPosition(collidableA.Shape, collidableB.Shape, ref localTransformB, out contact.Position))
            //{
            //    Vector3 rayCastDirection = localTransformB.Position;
            //    MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref rayCastDirection, out contact.PenetrationDepth, out contact.Normal);
            //    MPRTesting.LocalSurfaceCast(collidableA.Shape, collidableB.Shape, ref localTransformB, ref contact.Normal, out contact.PenetrationDepth, out rayCastDirection);
            //    RigidTransform.Transform(ref contact.Position, ref collidableA.worldTransform, out contact.Position);
            //    Vector3.Transform(ref contact.Normal, ref collidableA.worldTransform.Orientation, out contact.Normal);
            //    return true;
            //}
            //contact.Normal = new Vector3();
            //contact.PenetrationDepth = 0;
            //return false;
            #endregion

            #region v0.15.2 and before
            //if (MPRToolbox.AreObjectsColliding(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, out contact))
            //{
            //    if (contact.PenetrationDepth < collidableA.Shape.collisionMargin + collidableB.Shape.collisionMargin)
            //        state = CollisionState.ShallowContact; //If it's emerged from the deep contact, we can go back to using the preferred GJK method.
            //    return true;
            //}
            ////This is rare, but could happen.
            //state = CollisionState.Separated;
            //return false;
            #endregion

        }
Пример #50
0
  // to retain start cycle events
 protected virtual void Awake()
  {
      inputState = GetComponent<InputState>();
      rb = GetComponent<Rigidbody2D>();
      collisionState = GetComponent<CollisionState>(); ;
  }
Пример #51
0
		public void testCollisions( ref Vector2 motion, Rectangle boxColliderBounds, CollisionState collisionState )
		{
			_boxColliderBounds = boxColliderBounds;

			// save off our current grounded state which we will use for wasGroundedLastFrame and becameGroundedThisFrame
			collisionState.wasGroundedLastFrame = collisionState.below;

			// reset our collisions state
			collisionState.reset( ref motion );

			// reset rounded motion for us while dealing with subpixel movement so fetch the rounded values to use for our actual detection
			var motionX = (int)motion.X;
			var motionY = (int)motion.Y;

			// first, check movement in the horizontal dir
			if( motionX != 0 )
			{
				var direction = motionX > 0 ? Edge.Right : Edge.Left;
				var sweptBounds = collisionRectForSide( direction, motionX );

				int collisionResponse;
				if( testMapCollision( sweptBounds, direction, collisionState, out collisionResponse ) )
				{
					// react to collision. get the distance between our leading edge and what we collided with
					motion.X = collisionResponse - boxColliderBounds.getSide( direction );
					collisionState.left = direction == Edge.Left;
					collisionState.right = direction == Edge.Right;
					collisionState._movementRemainderX.reset();
				}
				else
				{
					collisionState.left = false;
					collisionState.right = false;
				}
			}

			// next, check movement in the vertical dir
			{
				var direction = motionY >= 0 ? Edge.Bottom : Edge.Top;
				var sweptBounds = collisionRectForSide( direction, motionY );
				sweptBounds.X += (int)motion.X;

				int collisionResponse;
				if( testMapCollision( sweptBounds, direction, collisionState, out collisionResponse ) )
				{
					// react to collision. get the distance between our leading edge and what we collided with
					motion.Y = collisionResponse - boxColliderBounds.getSide( direction );
					collisionState.above = direction == Edge.Top;
					collisionState.below = direction == Edge.Bottom;
					collisionState._movementRemainderY.reset();

					if( collisionState.below && collisionState._lastGroundTile != null && collisionState._lastGroundTile.isSlope() )
						collisionState.slopeAngle = MathHelper.ToDegrees( (float)Math.Atan( collisionState._lastGroundTile.getSlope() ) );
				}
				else
				{
					collisionState.above = false;
					collisionState.below = false;
					collisionState._lastGroundTile = null;
				}


				// when moving down we also check for collisions in the opposite direction. this needs to be done so that ledge bumps work when
				// a jump is made but misses by the colliderVerticalInset
				if( direction == Edge.Bottom )
				{
					direction = direction.oppositeEdge();
					sweptBounds = collisionRectForSide( direction, 0 );
					sweptBounds.X += (int)motion.X;
					sweptBounds.Y += (int)motion.Y;

					if( testMapCollision( sweptBounds, direction, collisionState, out collisionResponse ) )
					{
						// react to collision. get the distance between our leading edge and what we collided with
						motion.Y = collisionResponse - boxColliderBounds.getSide( direction );
						// if we collide here this is an overlap of a slope above us. this small bump down will prevent hitches when hitting
						// our head on a slope that connects to a solid tile. It puts us below the slope when the normal response would put us
						// above it
						motion.Y += 2;
						collisionState.above = true;
					}
				}
			}

			// set our becameGrounded state based on the previous and current collision state
			if( !collisionState.wasGroundedLastFrame && collisionState.below )
				collisionState.becameGroundedThisFrame = true;
		}
Пример #52
0
		bool testMapCollision( Rectangle collisionRect, Edge direction, CollisionState collisionState, out int collisionResponse )
		{
			collisionResponse = 0;
			var side = direction.oppositeEdge();
			var perpindicularPosition = side.isVertical() ? collisionRect.Center.X : collisionRect.Center.Y;
			var leadingPosition = collisionRect.getSide( direction );
			var shouldTestSlopes = side.isVertical();
			populateCollidingTiles( collisionRect, direction );

			for( var i = 0; i < _collidingTiles.Count; i++ )
			{
				if( _collidingTiles[i] == null )
					continue;

				// disregard horizontal collisions if the last tile we were grounded on was a slope. Our y movement will push us up on the slope.
				// this is not a fantastic solution
				if( direction.isHorizontal() && collisionState._lastGroundTile != null && collisionState._lastGroundTile.isSlope() && _collidingTiles[i].isSlope() )
					return false;
				
				if( testTileCollision( _collidingTiles[i], side, perpindicularPosition, leadingPosition, shouldTestSlopes, out collisionResponse ) )
				{
					// store off our last ground tile if we collided below
					if( direction == Edge.Bottom )
					{
						collisionState._lastGroundTile = _collidingTiles[i];
						collisionState.isGroundedOnOneWayPlatform = collisionState._lastGroundTile.isOneWayPlatform();
					}
					
					return true;
				}

				// special case for sloped ground tiles
				if( collisionState._lastGroundTile != null && direction == Edge.Bottom )
				{
					// if grounded on a slope and intersecting a slope or if grounded on a wall and intersecting a tall slope we go sticky.
					// tall slope here means one where the the slopeTopLeft/Right is 0, i.e. it connects to a wall
					var isHighSlopeNearest = _collidingTiles[i].getNearestEdge( perpindicularPosition ) == _collidingTiles[i].getHighestSlopeEdge();
					if( ( collisionState._lastGroundTile.isSlope() && _collidingTiles[i].isSlope() ) || ( !collisionState._lastGroundTile.isSlope() && isHighSlopeNearest ) )
					{
						// store off our last ground tile if we collided below
						collisionState._lastGroundTile = _collidingTiles[i];
						return true;
					}
				}
			}

			return false;
		}
    /*
     * \brief Works out if a value is almost another value (for floating point accuracy)
    */
    public void CallOnCollisionEnter(Collision collision)
    {
        m_collisionState = CollisionState.None;

        foreach (ContactPoint contact in collision)
        {
            m_platform = contact.otherCollider.gameObject.GetComponent<CSceneObjectPlatform>();
            if (m_platform != null) {
                m_platform.resetDeltaA();
            }
            if (isNearly(contact.normal.y, 1.0f, 0.2f))
            {
                m_collisionState = CollisionState.OnFloor;

                // are we on a special material?
                m_footMaterial = FootMaterial.Stone;
                if (contact.otherCollider.tag == "Wood Object")
                    m_footMaterial = FootMaterial.Wood;
                else if (contact.otherCollider.tag == "Metal Object")
                    m_footMaterial = FootMaterial.Metal;

            }
            else if (isNearly(contact.normal.y, -1.0f, 0.2f))
            {
                m_collisionState = CollisionState.OnRoof;
            }
            else
            {
                m_collisionState = CollisionState.OnWall;
                m_ladderClimb.State = LadderState.None;
            }
        }

        if (m_collisionState == CollisionState.OnFloor)
        {
            if (m_jumpState != JumpState.Landed)
                m_player.GetPlayerAnimation().PlayFootstepAudio(m_footMaterial);

            m_jumpState = JumpState.Landed;
            m_ladderClimb.State = LadderState.None;

            if (m_player.GetPlayerState() != PlayerState.Turning) m_player.SetPlayerState(PlayerState.Standing);

            //m_ledgeGrabBox.collider.enabled = true;
        }
    }
    /*
     * \brief Called whilst a collision is taking place
    */
    public void CallOnCollisionStay(Collision collision, ref PlayerState playerState, ref float playerAlpha)
    {
        m_collisionState = CollisionState.None;

        foreach (ContactPoint contact in collision)
        {
            Debug.DrawRay(contact.point, contact.normal);

            //
            if (contact.otherCollider != null && contact.otherCollider.gameObject != null)
            {
                CSceneObjectPlatform platform = contact.otherCollider.gameObject.GetComponent<CSceneObjectPlatform>();
                if (platform != null && m_platform == null) {
                    m_platform = platform;
                    m_platform.resetDeltaA();
                }
            }

            //
            CSceneObject obj = null;
            if (contact.otherCollider)
            {
                obj = contact.otherCollider.gameObject.GetComponent<CSceneObject>();
                if (obj == null && contact.otherCollider.gameObject.transform.parent != null) {
                    GameObject parent = contact.otherCollider.gameObject.transform.parent.gameObject;
                    if (parent != null) {
                        obj = parent.GetComponent<CSceneObject>();
                    }
                }
            }

            if (contact.thisCollider != null && contact.thisCollider.gameObject != null && contact.thisCollider.gameObject.name == "Ledge_Grab_Detection" && (obj == null || obj.CanLedgeGrab))
            {
                if(CSceneObject.CheckLedgeGrab(collision))
                    continue;
            }

            if (contact.otherCollider != null && contact.otherCollider.gameObject != null && contact.otherCollider.gameObject.name == "Ledge_Grab_Detection" && (obj == null || obj.CanLedgeGrab))
            {
                if (CSceneObject.CheckLedgeGrab(collision))
                    continue;
            }

            // wall jumping
            if (obj != null && obj.CanWallJump == true && m_jumpState != JumpState.Landed && !isNearly(contact.normal.y, 1.0f, 0.2f) && !isNearly(contact.normal.y, -1.0f, 0.1f))
            {
                m_collisionState = CollisionState.OnWall;
                playerState = PlayerState.WallJumpStart;
                m_jumpTimer = (Time.time * 1000.0f);
                m_body.constraints = RigidbodyConstraints.FreezeAll;
                m_velocity = 0.0f;
                m_wallJump.StartHangTime = Time.time * 1000.0f;
            }
            // floor check
            else if (isNearly(contact.normal.y, 1.0f, 0.8f))
            {
                m_collisionState = CollisionState.OnFloor;
                if (!isNearly(contact.normal.y, 1.0f, 0.15f) && collision.contacts.Length == 1)
                {
                    m_velocity = (m_movingDirection * 0.15f);
                    m_velocityLockTimer = (Time.time * 1000.0f);
                }

                // are we on a special material?
                m_footMaterial = FootMaterial.Stone;
                if (contact.otherCollider.tag == "Wood Object")
                    m_footMaterial = FootMaterial.Wood;
                else if (contact.otherCollider.tag == "Metal Object")
                    m_footMaterial = FootMaterial.Metal;
            }
            // head check
            else if (isNearly(contact.normal.y, -1.0f, 0.1f))
            {
                m_collisionState = CollisionState.OnRoof;
            }
            // wall check
            else
            {
                if (isFacingCollision(m_movingDirection, m_body.transform.position, contact.point, playerAlpha)) {
                    m_collisionState = CollisionState.OnWall;
                    break;
                }
            }
        }

        if (m_collisionState == CollisionState.OnWall && m_jumpState == JumpState.Jumping && playerState != PlayerState.WallJumpStart)
        {
            m_velocity = -(m_movingDirection * 0.15f);
        }

        if (m_collisionState == CollisionState.OnFloor && ((Time.time * 1000.0f) - m_jumpTimer > 200.0f))
        {
            m_jumpState = JumpState.Landed;

            if (m_ladderClimb.State != LadderState.AtBase)
            {
                m_ladderClimb.State = LadderState.None;
            }
            else
            {
                playerState = PlayerState.UpALadder;
            }

            if (m_player.GetPlayerState() != PlayerState.Turning) m_player.SetPlayerState(PlayerState.Standing);
            //m_ledgeGrabBox.collider.enabled = true;
        }
    }
    public void CallOnTriggerStay(Collider collider, ref PlayerState playerState)
    {
        CSceneObject obj = collider.gameObject.GetComponent<CSceneObject>();
        if (obj == null && collider.gameObject != null && collider.gameObject.transform.parent != null) {
            GameObject parent = collider.gameObject.transform.parent.gameObject;
            if (parent != null) {
                obj = parent.GetComponent<CSceneObject>();
            }
        }

        if (obj != null && obj.IsLadder && (m_ladderClimb.State != LadderState.JumpOff)) {
            m_ladderClimb.CallOnTriggerStay(collider, ref playerState);
            if (m_ladderClimb.State != LadderState.None) {
                m_body.constraints = RigidbodyConstraints.FreezeAll;
            }
            else
            {
                m_collisionState = CollisionState.OnFloor;
            }
            return;
        }
    }
    public void OnUpdate(ref PlayerState playerState)
    {
        if (playerState == PlayerState.Standing)
        {
            m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
            m_fakeJump = false;

            if (GetLadder.state != LadderState.AtBase)
            {
                // standing, we can't be on a ladder
                GetLadder.state = LadderState.None;
                GetLadder.offset = 0.0f;
                GetLadder.moving = false;
                GetLadder.direction = 0.0f;
            }
        }

        bool wasJump = m_isJumpDown;
        m_isJumpDown = Input.GetButtonDown("Jump");

        if (Application.platform == RuntimePlatform.Android)
            m_isJumpDown = Input.touchCount != 0;

        if (m_isJumpDown && !wasJump)
        {
            m_canJumpFromLedge = true;
        }
        else
        {
            m_canJumpFromLedge = false;
        }

        if (m_isJumpDown && m_jumpState == JumpState.Landed && CanJump(playerState))
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > JumpDelayMS)
            {
                m_jumpTimer = (Time.time * 1000.0f);
                m_body.AddForce(new Vector3(0, PlayerJumpHeight, 0), ForceMode.Impulse);
                m_jumpState = JumpState.Jumping;
                playerState = PlayerState.Jumping;
                m_collisionState = CollisionState.None;
            }
        }

        if (m_jumpState == JumpState.Jumping && playerState == PlayerState.Jumping)
        {
            if ((Time.time * 1000.0f) - m_jumpTimer > 2000.0f)
            {
                playerState = PlayerState.FallJumping;
                if (!m_fakeJump && ((Time.time * 1000.0f) - m_jumpTimer > 3000.0f))
                {
                    m_player.PushPlayerFromTower();
                }
            }
        }

        if (m_isJumpDown == true && (GetLadder.state == LadderState.OnMiddle || GetLadder.state == LadderState.OnTop))
        {
            GetLadder.state = LadderState.JumpingOff;
            m_jumpTimer = (Time.time * 1000.0f);
            m_body.velocity = Vector3.zero;
            m_body.AddForce(new Vector3(0, PlayerJumpHeight, 0), ForceMode.Impulse);
            m_jumpState = JumpState.Jumping;
            playerState = PlayerState.Jumping;
            m_collisionState = CollisionState.None;
            rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
        }

        // LADDER CODE

        float updown = (Input.GetAxis("Vertical") * 0.001f);
        if (updown > 0.0f)
        {
            if (GetLadder.state == LadderState.AtBase)
            {
                if (m_jumpState == JumpState.Jumping) {
                    GetLadder.state = LadderState.OnMiddle;
                } else {
                    GetLadder.state = LadderState.OnBase;
                }
                playerState = PlayerState.OnLadder;
                m_collisionState = CollisionState.None;
                m_jumpState = JumpState.Landed;
            }
            else if (GetLadder.state == LadderState.OnBase || GetLadder.state == LadderState.OnMiddle)
            {
                GetLadder.offset = (updown * 10.0f);
                GetLadder.moving = true;
                GetLadder.direction = 1.0f;
            }
            else if (GetLadder.state == LadderState.OnTop)
            {
                GetLadder.moving = false;
                GetLadder.direction = 0.0f;
                GetLadder.offset = 0.0f;
            }
        }
        else if (updown < 0.0f)
        {
            if (GetLadder.state == LadderState.OnBase)
            {
                GetLadder.state = LadderState.AtBase;
                playerState = PlayerState.Standing;
                rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
                rigidbody.AddForce(0, 0.1f, 0);
            }
            else if (GetLadder.state == LadderState.OnBase || GetLadder.state == LadderState.OnMiddle || GetLadder.state == LadderState.OnTop)
            {
                GetLadder.offset = (updown * 10.0f);
                GetLadder.moving = true;
                GetLadder.direction = -1.0f;
            }
        }

        if (updown == 0.0f && GetLadder.state != LadderState.None)
        {
            GetLadder.moving = false;
            GetLadder.direction = 0.0f;
            GetLadder.offset = 0.0f;
        }
    }
Пример #57
0
        private bool DoShallowContact(out ContactData contact)
        {
            Vector3 closestA, closestB;

            //RigidTransform transform = RigidTransform.Identity;
            //Vector3 closestAnew, closestBnew;
            //CachedSimplex cachedTest = cachedSimplex;
            //bool intersecting = GJKToolbox.GetClosestPoints(informationA.Shape, informationB.Shape, ref informationA.worldTransform, ref informationB.worldTransform, ref cachedTest, out closestAnew, out closestBnew);

            ////bool otherIntersecting = OldGJKVerifier.GetClosestPointsBetweenObjects(informationA.Shape, informationB.Shape, ref informationA.worldTransform, ref informationB.worldTransform, 0, 0, out closestA, out closestB);
            //bool otherIntersecting = GJKToolbox.GetClosestPoints(informationA.Shape, informationB.Shape, ref informationA.worldTransform, ref informationB.worldTransform, out closestA, out closestB);

            //Vector3 closestAold, closestBold;
            //bool oldIntersecting = OldGJKVerifier.GetClosestPointsBetweenObjects(informationA.Shape, informationB.Shape, ref informationA.worldTransform, ref informationB.worldTransform, 0, 0, out closestAold, out closestBold);

            //if (otherIntersecting != intersecting || (!otherIntersecting && !intersecting &&
            //    Vector3.DistanceSquared(closestAnew, closestBnew) - Vector3.DistanceSquared(closestA, closestB) > .0001f &&
            //    (Vector3.DistanceSquared(closestA, closestAnew) > .0001f ||
            //    Vector3.DistanceSquared(closestB, closestBnew) > .0001f)))// ||
            //    //Math.Abs(Vector3.Dot(closestB - closestA, closestBnew - closestAnew) - Vector3.Dot(closestB - closestA, closestB - closestA)) > Toolbox.Epsilon)))
            //    Debug.WriteLine("Break.");

            //Vector3 sub;
            //Vector3.Subtract(ref closestA, ref closestB, out sub);
            //if (sub.LengthSquared() < Toolbox.Epsilon)

            bool intersecting;
            if (UseSimplexCaching)
                intersecting = GJKToolbox.GetClosestPoints(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, ref cachedSimplex, out closestA, out closestB);
            else
            {
                //The initialization of the pair creates a pretty decent simplex to start from.
                //Just don't try to update it.
                CachedSimplex preInitializedSimplex = cachedSimplex;
                intersecting = GJKToolbox.GetClosestPoints(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, ref preInitializedSimplex, out closestA, out closestB);
            }

            Vector3 displacement;
            Vector3.Subtract(ref closestB, ref closestA, out displacement);
            if (intersecting)
            //if (OldGJKVerifier.GetClosestPointsBetweenObjects(informationA.Shape, informationB.Shape, ref informationA.worldTransform, ref informationB.worldTransform, 0, 0, out closestA, out closestB))
            {
                state = CollisionState.DeepContact;
                return DoDeepContact(out contact);
            }

            localDirection = displacement; //Use this as the direction for future deep contacts.
            float distanceSquared = displacement.LengthSquared();
            float margin = collidableA.Shape.collisionMargin + collidableB.Shape.collisionMargin;


            if (distanceSquared < margin * margin)
            {
                //Generate a contact.
                contact = new ContactData();
                //Displacement is from A to B.  point = A + t * AB, where t = marginA / margin.
                if (margin > Toolbox.Epsilon) //Avoid a NaN!
                    Vector3.Multiply(ref displacement, collidableA.Shape.collisionMargin / margin, out contact.Position); //t * AB
                else
                    contact.Position = new Vector3();

                Vector3.Add(ref closestA, ref contact.Position, out contact.Position); //A + t * AB.


                contact.Normal = displacement;
                float distance = (float)Math.Sqrt(distanceSquared);
                Vector3.Divide(ref contact.Normal, distance, out contact.Normal);
                contact.PenetrationDepth = margin - distance;
                return true;

            }
            //Too shallow to make a contact- move back to separation.
            state = CollisionState.Separated;
            contact = new ContactData();
            return false;
        }
Пример #58
0
        private bool DoExternalSeparated(out TinyStructList<ContactData> contactList)
        {

            if (GJKToolbox.AreShapesIntersecting(convex, triangle, ref Toolbox.RigidIdentity, ref Toolbox.RigidIdentity, ref localSeparatingAxis))
            {
                state = CollisionState.ExternalNear;
                return DoExternalNear(out contactList);
            }
            TryToEscape();
            contactList = new TinyStructList<ContactData>();
            return false;
        }
Пример #59
0
		/// <summary>
		/// moves the Entity taking into account the tiled map
		/// </summary>
		/// <param name="motion">Motion.</param>
		/// <param name="boxCollider">Box collider.</param>
		public void move( Vector2 motion, BoxCollider boxCollider, CollisionState collisionState )
		{
			// test for collisions then move the Entity
			testCollisions( ref motion, boxCollider.bounds, collisionState );

			boxCollider.unregisterColliderWithPhysicsSystem();
			boxCollider.entity.transform.position += motion;
			boxCollider.registerColliderWithPhysicsSystem();
		}
    /*
     * \brief Called on player update
    */
    public void OnFixedUpdate(ref PlayerState playerState)
    {
        if (playerState == PlayerState.FallingFromTower)
            return;

        float velocity = (Input.GetAxis("Horizontal") * MaxSpeed) * m_invert;
        if (Application.platform == RuntimePlatform.Android)
            velocity = Input.acceleration.y;

        if ((Time.time * 1000.0f) - m_velocityLockTimer < 100)
        {
            velocity = m_velocity;
        }

        if (m_ladderClimb.State == LadderState.AtMiddle || m_ladderClimb.State == LadderState.AtTop)
            velocity = 0;

        int direction = isNearly(velocity, 0.0f, 0.1f) ? 0 : velocity > 0 ? 1 : -1;

        //platform update
        if (m_platform && m_collisionState == CollisionState.OnFloor) {
            m_platformVelocity += m_platform.DeltaA;
            m_platform.resetDeltaA();
        }

        // Ledge hanging code start
        if (playerState == PlayerState.LedgeHang || playerState == PlayerState.LedgeClimb || playerState == PlayerState.LedgeClimbComplete) {

            m_velocity = 0.0f;

            // If we are trying to move in the opposite way of the wall, fall off the wall
            if (direction != 0 && direction != m_movingDirection) {
                m_velocity = velocity * 4.0f;
                playerState = PlayerState.Walking;
                m_jumpState = JumpState.Landed;
                m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
            //	m_ledgeGrabBox.collider.enabled = true;
                m_movingDirection *= -1;
                m_direction *= -1;
                m_collisionState = CollisionState.None;

            //	Transform t = m_ledgeGrabBox.transform;
            //	t.localPosition = new Vector3(m_direction > 0 ? -0.18f : 0.18f, t.localPosition.y, t.localPosition.z);
                return;
            }

            // if the player is not already climbing the wall, check keys
            if (playerState != PlayerState.LedgeClimb)
            {
                // if the user pressed up, climb the wall
                if (Input.GetAxis("Vertical") > 0 && playerState != PlayerState.LedgeClimbComplete) {
                    playerState = PlayerState.LedgeClimb;
                    m_jumpState = JumpState.Landed;
                //	m_ledgeGrabBox.collider.enabled = false;
                }
                // if the user pressed space, jump off the wall
                else if (m_isJumpDown) {
                    m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
                    m_velocity = -(m_movingDirection) * 4.0f; // kick it away from the wall
                    m_body.AddForce(new Vector3(0, PlayerJumpHeight * 0.25f, 0), ForceMode.Impulse);
                    playerState = PlayerState.Jumping;
                    m_collisionState = CollisionState.None;
                    m_movingDirection *= -1;
                    m_direction *= -1;
                //	m_ledgeGrabBox.collider.enabled = true;

                //	Transform t = m_ledgeGrabBox.transform;
                //	t.localPosition = new Vector3(m_direction > 0 ? -0.18f : 0.18f, t.localPosition.y, t.localPosition.z);
                }
                return;
            }

            return;
        }
        // Ledge hanging code end

        if (playerState == PlayerState.WallJumpStart)
        {
            if ((Time.time * 1000.0f) - m_wallJump.StartHangTime > m_wallJump.WallHangTime) {
                m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
                m_velocity = -m_movingDirection;
                playerState = PlayerState.Walking;
                m_jumpState = JumpState.Landed;
            } else if (m_isJumpDown && direction != 0 && direction != m_movingDirection) {
                m_body.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
                m_velocity = -(m_movingDirection); // kick it away from the wall
                m_body.AddForce(new Vector3(0, PlayerJumpHeight * 1.1f, 0), ForceMode.Impulse);
                playerState = PlayerState.Jumping;
                m_jumpTimer = (Time.time * 1000.0f);
                m_collisionState = CollisionState.None;
                m_movingDirection *= -1;
                m_direction *= -1;
            }
            return;
        }

        if (!(m_collisionState == CollisionState.OnWall && m_jumpState == JumpState.Jumping))
            m_velocity = velocity;

        int lastDirection = m_direction;
        int lastMovingDirection = m_movingDirection;

        if (playerState != PlayerState.Turning)
        {
            m_direction = direction;
            if (m_direction != 0) m_movingDirection = m_direction;
        }

        if (m_collisionState != CollisionState.None && m_jumpState != JumpState.Jumping)
        {
            if (m_direction == 0 && playerState != PlayerState.Turning)
            {
                playerState = PlayerState.Standing;
            }
            else
            {
                if (playerState == PlayerState.Turning)
                {
                    m_velocity = 0.0f;
                    return;
                }

                // are we tuning round?
                if (lastDirection != direction && ((Time.time * 1000.0f) - m_turnLockTimer > 1000.0f))
                {
                    playerState = PlayerState.Walking;
                    if (m_velocity != 0.0f && lastMovingDirection != m_direction)
                    {
                        playerState = PlayerState.Turning;
                        m_velocity = 0.0f;
                        m_turnLockTimer = Time.time * 1000.0f;
                    }
                }
                else
                    playerState = PlayerState.Walking;
            }
        }
    }