// Update the segment's position and compute a smoothed velocity for the circle or the
        // endpoints of the segment based on  the time it took it to move from the last position
        // to the current one.  The velocity is in pixels per second.

        public void UpdateSegment(Segment s)
        {
            segLast = seg;
            seg     = s;

            DateTime cur = DateTime.Now;
            double   fMs = cur.Subtract(timeLastUpdated).TotalMilliseconds;

            if (fMs < 10.0)
            {
                fMs = 10.0;
            }
            double fFPS = 1000.0 / fMs;

            timeLastUpdated = cur;

            if (seg.IsCircle())
            {
                xVel = xVel * smoothing + (1.0 - smoothing) * (seg.x1 - segLast.x1) * fFPS;
                yVel = yVel * smoothing + (1.0 - smoothing) * (seg.y1 - segLast.y1) * fFPS;
            }
            else
            {
                xVel  = xVel * smoothing + (1.0 - smoothing) * (seg.x1 - segLast.x1) * fFPS;
                yVel  = yVel * smoothing + (1.0 - smoothing) * (seg.y1 - segLast.y1) * fFPS;
                xVel2 = xVel2 * smoothing + (1.0 - smoothing) * (seg.x2 - segLast.x2) * fFPS;
                yVel2 = yVel2 * smoothing + (1.0 - smoothing) * (seg.y2 - segLast.y2) * fFPS;
            }
        }
        // Using the velocity calculated above, estimate where the segment is right now.

        public Segment GetEstimatedSegment(DateTime cur)
        {
            Segment estimate = seg;
            double  fMs      = cur.Subtract(timeLastUpdated).TotalMilliseconds;

            estimate.x1 += fMs * xVel / 1000.0;
            estimate.y1 += fMs * yVel / 1000.0;
            if (seg.IsCircle())
            {
                estimate.x2 = estimate.x1;
                estimate.y2 = estimate.y1;
            }
            else
            {
                estimate.x2 += fMs * xVel2 / 1000.0;
                estimate.y2 += fMs * yVel2 / 1000.0;
            }
            return(estimate);
        }
Esempio n. 3
0
            // Hit testing between this thing and a single segment.  If hit, the center point on
            // the segment being hit is returned, along with the spot on the line from 0 to 1 if
            // a line segment was hit.
            public bool Hit(Segment seg, ref Point ptHitCenter, ref double lineHitLocation)
            {
                double minDxSquared = size + seg.radius;
                minDxSquared *= minDxSquared;

                // See if falling thing hit this body segment
                if (seg.IsCircle())
                {
                    if (SquaredDistance(center.X, center.Y, seg.x1, seg.y1) <= minDxSquared)
                    {
                        ptHitCenter.X = seg.x1;
                        ptHitCenter.Y = seg.y1;
                        lineHitLocation = 0;
                        return true;
                    }
                }
                else
                {
                    double sqrLineSize = SquaredDistance(seg.x1, seg.y1, seg.x2, seg.y2);
                    if (sqrLineSize < 0.5)  // if less than 1/2 pixel apart, just check dx to an endpoint
                    {
                        return (SquaredDistance(center.X, center.Y, seg.x1, seg.y1) < minDxSquared) ? true : false;
                    }
                    else
                    {   // Find dx from center to line
                        double u = ((center.X - seg.x1) * (seg.x2 - seg.x1) + (center.Y - seg.y1) * (seg.y2 - seg.y1)) / sqrLineSize;
                        if ((u >= 0) && (u <= 1.0))
                        {   // Tangent within line endpoints, see if we're close enough
                            double xIntersect = seg.x1 + (seg.x2 - seg.x1) * u;
                            double yIntersect = seg.y1 + (seg.y2 - seg.y1) * u;

                            if (SquaredDistance(center.X, center.Y,
                                xIntersect, yIntersect) < minDxSquared)
                            {
                                lineHitLocation = u;
                                ptHitCenter.X = xIntersect;
                                ptHitCenter.Y = yIntersect; ;
                                return true;
                            }
                        }
                        else
                        {
                            // See how close we are to an endpoint
                            if (u < 0)
                            {
                                if (SquaredDistance(center.X, center.Y, seg.x1, seg.y1) < minDxSquared)
                                {
                                    lineHitLocation = 0;
                                    ptHitCenter.X = seg.x1;
                                    ptHitCenter.Y = seg.y1;
                                    return true;
                                }
                            }
                            else
                            {
                                if (SquaredDistance(center.X, center.Y, seg.x2, seg.y2) < minDxSquared)
                                {
                                    lineHitLocation = 1;
                                    ptHitCenter.X = seg.x2;
                                    ptHitCenter.Y = seg.y2;
                                    return true;
                                }
                            }
                        }
                    }
                    return false;
                }
                return false;
            }
