Beispiel #1
0
        // Add an attack Animation here
        // TODO: maybe put the thing that actually applies the damage here, just to consolodate logical code
        public void AddAttack(Derp from, Derp to)
        {
            // This must be located two radius distance from the derp, in the direction of the delivering attacker
            myVector u = new myVector(from.x - to.x, from.y - to.y);

            u.toUnit();

            // opposite direction for nearest cardinal dir calculation
            myVector u2 = new myVector(-u.x, -u.y);

            DerpAttack attack = new DerpAttack(to.x + (u.x * to.stats.radius * 2), to.y + (u.y * to.stats.radius * 2), Geometry.GetNearestCardinalDir(u2));

            derpAttacks.Add(attack.key, attack);
        }
Beispiel #2
0
        // Set a derp to move out of the way of another derp. Also returns the slow derp. (even if it actually isn't slower?)
        // The fastDerp has run into the slow derp, it must tell it to move out of the way. Give the other derp the unit vector to move along
        public Derp SetToMoveOutOfWay(int slowDerpID, Derp fastDerp)
        {
            List <Derp> checkList = (fastDerp.team == TEAM.HOME ? homeDerps : awayDerps);
            Derp        slowDerp  = checkList[slowDerpID];

            // only actually do this if the slow derp is slower or equal
            if (slowDerp.stats.spd > fastDerp.stats.spd)
            {
                return(slowDerp);
            }

            // The Move Vector should be directly away from the fast derp
            myVector awayVector = new myVector(slowDerp.x - fastDerp.x, slowDerp.y - fastDerp.y);

            awayVector.toUnit();

            // Tell 'em to move
            slowDerp.moveOutOfWay       = true;
            slowDerp.moveOutOfWayVector = awayVector;

            return(slowDerp);
        }
Beispiel #3
0
        // This is the function that tries to make a step, it can recurse once.
        public void attemptStep(myVector v, bool recurse)
        {
            // Optimistic no collision
            double   t    = 1.0;
            myVector newV = null;

            // Check for team derp collisions
            double   derpT;
            myVector derpV = null;

            int colID = manager.CheckDerpCollision(this, v, out derpT, enemyDetected); // note: this returns -1 if either there is no collision, or if we are colliding with the other team

            isColliding = (colID != -1);

            // We have collided with another derp
            // Tell the other to move out of the way, and have us try to move perpendicular to them
            if (isColliding && !recurse)
            {
                Derp slowDerp = manager.SetToMoveOutOfWay(colID, this);

                if (slowDerp != null)
                {
                    // Get the Unit Vector towards the slow Derp
                    myVector u = new myVector(slowDerp.x - x, slowDerp.y - y);
                    u.toUnit();

                    // Make sure that the slow derp is actually in front of where you want to go
                    if (u.dot(v) > 0.0)
                    {
                        // Get a perpendicular unit vector to follow
                        myVector uPerp = new myVector(-u.y, u.x);

                        // Make sure it is the correct way
                        double dir = uPerp.dot(v);

                        // Wrong way
                        if (dir < -1e-3)
                        {
                            uPerp.x *= -1;
                            uPerp.y *= -1;
                        }
                        // Special Zero case, pick a random direction
                        // this should... almost never happen
                        // I'm concerned this could mess up random synch in multiplayer. Just pick a constant direction.
                        else if (dir < 1e-3)
                        {
                            /*
                             * if (MyRandom.Next(team, 2) % 2 == 0)
                             * {
                             *  uPerp.x *= -1;
                             *  uPerp.y *= -1;
                             * }
                             */
                        }

                        // Try moving along the new path
                        double remainingT = (1.0 - derpT);
                        derpV = new myVector(uPerp.x * remainingT * v.mag(), uPerp.y * remainingT * v.mag());
                    }
                }
            }

            // Check for field collisions
            double        fieldT;
            myVector      fieldV = null;
            myLineSegment collisionVect;

            if (Field.field.CheckFieldCollision(this, v, out fieldT, out collisionVect) && !recurse)
            {
                // try to move parallel to the wall with the extra t
                collisionVect.v.toUnit();

                // make sure this unit vector is in the right direction
                double dir = collisionVect.v.dot(v);

                // Wrong way
                if (dir < -1e-3)
                {
                    collisionVect.v.x *= -1;
                    collisionVect.v.y *= -1;
                }

                // ignore zero case
                if (Math.Abs(dir) > 1e-3)
                {
                    // Try moving along the new path
                    double remainingT = (1.0 - fieldT);
                    fieldV = new myVector(collisionVect.v.x * remainingT * v.mag(), collisionVect.v.y * remainingT * v.mag());
                }
            }

            // See if we have a collision
            // If either of the recalculated V values are not null, we hit something along the way
            if (derpT < 1.0 - 1e-6 || fieldT < 1.0 - 1e-6)
            {
                if (fieldT < derpT)
                {
                    t    = fieldT;
                    newV = fieldV;
                }
                else
                {
                    t    = derpT;
                    newV = derpV;
                }
            }

            // Only step as far as we can
            x += v.x * t;
            y += v.y * t;

            if (newV != null)
            {
                attemptStep(newV, true);
            }
        }
