예제 #1
0
        public override void Update(GameTime gameTime)
        {
            float elapsedTime = this.elapsedTime + (float)gameTime.ElapsedGameTime.TotalSeconds;
            this.elapsedTime = 0;
            if (spawnTime > 0) {
                spawnTime -= elapsedTime;
                if (spawnTime <= 0) {
                    spawnTime = 0;
                    health = 100;
                    ammo = 200;
                    equipped = new Pistol();
                    core.spawnPlayer(this);
                }
                return;
            }
            else if (health < 0) {
                spawnTime = spawnDelay;
                return;
            }
            equipped.Update(gameTime);

            //ping the input engine for move
            List<Actions> actions = new List<Actions>();
            actions.AddRange(core.inputEngine.getGameKeys());
            actions.AddRange(core.inputEngine.getGameButtons(playerIndex));

            Vector2 move = core.inputEngine.getMove() + core.inputEngine.getMove(playerIndex);
            Vector2 look = core.inputEngine.getLook() + core.inputEngine.getLook(playerIndex) * lookSensitivity;
            look = new Vector2(MathHelper.ToRadians(look.X), MathHelper.ToRadians(look.Y)) * rotationSpeed * elapsedTime;

            direction = direction + look;
            clampDirection();

            Vector3 jumpVelocity = Vector3.Zero;

            foreach (Actions a in actions)
                if (a == Actions.Jump) {
                    jumpVelocity.Y = jump;
                }
                else if (a == Actions.Fire) {
                    equipped.fire(this, core.physicsEngine);
                }
                else if (a == Actions.Downgrade)
                    equipped = equipped.upgradeDown();
                else if (a == Actions.Scoreboard) {
                    showScoreboard = true;
                    if (scoreboardDist < maxScoreBoardDist)
                        scoreboardDist += 30;
                }
                else if (a == Actions.Reload) {
                    if (currentPathsWheelHeight < maxPathsWheelHeight)
                        currentPathsWheelHeight += 30;
                    drawUpgradePath = true;
                }
                else if(actions.Contains(Actions.Pause)){
                    core.currentState=GameState.MenuScreen;
                    core.menuEngine.currentMenu=core.menuEngine.pauseMenu;
                    }

            //Check for released buttons
            if (!actions.Contains(Actions.Reload)) {
                currentPathsWheelHeight = 0;
                drawUpgradePath = false;
            }
            if (!actions.Contains(Actions.Scoreboard)) {
                scoreboardDist = 0;
                showScoreboard = false;
            }

            //reduce damage alpha values
            if (takingDamage) {
                if (damageAlpha1 != 0)
                    damageAlpha2 = 1;
                else
                    damageAlpha1 = 1;
                takingDamage = false;
            }
            if (damageAlpha1 > 0) {
                damageAlpha1 -= 0.005f;
            }
            else
                damageAlpha1 = 0;

            if (damageAlpha2 > 0) {
                damageAlpha2 -= 0.005f;
            }
            else
                damageAlpha2 = 0;

            Vector3 velocity = Vector3.Zero;
            Vector3 forward = getDirectionVector();
            curBlinkTime = Math.Max(curBlinkTime - (float)gameTime.ElapsedGameTime.TotalSeconds, 0);

            if (curBlinkTime <= 0 && actions.Contains(Actions.Aim) && ammo >= blinkCost) {
                jumpVelocity = Vector3.Zero;
                curBlinkTime = blinkTime;
                ammo -= blinkCost;
                core.physicsEngine.applyBlink(elapsedTime, this, forward * 1000);
            }
            else {
                if (core.clip)
                    forward.Y = 0;
                forward.Normalize();
                Vector3 right = Vector3.Cross(forward, Vector3.Up);
                right.Normalize();
                velocity = forward * move.Y + right * move.X;
                if (velocity != Vector3.Zero)
                    velocity.Normalize();
                velocity = velocity * speed;   //this is when it actually becomes the velocity
                core.physicsEngine.applyMovement(elapsedTime, playerIndex, velocity + jumpVelocity);
            }

            //the velocity given to the physics engine is but a request for movement.
            //the final position is decided by that engine, taking into account gravity and collision detection/response

            core.physicsEngine.updateCollisionCellsFor(this);
        }
