コード例 #1
0
ファイル: Entity.cs プロジェクト: HuskyGameDev/2020s-team5
    private bool TestTileCollision(World world, AABB a, AABB b, Vector2 delta, ref float tMin, ref Vector2 normal)
    {
        bool result = false;

        b.Expand(a.radius);
        a.Shrink(a.radius);

        Vector2Int tPos = Utils.TilePos(b.center);
        Vector2    wMin = b.center - b.radius, wMax = b.center + b.radius;

        Tile up    = world.GetTile(tPos.x, tPos.y + 1);
        Tile down  = world.GetTile(tPos.x, tPos.y - 1);
        Tile left  = world.GetTile(tPos.x - 1, tPos.y);
        Tile right = world.GetTile(tPos.x + 1, tPos.y);

        // Top surface.
        if (TileManager.GetData(up).passable&& TestWall(delta, a.center, wMax.y, wMin, wMax, 1, 0, ref tMin))
        {
            normal = Vector2.up;

            if (delta.y < 0.0f)
            {
                colFlags |= CollideFlags.Below;
                result    = true;
            }
        }

        // Bottom surface.
        if (TileManager.GetData(down).passable&& TestWall(delta, a.center, wMin.y, wMin, wMax, 1, 0, ref tMin))
        {
            normal    = Vector2.down;
            colFlags |= CollideFlags.Above;
            result    = true;
        }

        // Left wall.
        if (TileManager.GetData(left).passable&& TestWall(delta, a.center, wMin.x, wMin, wMax, 0, 1, ref tMin))
        {
            normal    = Vector2.left;
            colFlags |= CollideFlags.Left;
            result    = true;
        }

        // Right wall.
        if (TileManager.GetData(right).passable&& TestWall(delta, a.center, wMax.x, wMin, wMax, 0, 1, ref tMin))
        {
            normal    = Vector2.right;
            colFlags |= CollideFlags.Right;
            result    = true;
        }

        return(result);
    }
コード例 #2
0
ファイル: Entity.cs プロジェクト: HuskyGameDev/2020s-team5
    public void Move(Vector2 accel, float gravity)
    {
        if (disabled)
        {
            return;
        }

        facingLockTime -= Time.deltaTime;
        KillOnOverlap();

        moveState = MoveState.Normal;

        accel *= speed;
        accel += velocity * friction;

        if (gravity != 0.0f)
        {
            accel.y = gravity;
        }

        // Using the following equations of motion:

        // - p' = 1/2at^2 + vt + p.
        // - v' = at + v.
        // - a = specified by input.

        // Where a = acceleration, v = velocity, and p = position.
        // v' and p' denote new versions, while non-prime denotes old.

        // These are found by integrating up from acceleration to velocity. Use derivation
        // to go from position down to velocity and then down to acceleration to see how
        // we can integrate back up.
        Vector2 delta = accel * 0.5f * Utils.Square(Time.deltaTime) + velocity * Time.deltaTime;

        if (swimming)
        {
            velocity = (accel * 0.35f) * Time.deltaTime + velocity;
        }
        else
        {
            velocity = accel * Time.deltaTime + velocity;
        }

        Vector2 target   = Position + delta;
        AABB    entityBB = GetBoundingBox();

        colFlags = CollideFlags.None;

        // Player size in tiles.
        Vector2Int tSize = Utils.CeilToInt(entityBB.radius * 2.0f);

        Vector2Int start = Utils.TilePos(Position);
        Vector2Int end   = Utils.TilePos(target);

        // Compute the range of tiles we could touch with our movement. We'll test for collisions
        // with the tiles in this range.
        Vector2Int min = new Vector2Int(Mathf.Min(start.x, end.x) - tSize.x, Mathf.Min(start.y, end.y) - tSize.y);
        Vector2Int max = new Vector2Int(Mathf.Max(start.x, end.x) + tSize.x, Mathf.Max(start.y, end.y) + tSize.y);

        // Tile collision checking.
        GetPossibleCollidingTiles(world, entityBB, min, max);

        // Entity collision checking.
        GetPossibleCollidingEntities(world, entityBB, min, max);

        possibleCollides.Sort(collideCompare);

        float tRemaining = 1.0f;

        for (int it = 0; it < 3 && tRemaining > 0.0f; ++it)
        {
            float   tMin   = 1.0f;
            Vector2 normal = Vector2.zero;

            CollideResult hitResult = default;
            bool          hit       = false;

            for (int i = 0; i < possibleCollides.Count; ++i)
            {
                CollideResult info   = possibleCollides[i];
                bool          result = TestTileCollision(world, entityBB, info.bb, delta, ref tMin, ref normal);

                if (result)
                {
                    hitResult = info;
                    hit       = true;
                }
            }

            MoveBy(delta * tMin);

            if (normal != Vector2.zero)
            {
                MoveBy((normal * Epsilon));
            }

            if (hit)
            {
                OnCollide(hitResult);
            }

            entityBB = GetBoundingBox();

            // Subtract away the component of the velocity that collides with the tile wall
            // and leave the remaining velocity intact.
            velocity -= Vector2.Dot(velocity, normal) * normal;
            delta    -= Vector2.Dot(delta, normal) * normal;

            delta      -= (delta * tMin);
            tRemaining -= (tMin * tRemaining);
        }

        possibleCollides.Clear();

        if (overlaps.Count > 0)
        {
            HandleOverlaps(overlaps);
        }

        overlaps.Clear();

        SetFacingDirection();
        Rebase(world);
        ApplyOverTimeDamage();

        if (DebugServices.Instance.ShowDebug)
        {
            GetBoundingBox().Draw(Color.green);
        }
    }