Esempio n. 4
0
        // Update the segment's position and compute a smoothed velocity for the circle or the
        // endpoints of the segment based on  the time it took it to move from the last position
        // to the current one.  The velocity is in pixels per second.
        public void UpdateSegment(Segment s)
        {
            segLast = seg;
            seg = s;

            DateTime cur = DateTime.Now;
            double fMs = cur.Subtract(timeLastUpdated).TotalMilliseconds;
            if (fMs < 10.0)
                fMs = 10.0;
            double fFPS = 1000.0 / fMs;
            timeLastUpdated = cur;

            if (seg.IsCircle())
            {
                xVel = xVel * smoothing + (1.0 - smoothing) * (seg.x1 - segLast.x1) * fFPS;
                yVel = yVel * smoothing + (1.0 - smoothing) * (seg.y1 - segLast.y1) * fFPS;
            }
            else
            {
                xVel = xVel * smoothing + (1.0 - smoothing) * (seg.x1 - segLast.x1) * fFPS;
                yVel = yVel * smoothing + (1.0 - smoothing) * (seg.y1 - segLast.y1) * fFPS;
                xVel2 = xVel2 * smoothing + (1.0 - smoothing) * (seg.x2 - segLast.x2) * fFPS;
                yVel2 = yVel2 * smoothing + (1.0 - smoothing) * (seg.y2 - segLast.y2) * fFPS;
            }
        }
        public HitType LookForHits(Dictionary <Bone, BoneData> segments, int playerId)
        {
            DateTime cur     = DateTime.Now;
            HitType  allHits = HitType.None;

            // Zero out score if necessary
            if (!scores.ContainsKey(playerId))
            {
                scores.Add(playerId, 0);
            }

            foreach (var pair in segments)
            {
                for (int i = 0; i < things.Count; i++)
                {
                    HitType hit   = HitType.None;
                    Thing   thing = things[i];
                    switch (thing.state)
                    {
                    case ThingState.Bouncing:
                    case ThingState.Falling:
                    {
                        var     ptHitCenter     = new Point(0, 0);
                        double  lineHitLocation = 0;
                        Segment seg             = pair.Value.GetEstimatedSegment(cur);
                        if (thing.Hit(seg, ref ptHitCenter, ref lineHitLocation))
                        {
                            double fMs = 1000;
                            if (thing.timeLastHit != DateTime.MinValue)
                            {
                                fMs = cur.Subtract(thing.timeLastHit).TotalMilliseconds;
                                thing.avgTimeBetweenHits = thing.avgTimeBetweenHits * 0.8 + 0.2 * fMs;
                            }
                            thing.timeLastHit = cur;

                            // Bounce off head and hands
                            if (seg.IsCircle())
                            {
                                // Bounce off of hand/head/foot
                                thing.BounceOff(ptHitCenter.X, ptHitCenter.Y, seg.radius,
                                                pair.Value.xVel / targetFrameRate, pair.Value.yVel / targetFrameRate);

                                if (fMs > 100.0)
                                {
                                    hit |= HitType.Hand;
                                }
                            }
                            else          // Bonce off line segment
                            {
                                double xVel = pair.Value.xVel * (1.0 - lineHitLocation) + pair.Value.xVel2 * lineHitLocation;
                                double yVel = pair.Value.yVel * (1.0 - lineHitLocation) + pair.Value.yVel2 * lineHitLocation;

                                thing.BounceOff(ptHitCenter.X, ptHitCenter.Y, seg.radius,
                                                xVel / targetFrameRate, yVel / targetFrameRate);

                                if (fMs > 100.0)
                                {
                                    hit |= HitType.Arm;
                                }
                            }

                            if (gameMode == GameMode.TwoPlayer)
                            {
                                if (thing.state == ThingState.Falling)
                                {
                                    thing.state      = ThingState.Bouncing;
                                    thing.touchedBy  = playerId;
                                    thing.hotness    = 1;
                                    thing.flashCount = 0;
                                }
                                else if (thing.state == ThingState.Bouncing)
                                {
                                    if (thing.touchedBy != playerId)
                                    {
                                        if (seg.IsCircle())
                                        {
                                            thing.touchedBy = playerId;
                                            thing.hotness   = Math.Min(thing.hotness + 1, 4);
                                        }
                                        else
                                        {
                                            hit |= HitType.Popped;
                                            AddToScore(thing.touchedBy, 5 << (thing.hotness - 1), thing.center);
                                        }
                                    }
                                }
                            }
                            else if (gameMode == GameMode.Solo)
                            {
                                if (seg.IsCircle())
                                {
                                    if (thing.state == ThingState.Falling)
                                    {
                                        thing.state      = ThingState.Bouncing;
                                        thing.touchedBy  = playerId;
                                        thing.hotness    = 1;
                                        thing.flashCount = 0;
                                    }
                                    else if ((thing.state == ThingState.Bouncing) && (fMs > 100.0))
                                    {
                                        hit |= HitType.Popped;
                                        AddToScore(thing.touchedBy,
                                                   (pair.Key.joint1 == JointID.FootLeft || pair.Key.joint1 == JointID.FootRight) ? 10 : 5,
                                                   thing.center);
                                        thing.touchedBy = playerId;
                                    }
                                }
                            }

                            things[i] = thing;

                            if (thing.avgTimeBetweenHits < 8)
                            {
                                hit |= HitType.Popped | HitType.Squeezed;
                                if (gameMode != GameMode.Off)
                                {
                                    AddToScore(playerId, 1, thing.center);
                                }
                            }
                        }
                    }
                    break;
                    }

                    if ((hit & HitType.Popped) != 0)
                    {
                        thing.state     = ThingState.Dissolving;
                        thing.dissolve  = 0;
                        thing.xVelocity = thing.yVelocity = 0;
                        thing.spinRate  = thing.spinRate * 6 + 0.2;
                        things[i]       = thing;
                    }
                    allHits |= hit;
                }
            }
            return(allHits);
        }
            // Hit testing between this thing and a single segment.  If hit, the center point on
            // the segment being hit is returned, along with the spot on the line from 0 to 1 if
            // a line segment was hit.

            public bool Hit(Segment seg, ref Point ptHitCenter, ref double lineHitLocation)
            {
                double minDxSquared = size + seg.radius;

                minDxSquared *= minDxSquared;

                // See if falling thing hit this body segment
                if (seg.IsCircle())
                {
                    if (SquaredDistance(center.X, center.Y, seg.x1, seg.y1) <= minDxSquared)
                    {
                        ptHitCenter.X   = seg.x1;
                        ptHitCenter.Y   = seg.y1;
                        lineHitLocation = 0;
                        return(true);
                    }
                }
                else
                {
                    double sqrLineSize = SquaredDistance(seg.x1, seg.y1, seg.x2, seg.y2);
                    if (sqrLineSize < 0.5)  // if less than 1/2 pixel apart, just check dx to an endpoint
                    {
                        return((SquaredDistance(center.X, center.Y, seg.x1, seg.y1) < minDxSquared) ? true : false);
                    }
                    else
                    {   // Find dx from center to line
                        double u = ((center.X - seg.x1) * (seg.x2 - seg.x1) + (center.Y - seg.y1) * (seg.y2 - seg.y1)) / sqrLineSize;
                        if ((u >= 0) && (u <= 1.0))
                        {   // Tangent within line endpoints, see if we're close enough
                            double xIntersect = seg.x1 + (seg.x2 - seg.x1) * u;
                            double yIntersect = seg.y1 + (seg.y2 - seg.y1) * u;

                            if (SquaredDistance(center.X, center.Y,
                                                xIntersect, yIntersect) < minDxSquared)
                            {
                                lineHitLocation = u;
                                ptHitCenter.X   = xIntersect;
                                ptHitCenter.Y   = yIntersect;;
                                return(true);
                            }
                        }
                        else
                        {
                            // See how close we are to an endpoint
                            if (u < 0)
                            {
                                if (SquaredDistance(center.X, center.Y, seg.x1, seg.y1) < minDxSquared)
                                {
                                    lineHitLocation = 0;
                                    ptHitCenter.X   = seg.x1;
                                    ptHitCenter.Y   = seg.y1;
                                    return(true);
                                }
                            }
                            else
                            {
                                if (SquaredDistance(center.X, center.Y, seg.x2, seg.y2) < minDxSquared)
                                {
                                    lineHitLocation = 1;
                                    ptHitCenter.X   = seg.x2;
                                    ptHitCenter.Y   = seg.y2;
                                    return(true);
                                }
                            }
                        }
                    }
                    return(false);
                }
                return(false);
            }