Beispiel #4
0
        // Check for a Derp's Circle-Cast across the field
        // This will work like a BFS, starting from the initial position
        // then check all 4 corners around the position to build on the bfs
        public bool CheckFieldCollision(Derp d, myVector v, out double t, out myLineSegment col)
        {
            // initial optimistic setup that there will not be a collision
            bool ret = false;
            t = 1.0;
            col = null;

            // calculate starting point
            int startX = (int)(d.x / BLOCK_WIDTH);
            int startY = (int)(d.y / BLOCK_HEIGHT);

            // Unit Vector in desired direction
            myVector vUnit = new myVector(v.x, v.y);
            vUnit.toUnit();

            // set up the bfs
            Queue<SimpleNode> q = new Queue<SimpleNode>();
            bool[,] vis = new bool[height+1, width+1];

            q.Enqueue(new SimpleNode(startX, startY, 0));
            vis[startY, startX] = true;

            // Create the 4 line segments so we don't have to do quiiite as much object creation in this loop
            myLineSegment[] segs = new myLineSegment[4];
            for (int i = 0; i < 4; ++i)
                segs[i] = new myLineSegment(null, null);

            // BFS
            int[] dx = { 0, 1, 0, -1 };
            int[] dy = { -1, 0, 1, 0 };
            int cur_step = 0;
            while (q.Count > 0)
            {
                SimpleNode cur = q.Dequeue();

                // end early if we had a hit already in a previous step
                if (ret && cur_step != cur.step)
                    break;

                // checking 4 nodes around us
                myPoint p1 = new myPoint(cur.x * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p2 = new myPoint((cur.x + 1) * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p3 = new myPoint((cur.x + 1) * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                myPoint p4 = new myPoint(cur.x * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                segs[0].Update(p1, p2);
                segs[1].Update(p2, p3);
                segs[2].Update(p4, p3);
                segs[3].Update(p1, p4);

                for (int i = 0; i < 4; ++i)
                {
                    int nx = cur.x + dx[i];
                    int ny = cur.y + dy[i];

                    if (nx < 0 || nx > width || ny < 0 || ny >= height || vis[ny, nx])
                        continue;

                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, segs[i], out possible_t))
                    {
                        // We have a hit! If the next zone is safe to move in, then continue the bfs
                        if (gameGrid[ny, nx] != '0')
                        {
                            q.Enqueue(new SimpleNode(nx, ny, cur.step + 1));
                            vis[ny, nx] = true;
                        }
                        // We hit an unnavigable space. Stop the BFS, this is as far as we go
                        else
                        {
                            ret = true;

                            if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                            {
                                // break ties by taking the furthest behind the direction we wish to go
                                // Calculate the center point on the wall, and get the dot product of the vector to that point.
                                // The most negative value is the furthest behind
                                myPoint segMidPoint1 = new myPoint((segs[i].p1.x + segs[i].p2.x) / 2.0, (segs[i].p1.y + segs[i].p2.y) / 2.0);
                                myVector toMidPoint1 = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                                myPoint segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                                myVector toMidPoint2 = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                                if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                                {
                                    t = possible_t;
                                    col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                                }
                            }
                            else if (possible_t < t)
                            {
                                t = possible_t;
                                col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                            }
                        }
                    }
                }

                // if we are a special diagonal case, then check the cross hit as well
                myLineSegment diag = null;

                char c = gameGrid[cur.y, cur.x];
                if (c == '1' || c == '3')
                    diag = new myLineSegment(p2, p4);

                if (c == '2' || c == '4')
                    diag = new myLineSegment(p1, p3);

                if (diag != null)
                {
                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, diag, out possible_t))
                    {
                        ret = true;

                        if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                        {
                            // break ties by taking the furthest behind the direction we wish to go
                            // Calculate the center point on the wall, and get the dot product of the vector to that point.
                            // The most negative value is the furthest behind
                            myPoint segMidPoint1 = new myPoint((diag.p1.x + diag.p2.x) / 2.0, (diag.p1.y + diag.p2.y) / 2.0);
                            myVector toMidPoint1 = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                            myPoint segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                            myVector toMidPoint2 = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                            if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                            {
                                t = possible_t;
                                col = new myLineSegment(diag.p1.x, diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                            }
                        }
                        else if (possible_t < t)
                        {
                            t = possible_t;
                            col = new myLineSegment(diag.p1.x,diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                        }
                    }
                }

                cur_step = cur.step;
            }

            return ret;
        }