예제 #1
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);
            }
        }
예제 #2
0
        public void Update()
        {
            // CHECK FOR ATTACKS
            // use the derp radar to search for visible enemies in range
            Derp enemy = manager.SearchForEnemy(this, 100.0);

            enemyDetected = (enemy != null);

            // see if we can attack this enemy
            myVector toEnemy = null;

            if (enemyDetected)
            {
                toEnemy     = new myVector(enemy.x - x, enemy.y - y);
                isAttacking = (toEnemy.mag() < stats.radius + enemy.stats.radius + stats.rng);
                debugDist   = toEnemy.mag();

                if (isAttacking && (DateTime.Now.Subtract(lastAttack).TotalMilliseconds > (2000 - 15 * stats.aspd)))
                {
                    lastAttack = DateTime.Now;

                    enemy.takeHit(stats.atk);
                    manager.AddAttack(this, enemy);
                }
            }
            else
            {
                isAttacking = false;
            }

            // FOLLOW THE TRAIL
            // Find the vector between the derp and its current node destination
            double dx  = path[pathID].x - x;
            double dy  = path[pathID].y - y;
            double mag = Math.Sqrt(dx * dx + dy * dy);

            double        t = 1.0;
            myLineSegment throwaway;
            int           nextPathID = pathID + (team == TEAM.HOME ? 1 : -1);

            // Check if we can move to the next path node
            if (mag < (stats.spd * SPEED_CONST))
            {
                pathID = nextPathID;

                // Recalculate for the next node
                dx  = path[pathID].x - x;
                dy  = path[pathID].y - y;
                mag = Math.Sqrt(dx * dx + dy * dy);
            }
            // Sometimes we can abort the current node for the next-next node
            else if (nextPathID >= 0 && nextPathID < path.Count)
            {
                // if the next node is behind us (meaning we passed it accidentily) then just keep going
                // we use a manual dot product for this
                double ndx = path[nextPathID].x - x;
                double ndy = path[nextPathID].y - y;
                if (dx * ndx + dy * ndy < 0.0 && !Field.field.CheckFieldCollision(this, new myVector(path[nextPathID].x - x, path[nextPathID].y - y), out t, out throwaway))
                {
                    pathID = nextPathID;

                    // Recalculate for the next node
                    dx  = path[pathID].x - x;
                    dy  = path[pathID].y - y;
                    mag = Math.Sqrt(dx * dx + dy * dy);
                }
                // we can give a more liberal option to move forward to the next node
                // if we are colliding or seeking an enemy derp, and we can see the next node
                else if (isColliding && mag < GENERIOUS_THRESHHOLD &&
                         !Field.field.CheckFieldCollision(this, new myVector(path[nextPathID].x - x, path[nextPathID].y - y), out t, out throwaway))
                {
                    pathID = nextPathID;

                    // Recalculate for the next node
                    dx  = path[pathID].x - x;
                    dy  = path[pathID].y - y;
                    mag = Math.Sqrt(dx * dx + dy * dy);
                }
            }

            // DETERMINE MOVE
            if (!isAttacking)
            {
                // Calculate velocity and try to make the step
                double   velocity = stats.spd * SPEED_CONST;
                myVector v;
                if (enemyDetected && toEnemy != null)
                {
                    toEnemy.toUnit();
                    v = new myVector(toEnemy.x * velocity, toEnemy.y * velocity);
                }
                else if (moveOutOfWay)
                {
                    // Move out of the way!
                    v = new myVector(moveOutOfWayVector.x * velocity, moveOutOfWayVector.y * velocity);
                }
                else
                {
                    // Move Towards next Node
                    v = new myVector((dx / mag) * velocity, (dy / mag) * velocity);
                }

                // DEBUG: error catching
                double oldx = x;
                double oldy = y;

                if (isStuck)
                {
                    isStuck = false;
                }

                // Try to Step
                attemptStep(v, false);

                // DEBUG: error catching
                if (Math.Abs(x - oldx) < 1e-3)
                {
                    isStuck = true;
                }

                // Update our current instantaneous velocity
                vel.x = x - oldx; vel.y = y - oldy;

                // WE SHOULD NEVER MOVE THIS FAST. FIND MATH ERRORS.
                if (Math.Abs(vel.x) > 50 || Math.Abs(vel.y) > 50)
                {
                    x = oldx;
                    y = oldy;
                }
            }

            // Reset our MoveOUtOfWay variable, it will be set again next round if we need to keep moving out of the way
            moveOutOfWay = false;

            // This will be the game end condition eventually
            if ((team == TEAM.HOME && x > (Field.field.Width - 1) * Field.BLOCK_WIDTH) || (team == TEAM.AWAY && x < Field.BLOCK_WIDTH) || stats.hp <= 0)
            {
                Kill();
            }
        }