예제 #2
0
        public override void Update(GameTime gameTime)
        {
            /* If we're dead then wait until we can spawn ourselves
             * again.
             */
            if (spawnTime > 0) {
                spawnTime -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (spawnTime <= 0) {
                    spawnTime = 0;
                    health = 100;
                    ammo = 200;
                    equipped = new Pistol();
                    core.spawnPlayer(this);
                }
                return;
            }
            else if (health < 0) {
                spawnTime = spawnDelay;
                return;
            }

            timeSinceDamageDealt += (float)gameTime.ElapsedGameTime.TotalSeconds;

            //update the weapon
            equipped.Update(gameTime);

            //check if we can look for and find an enemy agent
            //if we aren't already targetting an agent, or it's time to give up, find a new target, if we can
            if (timeSinceLastShot >= lastShotTimeLimit) {
                agentTarget = null;
                path.Clear();
                timeSinceLastShot = 0;
                Console.WriteLine("giving up");
            }
            else if(agentTarget != null)
                timeSinceLastShot += (float)gameTime.ElapsedGameTime.TotalSeconds;

            curReevaluationTime -= (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (curReevaluationTime <= 0) {
                curReevaluationTime = reevaulationTime;
                agentTarget = null;

                /* depending on the current state of this agent we want to do something
                 * different. if we are low on health, then we move towards a health pickup
                 * if we are low on ammo, then towards ammo, otherwise we look for an opponent.
                 * Now there are also overriding circumstances: if an enemy is too close, then we
                 * attack them (unless we have no ammo). also, if we have a low-level weapon then
                 * we want to upgrade our weapon. to do this we calculate all relevant data
                 */

                //find a new target, but only if ammo is sufficient
                float closestFeasibleTargetDist = float.MaxValue;
                Agent closestAgent = null;
                //we need to at least be able to shoot our gun at the enemy for a second
                if (ammo >= equipped.ammoUsed * 2 && ammo >= equipped.ammoUsed / equipped.cooldown) {
                    Vector3 eye = getEyePosition(),
                            dir = getDirectionVector();
                    //first try and go after the guy that just shot us
                    if (damageSource != null
                            && damageSource != this
                            && damageSource.spawnTime == 0
                            && timeSinceDamageDealt <= timeLimitSinceDamageDealt) {
                        timeSinceDamageDealt = timeLimitSinceDamageDealt + 1;
                        Vector3 aCent = damageSource.getCenter();
                        float dist = Vector3.Distance(eye, aCent);
                        PhysicsEngine.HitScan hs = core.physicsEngine.hitscan(eye, aCent - eye, null);
                        if (hs == null || hs.Distance() > dist) {
                            closestAgent = damageSource;
                            closestFeasibleTargetDist = Vector3.Distance(eye, aCent);
                        }
                    }
                    if(closestAgent == null) {
                        foreach (Agent a in core.allAgents()) {
                            if (a.spawnTime > 0 || a == this) continue;  //if the agent is not in the level, then you can't see them
                            Vector3 aCent = a.getCenter();
                            float dist = Vector3.Distance(eye, aCent);
                            if (dist < closestFeasibleTargetDist    //we're only concerned in closer enemies
                                    && Vector3.Dot(dir, Vector3.Normalize(aCent - eye)) > -0.2) {   //if they're infront of us
                                PhysicsEngine.HitScan hs = core.physicsEngine.hitscan(eye, aCent - eye, null);
                                if (hs == null || hs.Distance() > dist) {
                                    closestAgent = a;
                                    closestFeasibleTargetDist = Vector3.Distance(eye, aCent);
                                }
                            }
                        }
                    }
                }

                //calculate the tier of a weapon
                int weaponTier = 2;
                if (equipped is Rifle || equipped is Shotgun)
                    weaponTier = 1;
                else if (equipped is Pistol)
                    weaponTier = 0;

                //calculate the nearest ammo, upgrade and health pickups
                float closestHealthDist = float.MaxValue, closestAmmoDist = float.MaxValue, closestUpgradeDist = float.MaxValue;
                MeshNode closestHealth = null, closestAmmo = null, closestUpgrade = null;
                foreach (MeshNode m in core.aiEngine.pickupNodes) {
                    if (m.linkedPickupGen.held != null) {
                        float dist = Vector3.Distance(m.position, position);
                        if (m.linkedPickupGen.itemType == PickUp.PickUpType.HEALTH) {
                            if (dist < closestHealthDist) {
                                closestHealthDist = dist;
                                closestHealth = m;
                            }
                        }
                        else if (m.linkedPickupGen.itemType == PickUp.PickUpType.AMMO) {
                            if (dist < closestAmmoDist) {
                                closestAmmoDist = dist;
                                closestAmmo = m;
                            }
                        }
                        else if (dist < closestUpgradeDist) {
                            closestUpgradeDist = dist;
                            closestUpgrade = m;
                        }
                    }
                }

                //now decide what to do, but how? we calculate a score for each value between 0 and 1
                double agentScore = Math.Min(1, Math.Max(0, (closestAgent == null || closestFeasibleTargetDist >= sightRadius ?
                                        0 : Math.Pow((sightRadius - closestFeasibleTargetDist) / sightRadius, 0.4)))),
                       healthScore = Math.Min(1, Math.Max(0, (closestHealth == null ?
                                        0 : Math.Pow((double)(70 - health)/maxHealth, 2)))),
                       ammoScore = Math.Min(1, Math.Max(0, (closestAmmo == null ?
                                        0 : Math.Pow((double)(maxAmmo - ammo)/maxAmmo, 3)))),
                       upgradeScore = Math.Min(1, Math.Max(0, (closestUpgrade == null ?
                                        0 : Math.Pow((double)(2 - weaponTier) / 2, 4))));

                //find the max
                double maxScore = Math.Max(agentScore, Math.Max(healthScore, Math.Max(ammoScore, upgradeScore)));

                //do the work
                if (maxScore > 0) {
                    ignore.Clear();
                    if (agentScore == maxScore) {
                        Console.WriteLine("going for agent: " + closestAgent);
                        agentTarget = closestAgent;
                        setPathTo(core.aiEngine.findClosestMeshNode(agentTarget.getPosition(), 100, ignore), ignore);
                    }
                    else if (healthScore == maxScore) {
                        Console.WriteLine("going for health: " + closestHealth);
                        setPathTo(closestHealth, null);
                    }
                    else if (ammoScore == maxScore) {
                        Console.WriteLine("going for ammo: " + closestAmmo);
                        setPathTo(closestAmmo, null);
                    }
                    else {
                        Console.WriteLine("going for upgrade: " + closestUpgrade);
                        setPathTo(closestUpgrade, null);
                    }
                }
            }

            if (agentTarget != null && (agentTarget == this || agentTarget.spawnTime > 0))
                agentTarget = null;

            if(agentTarget != null) {
                //walking towards the target
                if (path.Count == 0)
                    setPathTo(core.aiEngine.findClosestMeshNode(agentTarget.getPosition(), 100, ignore), ignore);
                Vector3 aCent = agentTarget.getCenter();
                Vector3 cent = position + new Vector3(0, size.Y / 2, 0);
                direction = getDirectionFromVector(Vector3.Normalize(aCent - cent));
                //shooting the target
                curAgentShootTime -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (curAgentShootTime <= 0 && equipped.curCooldown <= 0) {
                    curAgentShootTime = agentShootTime;
                    //try and shoot the player
                    PhysicsEngine.HitScan hs = core.physicsEngine.hitscan(cent, aCent - cent, null);
                    if (hs == null || hs.Distance() > Vector3.Distance(cent, aCent)) {
                        timeSinceLastShot = 0;
                        //actually shoot now
                        //we want to adjust the direction based on the relative motion of the target to this agent
                        Vector3 right = Vector3.Normalize(Vector3.Cross(aCent - cent, Vector3.Up));
                        //now get the target's previous move in terms of right and up
                        Vector3 move = agentTarget.getPosition() - agentTarget.getOldPosition() + position - oldPosition;
                        double x = Math.Abs(Vector3.Dot(move, right)),
                            y = Math.Abs(Vector3.Dot(move, Vector3.Up));
                        //clamp x and y
                        //what's the max speed that they could've moved?
                        double max = agentTarget.speed * gameTime.ElapsedGameTime.TotalSeconds;
                        x = Math.Min(x/max, 1);
                        y = Math.Min(y/max, 1);

                        //y determines the inaccuracy of up-down aiming and x for left-right
                        //the "range" of this inaccuracy is determined by the distance the agent is from the me
                        double inaccuracy = Math.Pow(Math.Min(Vector3.Distance(cent, aCent) / sightRadius, 1), 0.02);

                        Console.WriteLine(inaccuracy * x);
                        direction.X += (float)((core.aiEngine.random.NextDouble() * 2 - 1) * Math.PI * inaccuracy * x / 2);
                        direction.Y += (float)((core.aiEngine.random.NextDouble() * 2 - 1) * Math.PI * inaccuracy * y / 2);

                        equipped.fire(this, core.physicsEngine);
                    }
                }
            }

            //if we're not moving towards something then stop ignoring nodes and find a pickup to go to
            if (path.Count == 0) {
                Console.WriteLine("here");
                ignore.Clear();     //should we clear ignore here?
                setPathTo(core.aiEngine.pickupNodes[core.aiEngine.random.Next(core.aiEngine.pickupNodes.Count)], ignore);
                if (path.Count == 0) {
                    Console.WriteLine("no path");
                    core.spawnPlayer(this);
                    return;
                }
            }

            //walk along the current path
            if (path.Count > 0) {

                //try move to the latest point in the path
                MeshNode target = path[0];
                /* if we're sufficiently close to the target switch it
                 * find the target's position relative to the position
                 */
                Vector2 tpos = new Vector2(Math.Abs(target.position.X - position.X),
                                            Math.Abs(target.position.Z - position.Z));
                if (tpos.X < size.X / 6 && tpos.Y < size.Y / 6) {
                    ignore.Clear();
                    popFromPath();
                    targetAquisitionDuration = 0;
                    //if (path.Count == 0 && agentTarget == null)setPathTo(core.aiEngine.pickupNodes[core.aiEngine.random.Next(core.aiEngine.pickupNodes.Count)], ignore);
                    if (path.Count == 0)
                        return;
                    target = path[0];
                }

                if (agentVelocities.persistentVelocity != Vector3.Zero)
                    previousTarget = null;

                //calculate direction to target -- we need this for the model, this will probably change, but the principles are right
                Vector3 velocity = target.position - position;
                direction = getDirectionFromVector(velocity);

                /* now calculate the move and actually move
                 * depending on whether we're on the mesh or not, we don't need collision detection
                 * if we've gotten here and there's a previous target then we're on the path
                 */
                if (true || previousTarget != null) {
                    velocity.Normalize();
                    core.physicsEngine.applySimpleMovement(gameTime, this, velocity * speed);
                }
                //otherwise we need to take care of things the expensive way
                else {
                    velocity.Y = 0;
                    velocity.Normalize();
                    core.physicsEngine.applyMovement((float)gameTime.ElapsedGameTime.TotalSeconds, this, speed * velocity);
                }

                /* the targetAquisitionDuration variable helps us keep track of the time taken
                 * to move between two nodes. if it's taking too long the we give up on that node
                 * and try a different path to our target node (path[-1])
                 */
                targetAquisitionDuration += gameTime.ElapsedGameTime.TotalSeconds;
                if (targetAquisitionDuration >= timeout) {
                    ignore.Add(target);
                    targetAquisitionDuration = 0;
                    if (path.Count > 0)
                        setPathTo(path[path.Count - 1], ignore);
                }

                core.physicsEngine.updateCollisionCellsFor(this);
            }
        }