private void CheckObstacles(Player player) { for (int i = game.obstacles.Count - 1; i >= 0; i--) { Obstacle obstacle = game.obstacles[i]; Vector2 translation = player.Intersects(obstacle); if (translation != Vector2.Zero) { //if (player.CurrentState == Player.State.Slamming) //{ // game.obstacles.RemoveAt(i); // MakeParticles(obstacle.Position, obstacle, GameData.NUM_PART_OBSTACLE, 0, 0); //} if (player.Velocity.Y < 0) // player going up { player.Velocity.Y = -GameData.OBSTACLE_JUMP; player.StunTime = GameData.OBSTACLE_STUN; //player.CurrentState = Player.State.Flying; } else if (translation.Y == 0) // hitting from side { player.Velocity.X *= GameData.OBSTACLE_SLOW; player.Velocity.Y = 0; player.CurrentState = Player.State.Stunned; player.StunTime = GameData.OBSTACLE_HIT_STUN; game.obstacles.RemoveAt(i); MakeParticles(obstacle.Position, obstacle.texture, GameData.NUM_PART_OBSTACLE, 0, 0, obstacle.Color); } else if (translation.Y > 0) // hitting from top { player.MoveByPosition(-translation); player.Velocity.Y = 0; player.CurrentState = Player.State.Walking; } } } }
private void CheckPlatforms(Player player) { int totalCollisions = 0; foreach (Platform platform in game.platforms) { Vector2 translation = player.Intersects(platform); if (translation != Vector2.Zero) { totalCollisions++; //if (Math.Abs(translation.X) > Math.Abs(translation.Y)/* && !player.WallAbove*/) //{ // player.CurrentState = Player.State.Climbing; // //player.Velocity.Y = player.ActionTime > 0 ? -GameData.CLIMB_SPEED_FAST : -GameData.CLIMB_SPEED; //} //else if (player.CurrentState == Player.State.Climbing) // player.CurrentState = Player.State.Walking; if (translation.Y == 0) // Horizontal collision { if (player.CurrentState == Player.State.Stunned) player.Velocity.X *= -1; else { player.Velocity.X = 0; //if (player.InAir && player.JumpTime <= 0) //{ //if (player.WallJump == Player.Jump.None && player.Velocity.Y > 0) // player.Velocity.Y *= GameData.WALL_STICK_SCALE; if (player.Velocity.Y >= GameData.WALL_STICK_VEL) { if (translation.X > 0 && player.TargetVelocity == Player.Direction.Right || translation.X < 0 && player.TargetVelocity == Player.Direction.Left) player.CurrentState = Player.State.WallStick; } //player.WallJumpLeway = GameData.WALL_JUMP_LEWAY; //} } } else // Vertical or diagonal collision { if (player.CurrentState == Player.State.Stunned) player.Velocity.Y *= -1; else { player.Velocity.Y = 0; player.JumpTime = 0f; if (translation.Y > 0 && player.InAir) { player.CurrentState = Player.State.Walking; player.GrappleTarget = Vector2.Zero; player.JetpackTime = GameData.JETPACK_TIME; player.JetpackEnabled = false; player.JumpsLeft = GameData.TOTAL_JUMPS; } } } player.MoveByPosition(-translation); #if DEBUG if (translation.LengthSquared() > 1) { Console.WriteLine("Collision translation of {0}", translation); platform.Color = Color.Green; } #endif } //else // player is Slamming or Stunned //{ // if (platform.Rotation != 0) // { // MakeParticles(player.Position, platform, GameData.NUM_PART_FLOOR, 0, 1); // } // else // { // MakeParticles(player.Position, platform, GameData.NUM_PART_FLOOR, 0, 1); // float newFloorX = platform.Position.X + player.Position.X; // float sizeDiff = platform.Size.X / 2 + GameData.FLOOR_HOLE / 2; // float halfWidth = platform.Size.X / 2 - GameData.FLOOR_HOLE / 2; // float playerDist = player.Position.X - platform.Position.X; // if (halfWidth + playerDist > GameData.MIN_FLOOR_WIDTH) // game.platforms.Add(new Platform(platform.texture, new Vector2((newFloorX - sizeDiff) / 2, platform.Position.Y), halfWidth + playerDist)); // if (halfWidth - playerDist > GameData.MIN_FLOOR_WIDTH) // game.platforms.Add(new Platform(platform.texture, new Vector2((newFloorX + sizeDiff) / 2, platform.Position.Y), halfWidth - playerDist)); // } // game.platforms.Remove(platform); // break; //} } if (player.Position.Y > BOTTOM) { // bottom of the level // Kill the player player.Reset(); //if (player.Score == 0) { // for (int i = 0; i < game.players.Count; i++) { // game.players [i].Score++; // } //} //player.Score--; } if (totalCollisions == 0 && player.CurrentState != Player.State.Stunned && player.WallJump == Player.Direction.None) player.CurrentState = Player.State.Jumping; }
private void CheckPlatforms(Player player) { int totalCollisions = 0; foreach (Platform platform in game.platforms) { Vector2 translation = player.Intersects(platform); if (translation != Vector2.Zero) { totalCollisions++; //if (Math.Abs(translation.X) > Math.Abs(translation.Y)/* && !player.WallAbove*/) //{ // player.CurrentState = Player.State.Climbing; // //player.Velocity.Y = player.ActionTime > 0 ? -GameData.CLIMB_SPEED_FAST : -GameData.CLIMB_SPEED; //} //else if (player.CurrentState == Player.State.Climbing) // player.CurrentState = Player.State.Walking; if (translation.Y == 0) // Horizontal collision { if (player.CurrentState == Player.State.Stunned) { player.Velocity.X *= -1; } else { player.Velocity.X = 0; //if (player.InAir && player.JumpTime <= 0) //{ //if (player.WallJump == Player.Jump.None && player.Velocity.Y > 0) // player.Velocity.Y *= GameData.WALL_STICK_SCALE; if (player.Velocity.Y >= GameData.WALL_STICK_VEL) { if (translation.X > 0 && player.TargetVelocity == Player.Direction.Right || translation.X < 0 && player.TargetVelocity == Player.Direction.Left) { player.CurrentState = Player.State.WallStick; } } //player.WallJumpLeway = GameData.WALL_JUMP_LEWAY; //} } } else // Vertical or diagonal collision { if (player.CurrentState == Player.State.Stunned) { player.Velocity.Y *= -1; } else { player.Velocity.Y = 0; player.JumpTime = 0f; if (translation.Y > 0 && player.InAir) { player.CurrentState = Player.State.Walking; player.GrappleTarget = Vector2.Zero; player.JetpackTime = GameData.JETPACK_TIME; player.JetpackEnabled = false; player.JumpsLeft = GameData.TOTAL_JUMPS; } } } player.MoveByPosition(-translation); #if DEBUG if (translation.LengthSquared() > 1) { Console.WriteLine("Collision translation of {0}", translation); platform.Color = Color.Green; } #endif } //else // player is Slamming or Stunned //{ // if (platform.Rotation != 0) // { // MakeParticles(player.Position, platform, GameData.NUM_PART_FLOOR, 0, 1); // } // else // { // MakeParticles(player.Position, platform, GameData.NUM_PART_FLOOR, 0, 1); // float newFloorX = platform.Position.X + player.Position.X; // float sizeDiff = platform.Size.X / 2 + GameData.FLOOR_HOLE / 2; // float halfWidth = platform.Size.X / 2 - GameData.FLOOR_HOLE / 2; // float playerDist = player.Position.X - platform.Position.X; // if (halfWidth + playerDist > GameData.MIN_FLOOR_WIDTH) // game.platforms.Add(new Platform(platform.texture, new Vector2((newFloorX - sizeDiff) / 2, platform.Position.Y), halfWidth + playerDist)); // if (halfWidth - playerDist > GameData.MIN_FLOOR_WIDTH) // game.platforms.Add(new Platform(platform.texture, new Vector2((newFloorX + sizeDiff) / 2, platform.Position.Y), halfWidth - playerDist)); // } // game.platforms.Remove(platform); // break; //} } if (player.Position.Y > BOTTOM) // bottom of the level // Kill the player { player.Reset(); //if (player.Score == 0) { // for (int i = 0; i < game.players.Count; i++) { // game.players [i].Score++; // } //} //player.Score--; } if (totalCollisions == 0 && player.CurrentState != Player.State.Stunned && player.WallJump == Player.Direction.None) { player.CurrentState = Player.State.Jumping; } }
/// <summary> /// Handles input for a single player for given input keys /// </summary> /// <param name="player"></param> /// <param name="controller"></param> private void HandlePlayerInput(Player player, int controller, float deltaTime) { GameData.Controls controls = playerControls[controller]; if (!simulating) { if (controls.Special1) { simTimes.Add(totalTime); keys.Add(GameData.ControlKey.Special1); } if (controls.Special2) { simTimes.Add(totalTime); keys.Add(GameData.ControlKey.Special2); } if (controls.Basic1) { simTimes.Add(totalTime); keys.Add(GameData.ControlKey.Basic1); } if (controls.Down != prevDown) { simTimes.Add(totalTime); prevDown = !prevDown; keys.Add(GameData.ControlKey.Down); } if (controls.JumpHeld != prevJumpHeld) { simTimes.Add(totalTime); prevJumpHeld = !prevJumpHeld; keys.Add(GameData.ControlKey.JumpHeld); } if (controls.Left != prevLeft) { simTimes.Add(totalTime); prevLeft = !prevLeft; keys.Add(GameData.ControlKey.Left); } if (controls.Right != prevRight) { simTimes.Add(totalTime); prevRight = !prevRight; keys.Add(GameData.ControlKey.Right); } } if (player.CurrentState != Player.State.Stunned) { // Wall-jump Vector2 dir = new Vector2(GameData.WALL_HITBOX, 0f); float ray = Raycast(player.Position - dir, dir); if (ray < 1f) player.WallJump = Player.Direction.Left; else if (ray < 2f) player.WallJump = Player.Direction.Right; else player.WallJump = Player.Direction.None; if (controls.JumpHeld) { if (!player.PrevJump) // toggle jump { if (player.CanJump) // normal jump { if (player.Velocity.Y > 0) player.Velocity.Y = 0; player.JumpSpeed = player.Velocity.Y * GameData.JUMP_HOLD_PROP - GameData.JUMP_SPEED; player.Velocity.Y -= GameData.JUMP_SPEED; //player.TargetVelocity = player.TargetVelocity * GameData.JUMP_SLOW; player.CurrentState = Player.State.Jumping; player.JumpTime = GameData.JUMP_TIME; } else if (player.WallJump != Player.Direction.None) // wall jump { if (player.Velocity.Y > 0) player.Velocity.Y = 0; player.JumpSpeed = player.Velocity.Y * GameData.JUMP_HOLD_PROP - GameData.WALL_JUMP_Y; player.Velocity.Y -= GameData.WALL_JUMP_Y; if (player.WallJump == Player.Direction.Left) player.Velocity.X = GameData.WALL_JUMP_X; else player.Velocity.X = -GameData.WALL_JUMP_X; player.JumpTime = GameData.JUMP_TIME; player.WallJump = Player.Direction.None; } else if (player.AbilityOneTime < 0) // jump abilities { switch (player.CurrentCharacter.Ability1) { case Character.AbilityOne.Platform: Platform plat = new Platform(platformTexture, player.Position + new Vector2(0, GameData.PLATFORM_DIST), new Vector2(GameData.PLATFORM_WIDTH, GameData.PLATFORM_HEIGHT)); platforms.Add(plat); player.AbilityOneTime = GameData.PLATFORM_COOLDOWN; player.PlatformTime = GameData.PLATFORM_LIFE; player.SpawnedPlatform = plat; break; case Character.AbilityOne.Grapple: //player.GrappleTarget = player.Position + new Vector2(10f, -10f); dir = new Vector2(player.FacingRight ? 1f : -1f, GameData.GRAPPLE_ANGLE); ray = Raycast(player.Position, dir); if (ray < GameData.MAX_GRAPPLE) { player.GrappleTarget = player.Position + dir * ray; player.TargetRadius = Vector2.Distance(player.Position, player.GrappleTarget); player.GrappleRight = player.Flip == SpriteEffects.None; } break; case Character.AbilityOne.Blink: player.AbilityOneTime = GameData.BLINK_COOLDOWN; player.MoveByPosition(new Vector2(player.FacingRight ? GameData.BLINK_DIST : -GameData.BLINK_DIST, 0)); // TODO maybe do some validation to make sure the person isn't 'cheating' break; case Character.AbilityOne.Jetpack: player.JetpackEnabled = true; // Jetpack is handled below break; case Character.AbilityOne.Jump: if (--player.JumpsLeft > 0) { if (player.Velocity.Y > 0) player.Velocity.Y *= GameData.AIR_JUMP_MOMENTUM_DOWN; else player.Velocity.Y *= GameData.AIR_JUMP_MOMENTUM; player.Velocity.Y -= GameData.AIR_JUMP_SPEED; player.JumpSpeed = player.Velocity.Y * GameData.AIR_JUMP_HOLD; player.JumpTime = GameData.AIR_JUMP_TIME; } break; } } } else if (player.JumpTime > 0) // hold jump in air { if (player.Velocity.Y > player.JumpSpeed) player.Velocity.Y = player.JumpSpeed; } else if (player.JetpackEnabled) { if (player.JetpackTime > 0) { float prevTime = player.JetpackTime; player.JetpackTime -= deltaTime; player.Velocity.Y -= (player.Velocity.Y > 0 ? GameData.JETPACK_ACCEL_DOWN : GameData.JETPACK_ACCEL_UP) * deltaTime; //Console.WriteLine("Jetpacking: {0} at time: {1}", player.Velocity.Y, player.JetpackTime); } } } else // not jumping { player.JumpTime = 0; if (player.GrappleTarget != Vector2.Zero) { // TODO fix when player mashes grapple to get super-speed player.Velocity *= GameData.GRAPPLE_BOOST; player.GrappleTarget = Vector2.Zero; player.AbilityOneTime = GameData.GRAPPLE_COOLDOWN; } player.JetpackEnabled = false; } if (controls.Right) player.TargetVelocity = Player.Direction.Right; else if (controls.Left) player.TargetVelocity = Player.Direction.Left; else player.TargetVelocity = Player.Direction.None; // activate (or toggle) special abilities if (player.AbilityTwoTime < 0 && controls.Special1) { switch (player.CurrentCharacter.Ability2) { case Character.AbilityTwo.Clone: //player.AbilityTwoTime = GameData.CLONE_COOLDOWN; if (player.ClonedPlayer == null) { GameData.SimulatedControls simulatedControls = new GameData.SimulatedControls(this); playerControls.Insert(players.Count, simulatedControls); AI clone = new AI(player, simulatedControls); clone.MaxVelocity = GameData.CLONE_VELOCITY; players.Add(clone); player.ClonedPlayer = clone; player.CloneTime = GameData.CLONE_TIME; clone.AbilityTwoTime = player.CloneTime; } else { AI clone = player.ClonedPlayer; if (clone.Timer > 0) { clone.Controls.JumpHeld = false; } clone.Timer = GameData.CLONE_JUMP_TIME; } break; case Character.AbilityTwo.Timewarp: player.AbilityTwoTime = GameData.TIMEWARP_COOLDOWN; int i = times.Count - 1; while (i >= 0 && times[i] + GameData.TIMEWARP_TIME >= totalTime) i--; if (i >= 0) { Console.WriteLine("Found time: {0}\tCurrent time: {1}", times[i], totalTime); foreach (Player target in players) { if (target != player && target.Alive) { Tuple<Vector2, Vector2> state = target.PrevStates[i]; target.MoveToPosition(state.Item1); target.Velocity = state.Item2; } } } break; case Character.AbilityTwo.Rocket: player.AbilityTwoTime = GameData.ROCKET_COOLDOWN; Vector2 vel = new Vector2(player.FacingRight ? GameData.ROCKET_X : -GameData.ROCKET_X, GameData.ROCKET_Y) + player.Velocity * GameData.ROCKET_SCALE; player.Projectiles.Add(new Projectile(whiteRect, player.Position, Color.DarkOliveGreen, Projectile.Types.Rocket, vel)); break; case Character.AbilityTwo.Hook: if (player.HookedLocation != Vector2.Zero) { player.HookedLocation = Vector2.Zero; player.AbilityTwoTime = GameData.HOOK_COOLDOWN; } else if (player.HookedPlayer != null) { player.HookedPlayer = null; player.AbilityTwoTime = GameData.HOOK_COOLDOWN; } else if (player.Projectiles.Count < 1) // player is not currently firing { //player.AbilityTwoTime = GameData.HOOK_COOLDOWN; vel = new Vector2(player.FacingRight ? GameData.HOOK_X : -GameData.HOOK_X, GameData.HOOK_Y) + player.Velocity * GameData.HOOK_SCALE; Projectile proj = new Projectile(whiteRect, player.Position, Color.DarkSlateGray, Projectile.Types.Hook, vel); proj.LiveTime = GameData.HOOK_LIFE; player.Projectiles.Add(proj); player.HookedLocation = Vector2.Zero; player.HookedPlayer = null; } break; case Character.AbilityTwo.Boomerang: player.AbilityTwoTime = GameData.BOOMERANG_COOLDOWN; vel = new Vector2(player.FacingRight ? GameData.BOOMERANG_X : -GameData.BOOMERANG_X, GameData.BOOMERANG_Y) + player.Velocity * GameData.BOOMERANG_SCALE; player.Projectiles.Add(new Projectile(whiteRect, player.Position, Color.YellowGreen, Projectile.Types.Boomerang, vel)); break; } } if (player.AbilityThreeTime < 0 && controls.Special2) { switch (player.CurrentCharacter.Ability3) { case Character.AbilityThree.Invert: player.AbilityThreeTime = GameData.INVERT_COOLDOWN; InvertScreen = GameData.INVERT_TIME; break; case Character.AbilityThree.Trap: player.AbilityThreeTime = GameData.TRAP_COOLDOWN; drops.Add(new Drop(player, whiteRect, player.Position, 1f, Drop.Types.Trap, Color.Red)); break; } } // Basic attack (with 3 modifiers in both land AND air) // TODO animations (or just smear) for attacks if (controls.Basic1 && player.AttackTime < 0f) { if (controls.Down) // holding down { foreach (Player target in players) { if (target != player && Math.Abs(player.Position.X - target.Position.X) < GameData.ATTACK_DOWN_WIDTH) { if (target.Position.Y > player.Position.Y - player.Size.Y / 2f && target.Position.Y < player.Position.Y + GameData.ATTACK_DOWN_HEIGHT) { if (target.Velocity.Y < 0) target.Velocity.Y = 0; target.Velocity += new Vector2(player.FacingRight ? GameData.ATTACK_DOWN_X : -GameData.ATTACK_DOWN_X, GameData.ATTACK_DOWN_Y) + player.Velocity * GameData.ATTACK_DOWN_MOMENTUM; hitPause = GameData.HIT_PAUSE; player.AttackTime = GameData.ATTACK_TIME; player.ShowSmear = true; } } } } else if (player.TargetVelocity == Player.Direction.None) // no direction { foreach (Player target in players) { if (target != player && Math.Abs(player.Position.Y - target.Position.Y) < GameData.ATTACK_NORM_HEIGHT) { if (player.FacingRight) { if (target.Position.X > player.Position.X - player.Size.X / 2f && target.Position.X < player.Position.X + GameData.ATTACK_NORM_WIDTH) { if (target.Velocity.X < 0) target.Velocity.X = 0; if (target.Velocity.Y > 0) target.Velocity.Y = 0; target.Velocity += new Vector2(GameData.ATTACK_NORM_X, GameData.ATTACK_NORM_Y) + player.Velocity * GameData.ATTACK_NORM_MOMENTUM; hitPause = GameData.HIT_PAUSE; player.AttackTime = GameData.ATTACK_TIME; player.ShowSmear = true; } } else { if (target.Position.X < player.Position.X + player.Size.X / 2f && target.Position.X > player.Position.X - GameData.ATTACK_NORM_WIDTH) { if (target.Velocity.X > 0) target.Velocity.X = 0; if (target.Velocity.Y > 0) target.Velocity.Y = 0; target.Velocity += new Vector2(-GameData.ATTACK_NORM_X, GameData.ATTACK_NORM_Y) + player.Velocity * GameData.ATTACK_NORM_MOMENTUM; hitPause = GameData.HIT_PAUSE; player.AttackTime = GameData.ATTACK_TIME; player.ShowSmear = true; } } } } } else // holding left or right { foreach (Player target in players) { if (target != player && Math.Abs(player.Position.Y - target.Position.Y) < GameData.ATTACK_SIDE_HEIGHT) { if (player.FacingRight) { if (target.Position.X > player.Position.X - player.Size.X / 2f && target.Position.X < player.Position.X + GameData.ATTACK_SIDE_WIDTH) { if (target.Velocity.X < 0) target.Velocity.X = 0; if (target.Velocity.Y > 0) target.Velocity.Y = 0; target.Velocity += new Vector2(GameData.ATTACK_SIDE_X + player.Velocity.X * GameData.ATTACK_SIDE_MOMENTUM, GameData.ATTACK_SIDE_Y); hitPause = GameData.HIT_PAUSE; player.AttackTime = GameData.ATTACK_TIME; player.ShowSmear = true; } } else { if (target.Position.X < player.Position.X + player.Size.X / 2f && target.Position.X > player.Position.X - GameData.ATTACK_SIDE_WIDTH) { if (target.Velocity.X > 0) target.Velocity.X = 0; if (target.Velocity.Y > 0) target.Velocity.Y = 0; target.Velocity += new Vector2(-GameData.ATTACK_SIDE_X + player.Velocity.X * GameData.ATTACK_SIDE_MOMENTUM, GameData.ATTACK_SIDE_Y); hitPause = GameData.HIT_PAUSE; player.AttackTime = GameData.ATTACK_TIME; player.ShowSmear = true; } } } } } } } player.PrevJump = controls.JumpHeld; }