} // end of Refresh() public override void Update(ref Matrix parentMatrix) { int focus = SelectionIndex.X; bool wasDirty = dirty; GamePadInput pad = GamePadInput.GetGamePad0(); base.Update(ref parentMatrix); // Did something change? If so, update the transforms for the tiles. if (wasDirty || focus != SelectionIndex.X) { float twitchTime = Time.FrameRate > 20.0f ? 0.2f : 0.0f; Vector3 negativeX = new Vector3(-1.0f, 1.0f, 1.0f); Vector3 rotation = new Vector3(kTipBackAngle, 0.0f, 0.0f); for (int i = 0; i < ActualDimensions.X; i++) { UIGridElement e = grid[i, 0]; e.Rotation = rotation; int index = focusIndex.X - i; if (index >= 0) { //e.Position = positions[index]; e.TwitchPosition(positions[index], twitchTime, TwitchCurve.Shape.OvershootOut); } else { Vector3 position = positions[-index]; position.X = -position.X; //e.Position = position; e.TwitchPosition(position, twitchTime, TwitchCurve.Shape.OvershootOut); } } } var brushElement = (UIGrid2DBrushElement)SelectionElement; var overlay = (string)(brushElement.Tag); HelpOverlay.ReplaceTop(overlay); } // end of Update();
private void CheckResizeSelection() { GamePadInput pad = GamePadInput.GetGamePad0(); const float kMinResizeTime = 0.25f; if (sizeTimer >= kMinResizeTime) { if (Actions.BrushLarger.WasPressedOrRepeat) { inGame.Terrain.ExpandSelection(); sizeTimer = 0.0f; } if (Actions.BrushSmaller.WasPressedOrRepeat) { inGame.Terrain.ShrinkSelection(); sizeTimer = 0.0f; } } }
/// <summary> /// If we're using the right trigger, then null out the a button action. /// It will still advance the cursor, but we don't want to do a road snap over it. /// </summary> /// <param name="rightMode"></param> /// <param name="aButton"></param> /// <param name="leftMode"></param> protected override void ProcessStretched( Terrain.EditMode rightMode, Terrain.EditMode aButton, Terrain.EditMode leftMode) { GamePadInput pad = GamePadInput.GetGamePad1(); if (StretchGoing && RightTriggerOn) { rightTriggered = true; } aButton = rightTriggered ? Terrain.EditMode.Noop : Terrain.EditMode.RoadSnap; base.ProcessStretched(Terrain.EditMode.Road, aButton, Terrain.EditMode.Smooth); if (pad.ButtonA.WasPressed) { rightTriggered = false; } }
public Paddle(Texture2D texture, ESide side, int screenWidth, int screenHeight, KeyboardInput keyboardInput = null, GamePadInput gamePadInput = null) { _screenWidth = screenWidth; _screenHeight = screenHeight; Vector2 position = new Vector2(); if (side == ESide.Left) { position.X = 0 + texture.Width; position.Y = screenHeight / 2; } else if (side == ESide.Right) { position.X = screenWidth - (texture.Width * 2); position.Y = screenHeight / 2; } _sprite = new Sprite("", texture, position, keyboardInput, gamePadInput); }
} // end of SetXButton() public override void Update(ref Matrix parentMatrix) { // Check for input but only if selected. if (selected) { GamePadInput pad = GamePadInput.GetGamePad0(); if (Actions.ComboRight.WasPressedOrRepeat) { Actions.ComboRight.ClearAllWasPressedState(); curIndex = (curIndex + 1) % 3; Foley.PlayClickUp(); dirty = true; } if (Actions.ComboLeft.WasPressedOrRepeat) { Actions.ComboLeft.ClearAllWasPressedState(); curIndex = (curIndex + 3 - 1) % 3; Foley.PlayClickDown(); dirty = true; } if (Actions.X.WasPressed) { Actions.X.ClearAllWasPressedState(); if (onXButton != null) { onXButton(curIndex); } } } RefreshTexture(); base.Update(ref parentMatrix); } // end of UIGridModularCameraModeElement Update()
/// <summary> /// Update the strengths of the left and right trigger effects. /// </summary> protected void UpdateRates() { if (!starting) { bool rightOn = RightTriggerOn; GamePadInput pad = GamePadInput.GetGamePad0(); rightRate = pad.RightTrigger; rightRate += inGame.MouseEdit.RightTrigger; if (rightRate < kSmallRate) { rightRate = 0.0f; } rightWasPressed = RightTriggerOn && !rightOn; bool leftOn = LeftTriggerOn; leftRate = pad.LeftTrigger; leftRate += inGame.MouseEdit.LeftTrigger; if (leftRate < kSmallRate) { leftRate = 0.0f; } leftWasPressed = LeftTriggerOn && !leftOn; bool aButtonOn = AButtonOn; aButtonRate = pad.ButtonA.IsPressed || KeyboardInput.IsPressed(Keys.A) ? 1.0f : 0.0f; float mouseA = inGame.MouseEdit.MiddleTrigger; aButtonRate = Math.Max(aButtonRate, mouseA); if (aButtonRate < kSmallRate) { aButtonRate = 0.0f; } aButtonWasPressed = AButtonOn && !aButtonOn; } else { rightRate = leftRate = aButtonRate = 0.0f; rightWasPressed = leftWasPressed = aButtonWasPressed = false; } }
public static AnimatedSprite Adventurer(Vector2 position) { AnimatedSprite adventurer = new AnimatedSprite("adventurer", Contents.adventurer, position, PlayerIndex.One, fps: 6, keyboardInput: KeyboardInput.Default(), gamePadInput: GamePadInput.Default(), isInteractable: true); adventurer.AddAnimation(EAnimation.Idle, 4, 50, 37, 0, 0, Vector2.Zero, 4, () => Console.WriteLine("Idle start"), () => Console.WriteLine("Idle end")); adventurer.AddAnimation(EAnimation.IdleLeft, 4, 50, 37, 0, 0, Vector2.Zero, 4, () => Console.WriteLine("IdleLeft start"), () => Console.WriteLine("IdleLeft end")); adventurer.AddAnimation(EAnimation.IdleUp, 4, 50, 37, 0, 0, Vector2.Zero, 4, () => Console.WriteLine("IdleUp start"), () => Console.WriteLine("IdleUp end")); adventurer.AddAnimation(EAnimation.IdleRight, 4, 50, 37, 0, 0, Vector2.Zero, 4, () => Console.WriteLine("IdleRight start"), () => Console.WriteLine("IdleRight end")); adventurer.AddAnimation(EAnimation.IdleDown, 4, 50, 37, 0, 0, Vector2.Zero, 4, () => Console.WriteLine("IdleDown start"), () => Console.WriteLine("IdleDown end")); adventurer.AddAnimation(EAnimation.Left, 5, 50, 37, 37, 1, Vector2.Zero, 5); adventurer.AddAnimation(EAnimation.Up, 5, 50, 37, 37, 1, Vector2.Zero, 5); adventurer.AddAnimation(EAnimation.Right, 5, 50, 37, 37, 1, Vector2.Zero, 5); adventurer.AddAnimation(EAnimation.Down, 5, 50, 37, 37, 1, Vector2.Zero, 5); adventurer.AddAnimation(EAnimation.MeleeLeft, 7, 50, 37, 222, 0, Vector2.Zero, 7, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.IdleLeft)); adventurer.AddAnimation(EAnimation.MeleeUp, 7, 50, 37, 222, 0, Vector2.Zero, 7, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.IdleUp)); adventurer.AddAnimation(EAnimation.MeleeRight, 7, 50, 37, 222, 0, Vector2.Zero, 7, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.IdleRight)); adventurer.AddAnimation(EAnimation.MeleeDown, 7, 50, 37, 222, 0, Vector2.Zero, 7, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.IdleDown)); adventurer.AddAnimation(EAnimation.Melee1, 7, 50, 37, 222, 0, Vector2.Zero, 8, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.Idle)); adventurer.AddAnimation(EAnimation.Melee2, 4, 50, 37, 259, 0, Vector2.Zero, 8, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.Idle)); adventurer.AddAnimation(EAnimation.Melee3, 3, 50, 37, 259, 4, Vector2.Zero, 4, onAnimationEnd: () => adventurer.SetAnimation(EAnimation.Idle)); return(adventurer); }
/// <summary> /// Take snapshot of terrain height at appropriate times. /// </summary> private void CheckLevel() { GamePadInput pad = GamePadInput.GetGamePad1(); if (pad.ButtonA.WasPressed || RightWasPressed) { float height = Terrain.GetTerrainHeight(shared.editBrushStart); inGame.Terrain.LevelHeight = height; } /// If we have a point selected, hide the cursor float startToEnd = Vector2.DistanceSquared(shared.editBrushPosition, shared.editBrushStart); const float kMaxDist = 0.1f * 0.1f; if (pad.ButtonA.IsPressed || RightTriggerOn || (startToEnd > kMaxDist)) { inGame.HideCursor(); } else { inGame.ShowCursor(); } }
} // end of RoadLevelTool Update() #endregion Public #region Internal /// <summary> /// Take snapshot of terrain height at appropriate times. /// </summary> protected virtual void CheckLevel() { if (!InStretchMode) { GamePadInput pad = GamePadInput.GetGamePad0(); if (pad.ButtonA.WasPressed || RightWasPressed || LeftWasPressed) { shared.editBrushStart = shared.editBrushPosition; float height = Terrain.GetTerrainHeightFlat(shared.editBrushStart); inGame.Terrain.LevelHeight = height; } /// If we have a point selected, hide the cursor if (pad.ButtonA.IsPressed || RightTriggerOn) { inGame.HideCursor(); } else { inGame.ShowCursor(); } } }
private void TestXml() { GamePadInput pad = GamePadInput.GetGamePad0(); if (pad.ButtonY.WasPressed) { doTest = 0; } if (doTest >= 0) { if (!Storage4.FileExists(BokuGame.Settings.MediaPath + @"Xml\OptionsData.Xml")) { doTest = 0; } XmlOptionsData.UIVolume = XmlOptionsData.UIVolume; if (!Storage4.FileExists(BokuGame.Settings.MediaPath + @"Xml\OptionsData.Xml")) { doTest = 0; } ++testsDone; } }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here Contents.LoadAll(Content, graphics.GraphicsDevice); paddleOne = new Paddle(Contents.paddle, ESide.Left, screenWidth, screenHeight, KeyboardInput.Default()); paddleTwo = new Paddle(Contents.paddle, ESide.Right, screenWidth, screenHeight, gamePadInput: GamePadInput.Default()); ball = new Ball(Contents.ball, new Vector2(screenWidth / 2, screenHeight / 2), screenWidth, screenHeight); ball.Sprite.CollisionHandler = partner => { ball.Forward = !ball.Forward; }; collisionManager = new CollisionManager(paddleOne.Sprite, paddleTwo.Sprite, ball.Sprite); }
// c'tor public Events(Object obj, PlayerIndex index) { this.creator = obj; this.index = index; switch (index) { case PlayerIndex.One: this.gamePad = gamePad1; break; case PlayerIndex.Two: this.gamePad = gamePad2; break; case PlayerIndex.Three: this.gamePad = gamePad3; break; case PlayerIndex.Four: this.gamePad = gamePad4; break; } } // end of Events c'tor
public Sprite(string name, Vector2 position, PlayerIndex playerIndex, GraphicsDevice graphicsDevice, Texture2D texture = null, KeyboardInput input = null, GamePadInput gamePadInput = null) { // Assign Parameter Values _name = name; _position = position; _playerIndex = playerIndex; _texture = texture; _keyboardInput = input; _gamePadInput = gamePadInput; // BoundingBox _boundingBox = new Rectangle((int)_position.X, (int)_position.Y, _texture.Width, _texture.Height); _boundingBoxLeftLine = new Rectangle(_boundingBox.X, _boundingBox.Y, 2, _texture.Height); _boundingBoxTopLine = new Rectangle(_boundingBox.X, _boundingBox.Y, _texture.Width, 2); _boundingBoxRightLine = new Rectangle(_boundingBox.X + _texture.Width - 2, _boundingBox.Y, 2, _texture.Height); _boundingBoxBottomLine = new Rectangle(_boundingBox.X, _boundingBox.Y + _texture.Height - 2, _texture.Width, 2); _boundingBoxTexture = new Texture2D(graphicsDevice, 1, 1, false, SurfaceFormat.Color); _boundingBoxTexture.SetData(new[] { Color.White }); // HandleConstructorDefaults(); }
} // end of ToolMenu Update() #if MF_HOSE_TESTS private void TestUndo() { GamePadInput pad = GamePadInput.GetGamePad0(); if (pad.ButtonY.WasPressed) { doTest = 0; pad.ButtonY.ClearAllWasPressedState(); } if (doTest >= 0) { { XmlGameActor testXml = XmlGameActor.Deserialize("BalloonBot"); if (testXml == null) { doTest = 0; } } bool doUndo = BokuGame.bokuGame.rnd.NextDouble() > 0.5f; if (doUndo) { InGame.UnDoStack.UnDo(); } else { InGame.UnDoStack.ReDo(); } { XmlGameActor testXml = XmlGameActor.Deserialize("BalloonBot"); if (testXml == null) { doTest = 0; } } } }
} // end of UIGridTextListElement AddText() public override void Update(ref Matrix parentMatrix) { // Check for input but only if selected. if (selected && textList.Count > 1) { GamePadInput pad = GamePadInput.GetGamePad0(); bool changed = false; // Handle input changes here. if (pad.ButtonA.WasPressed || pad.ButtonA.WasRepeatPressed) { do { ++curIndex; if (curIndex >= textList.Count) { curIndex = 0; } Foley.PlayClick(); changed = true; } while (textList[curIndex].Hidden); } if (changed) { onChange(textList[curIndex].Text); dirty = true; //RecalcPositions(); } } RefreshTexture(); base.Update(ref parentMatrix); } // end of UIGridTextListElement Update()
} // end of SetXButton() public override void Update(ref Matrix parentMatrix) { // Check for input but only if selected. if (selected) { GamePadInput pad = GamePadInput.GetGamePad0(); if (pad.ButtonA.WasPressed) { check = !check; if (check && onCheck != null) { onCheck(); } else if (!check && onClear != null) { onClear(); } Foley.PlayClick(); dirty = true; } if (pad.ButtonX.WasPressed) { if (onXButton != null) { onXButton(); } } } RefreshTexture(); base.Update(ref parentMatrix); } // end of UIGridCheckboxElement Update()
protected virtual void ProcessBButton() { float distSq = Vector2.DistanceSquared(shared.editBrushStart, shared.editBrushPosition); bButtonExits = distSq < kSmallMoveSq; GamePadInput pad = GamePadInput.GetGamePad0(); if (Actions.Cancel.IsPressed) { if (!bButtonExits) { StretchPhase = Phase.Open; Actions.Cancel.IgnoreUntilReleased(); } } if (MouseInput.Left.WasPressed && !LeftTriggerOn && !RightTriggerOn && !AButtonOn) { StretchPhase = Phase.Open; } }
} // end of OnSaveLevelDialogButton() /// <summary> /// OnSelect method used by mini-hub grid. If the level is dirty and needs to /// be saved the SaveChagesDialog will be activated. Upon its deactivation /// the level should no longer be marked dirty and OnSelect() will get called /// again allowing the user's action to be executed. /// </summary> /// <param name="grid"></param> public void OnSelect(ModularMenu menu) { // Prevent the button pressed from leaking into runtime. GamePadInput.IgnoreUntilReleased(Buttons.A); // In every case, we need to reset the level to its starting state. InGame.inGame.ResetSim(preserveScores: false, removeCreatablesFromScene: false, keepPersistentScores: false); // Resetting the sim just started up all game audio, let's pause it down again. // It will be resumed when we go back into sim mode. BokuGame.Audio.PauseGameAudio(); // Flag to let us know if the level needs saving. If the save changes // dialog has already been activated then just set this to false. bool needToSaveLevel = (InGame.IsLevelDirty || InGame.AutoSaved) && !saveChangesActivated; // Does the current world belong to the user. Required to share to community. // Test the genre flag and also special case look at empty world. bool isMyWorld = false; if (InGame.XmlWorldData != null) { bool genreTest = ((int)InGame.XmlWorldData.genres & (int)Genres.MyWorlds) != 0; bool newWorldTest = InGame.XmlWorldData.Filename == emptyWorldFileName; if (genreTest && !newWorldTest) { isMyWorld = true; } } // Normally there would be a switch here but if we compare strings // we proof ourselves against changes in the order of the elements. if (menu.CurString == Strings.Localize("miniHub.reset")) { // Reset. // We've already done a Reset, so force to RunSim mode if we already aren't. Deactivate(); InGame.inGame.Activate(); InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.RunSim; InGame.inGame.RestorePlayModeCamera(); // The ResetSim above doesn't ApplyInlining since it's generally // meant for resetting into the editor. In this case we're going // into RunSim mode so be sure to apply inlining first. InGame.ApplyInlining(); if (InGame.inGame.PreGame != null) { InGame.inGame.PreGame.Active = true; } } else if (menu.CurString == Strings.Localize("miniHub.edit")) { // Edit level. Deactivate(); InGame.inGame.Activate(); InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.ToolMenu; } else if (menu.CurString == Strings.Localize("miniHub.save")) { // Save saveLevelDialog.Activate(); } else if (menu.CurString == Strings.Localize("miniHub.publish")) { // Offer to save first. Need to save if world has changed or is world doesn't belong to user. if (needToSaveLevel || !isMyWorld) { saveChangesActivated = true; saveChangesMessage.Activate(); } else { var level = LevelMetadata.CreateFromXml(InGame.XmlWorldData); shared.communityShareMenu.Activate(level); } } else if (menu.CurString == Strings.Localize("miniHub.load")) { // Load. // If we're back here and saveChangesActivated is true then the // user was given the option to save changes and chose Discard. // So don't offer to save again. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Deactivate mini-hub and bring up loading menu. Deactivate(); //InGame.inGame.DiscardTerrain(); BokuGame.bokuGame.loadLevelMenu.LocalLevelMode = LoadLevelMenu.LocalLevelModes.General; BokuGame.bokuGame.loadLevelMenu.ReturnToMenu = LoadLevelMenu.ReturnTo.MiniHub; BokuGame.bokuGame.loadLevelMenu.Activate(); } } else if (menu.CurString == Strings.Localize("miniHub.emptyLevel")) { // Empty Level. // If saveChangesActivated is already true then user chose Discard and // we can ignore the needToSaveLevel flag. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Undo any previous warping. ScreenWarp.FitRtToScreen(BokuGame.ScreenSize); newWorldDialog.Active = true; } } else if (menu.CurString == Strings.Localize("miniHub.print")) { Print.PrintProgramming(); // We don't want to exit the mini-hub so re-activate the menu. shared.menu.Active = true; } else if (menu.CurString == Strings.Localize("miniHub.quit")) { // Exit to main menu. // If we're back here and saveChangesActivated is true then the // user was given the option to save changes and chose Discard. // So don't offer to save again. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Wave bye, bye. Go back to the main menu Deactivate(); InGame.inGame.StopAllSounds(); BokuGame.bokuGame.mainMenu.Activate(); } } } // end of MiniHub OnSelect()
/// <summary> /// Called once per frame. /// If camera is null, assumes everything is in screenspace. /// </summary> public void Update(Camera camera) { if (Active) { // Don't let anyone else grab focus, if anyone has, grab it back. if (CommandStack.Peek() != commandMap) { CommandStack.Pop(commandMap); CommandStack.Push(commandMap); } // Check if we have input focus. if (CommandStack.Peek() == commandMap) { GamePadInput pad = GamePadInput.GetGamePad0(); if (handlerA != null && Actions.A.WasPressed) { Actions.A.ClearAllWasPressedState(); Actions.A.IgnoreUntilReleased(); handlerA(this); } if (handlerB != null && Actions.B.WasPressed) { Actions.B.ClearAllWasPressedState(); Actions.B.IgnoreUntilReleased(); handlerB(this); } if (handlerX != null && Actions.X.WasPressed) { Actions.X.ClearAllWasPressedState(); Actions.X.IgnoreUntilReleased(); handlerX(this); } if (handlerY != null && Actions.Y.WasPressed) { Actions.Y.ClearAllWasPressedState(); Actions.Y.IgnoreUntilReleased(); handlerY(this); } Vector2 hit; if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { for (int i = 0; i < TouchInput.TouchCount; i++) { TouchContact touch = TouchInput.GetTouchContactByIndex(i); hit = touch.position; if (camera != null) { hit = MouseInput.AdjustHitPosition(hit, camera, false, false); } hit = hit - pos; HandleTouchInput(hit, touch); } } else { // Since the dialog is screenspace we can use the mouse position directly. hit = MouseInput.PositionVec; if (useRtCoords) { hit = ScreenWarp.ScreenToRT(hit); } hit -= pos; HandleMouseInput(hit); } } // end if we have input focus. RefreshTexture(); } } // end of Update()
} // end of c'tor public void Update(Camera camera) { if (Active) { GamePadInput pad = GamePadInput.GetGamePad0(); if (Actions.Select.WasPressed) { Actions.Select.ClearAllWasPressedState(); // Disable this hint for this session. if (curHint.ShowOnce) { curHint.Disabled = true; } Deactivate(); } if (Actions.X.WasPressed) { Actions.X.ClearAllWasPressedState(); // Disable this hint until reset by user. XmlOptionsData.SetHintAsDisabled(curHint.ID); // Disable this hint for this session. if (curHint.ShowOnce) { curHint.Disabled = true; } Deactivate(); } // We need to be able to slip out to the mini-hub here since // continuous, repeated calls to ScrollableModalHint can lock the // user out of control. if (Actions.MiniHub.WasPressed) { Actions.MiniHub.ClearAllWasPressedState(); Deactivate(); InGame.inGame.SwitchToMiniHub(); } // We need to be able to slip out to the tool menu here since // continuous, repeated calls to ScrollableModalHint can lock the // user out of control. if (Actions.ToolMenu.WasPressed) { Actions.ToolMenu.ClearAllWasPressedState(); Deactivate(); if (InGame.inGame.State == InGame.States.Active) { InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.ToolMenu; } } // Scroll text??? if (blob.NumLines != 0) { int scroll = MouseInput.ScrollWheel - MouseInput.PrevScrollWheel; if (Actions.Up.WasPressedOrRepeat || scroll > 0) { ScrollDown(); } if (Actions.Down.WasPressedOrRepeat || scroll < 0) { ScrollUp(); } // If we're not shutting down... if (Active) { } // end if not shutting down. } // We should be on top and owning all input // focus so don't let anthing trickle down. GamePadInput.ClearAllWasPressedState(); // Disable the help overlay's tool icon because in some situations // it can overlap the text making it unreadable. HelpOverlay.ToolIcon = null; // If active we need to pre-render the text to the 1k rendertarget since // changing render targets on the Xbox forces a resolve. PreRender(); // If we're rendering this into a 1280x720 rt we need a matching camera to calc mouse hits. if (useBackgroundThumbnail) { camera = new PerspectiveUICamera(); camera.Resolution = new Point(1280, 720); } if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { for (int i = 0; i < TouchInput.TouchCount; i++) { TouchContact touch = TouchInput.GetTouchContactByIndex(i); Vector2 touchHit = touch.position; // Adjust for position and scaling of final rendering. touchHit -= renderPosition; touchHit /= renderScale; if (useRtCoords) { touchHit = ScreenWarp.ScreenToRT(touch.position); } HandleTouchInput(touch, touchHit); } } else if (GamePadInput.ActiveMode == GamePadInput.InputMode.KeyboardMouse) { Vector2 hit = MouseInput.PositionVec; // Adjust for position and scaling of final rendering. hit -= renderPosition; hit /= renderScale; if (useRtCoords) { hit = MouseInput.GetMouseInRtCoords(); } HandleMouseInput(hit); } } // end if active. } // end of Update()
protected void UpdateCommands() { this.stickCommands.Clear(); // Note that we're getting the pads via logical mapping. GamePadInput pad1 = GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(PlayerIndex.One)); GamePadInput pad2 = GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(PlayerIndex.Two)); GamePadInput pad3 = GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(PlayerIndex.Three)); GamePadInput pad4 = GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(PlayerIndex.Four)); switch (this.stick) { case GamePadStick.Left: if (this.playerId == GamePadSensor.PlayerId.All) { //add pad 1 if it was touched, we're using virtual controller, or the other pads aren't present if (pad1.EverTouched || InGame.ShowVirtualController || (!pad2.EverTouched && !pad3.EverTouched && !pad4.EverTouched)) { this.stickCommands.Add(new GamePadLeftThumbStick(PlayerIndex.One)); } if (pad2.EverTouched) { this.stickCommands.Add(new GamePadLeftThumbStick(PlayerIndex.Two)); } if (pad3.EverTouched) { this.stickCommands.Add(new GamePadLeftThumbStick(PlayerIndex.Three)); } if (pad4.EverTouched) { this.stickCommands.Add(new GamePadLeftThumbStick(PlayerIndex.Four)); } } else { this.stickCommands.Add(new GamePadLeftThumbStick((PlayerIndex)this.playerId)); } break; case GamePadStick.Right: if (this.playerId == GamePadSensor.PlayerId.All) { //add pad 1 if it was touched, we're using virtual controller, or the other pads aren't present if (pad1.EverTouched || InGame.ShowVirtualController || (!pad2.EverTouched && !pad3.EverTouched && !pad4.EverTouched)) { this.stickCommands.Add(new GamePadRightThumbStick(PlayerIndex.One)); } if (pad2.EverTouched) { this.stickCommands.Add(new GamePadRightThumbStick(PlayerIndex.Two)); } if (pad3.EverTouched) { this.stickCommands.Add(new GamePadRightThumbStick(PlayerIndex.Three)); } if (pad4.EverTouched) { this.stickCommands.Add(new GamePadRightThumbStick(PlayerIndex.Four)); } } else { this.stickCommands.Add(new GamePadRightThumbStick((PlayerIndex)this.playerId)); } break; } }
public override bool MatchAction(Reflex reflex, out object param) { GamePadSensor.PlayerId playerIdSensor = (GamePadSensor.PlayerId)reflex.targetSet.Param; if (this.playerId != playerIdSensor) { this.playerId = playerIdSensor; UpdateCommands(); } bool isPitch = (reflex.Selector is MoveDownSelector) || (reflex.Selector is MoveUpDownSelector) || (reflex.Selector is MoveUpSelector); bool isYaw = !isPitch && reflex.Data.IsMovement(); bool match = false; param = null; if (this.stickCommands.Count != 0) { this.stickPosition = Vector2.Zero; for (int indexCommand = 0; indexCommand < this.stickCommands.Count; indexCommand++) { StickCommand command = this.stickCommands[indexCommand] as StickCommand; command.Update(); // Bias stick input toward center if pushing forward. Vector2 stick = command.Position; if (isPitch) { bool invert = GamePadInput.InvertYAxis(command.playerIndex); if (invert) { stick.Y = -stick.Y; } } if (isYaw) { bool invert = GamePadInput.InvertXAxis(command.playerIndex); if (invert) { stick.X = -stick.X; } } // 5% flat deadzone. Vector2 s; s.X = stick.X > 0 ? Math.Max(stick.X * 1.05f - 0.05f, 0) : Math.Min(stick.X * 1.05f + 0.05f, 0); s.Y = stick.Y > 0 ? Math.Max(stick.Y * 1.05f - 0.05f, 0) : Math.Min(stick.Y * 1.05f + 0.05f, 0); stickPosition += s; // If a stick is being used for input in a bot program, don't blend it into gamepad0. if (command is Input.GamePadRightThumbStick) { GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(command.playerIndex)).RightStickIgnoreForGamePad0(); } else if (command is Input.GamePadLeftThumbStick) { GamePadInput.GetGamePad(GamePadInput.LogicalToGamePad(command.playerIndex)).LeftStickIgnoreForGamePad0(); } } param = this.stickPosition; match = (this.stickPosition != Vector2.Zero); // only if not centered } return(match); }
/// <summary> /// Initializes the MonoKle backend, returning a runnable game instance. /// </summary> /// <param name="enableConsole">Enables console.</param> /// <returns>Runnable <see cref="MGame"/>.</returns> public static MGame Initialize(bool enableConsole) { MBackend.initializing = true; AppDomain.CurrentDomain.UnhandledException += UnhandledException; MBackend.Logger = Logger.Global; MBackend.GameInstance = new MGame(); MBackend.GraphicsManager = new GraphicsManager(new GraphicsDeviceManager(MBackend.GameInstance)); MBackend.gamepad = new GamePadInput(); MBackend.keyboard = new KeyboardInput(); MBackend.mouse = new MouseInput(); MBackend.stateSystem = new StateSystem(); MBackend.GameInstance.RunOneFrame(); MBackend.InitializeTextureStorage(); MBackend.InitializeFontStorage(); MBackend.EffectStorage = new EffectStorage(GraphicsManager.GetGraphicsDevice()); MBackend.MessagePasser = new MessagePasser(); MBackend.InitializeConsole(); mouse.ScreenSize = GraphicsManager.ScreenSize; console.WriteLine("MonoKle Engine initialized!", Color.LightGreen); console.WriteLine("Running version: " + Assembly.GetCallingAssembly().GetName().Version, Color.LightGreen); MBackend.initializing = false; return MBackend.GameInstance; }
} // end of RunSimUpdateObj c'tor /// <summary> /// RunSimUpdateObj Update() /// </summary> /// <param name="camera"></param> public override void Update() { base.Update(); parent.Camera.Update(); float secs = Time.WallClockFrameSeconds; ThoughtBalloonManager.Update(shared.camera); SaidStringManager.Update(); #if !NETFX_CORE MicrobitManager.Update(); #endif // Start with visible cursor. parent.cursor3D.Activate(); parent.cursor3D.Rep = Cursor3D.Visual.RunSim; parent.cursor3D.Hidden = false; // // Determine the correct camera mode. // // // The priorities used to determine the camera mode when the game is running are: // // 1) First person. This can be either via programming or because the user zoomed // into a bot the camera was following. // 2) Follow mode caused by bot(s) programmed with "follow" camera view. // 3) World tweak screen fixed camera or fixed offset camera. // 4) Follow mode caused by user controlled bot(s). // 5) Free camera. // // Start with a fake loop to break out of. while (true) { Terrain terrain = InGame.inGame.Terrain; // Just a shortcut. // // Always use edit mode when the game is paused except during victory on level with one of the fixed cameras // or when game is paused for a bot to speak (modal text display). // bool victoryActive = VictoryOverlay.ActiveGameOver || VictoryOverlay.ActiveWinner; bool speaking = InGame.inGame.shared.smallTextDisplay.Active || InGame.inGame.shared.scrollableTextDisplay.Active; if (Time.Paused && !((terrain.FixedCamera || terrain.FixedOffsetCamera) && victoryActive) && !speaking) { CameraInfo.Mode = CameraInfo.Modes.Edit; CameraInfo.CameraFocusGameActor = null; break; } // // 1) First person // if (CameraInfo.FirstPersonActive) { CameraInfo.Mode = CameraInfo.Modes.Actor; // We're following a single actor so update the FollowActor camera values. shared.camera.FollowCameraValid = false; // Turn off 3d cursor since we don't need it. parent.cursor3D.Deactivate(); if (parent.cursorClone != null) { parent.cursorClone.Deactivate(); parent.cursorClone = null; } break; } // // 2) Follow mode caused by bot(s) programmed with "follow" camera view. // if (CameraInfo.ProgrammedFollowList.Count > 0) { // Note that even though we looked at the count of bot programmed to // have the camera follow them, for this mode we want to keep all // deserving bots in camera. So, the rest of this section will use // the merged follow list instead of just the programmed follow list. SetUpCameraFollowMode(); break; } // // 3) World tweak fixed cameras. Note for fixed offset we have to let // the later modes do their stuff and then override the camera. // if (terrain.FixedCamera) { CameraInfo.Mode = CameraInfo.Modes.FixedTarget; CameraInfo.CameraFocusGameActor = null; // Turn off 3d cursor since we don't need it. parent.cursor3D.Deactivate(); if (parent.cursorClone != null) { parent.cursorClone.Deactivate(); parent.cursorClone = null; } break; } // // 4) Follow mode caused by user controlled bot(s). // if (CameraInfo.MergedFollowList.Count > 0) { SetUpCameraFollowMode(); break; } // // 5) Free! // // Not following an actor. CameraInfo.Mode = CameraInfo.Modes.Edit; CameraInfo.CameraFocusGameActor = null; // Turn on 3d cursor in case we previously disabled it. parent.cursor3D.Activate(); parent.CreateCursorClone(); parent.cursor3D.Hidden = false; // We have no camera restrictions, so keep track of what the user is doing. shared.camera.PlayValid = true; shared.camera.PlayCameraFrom = shared.camera.From; shared.camera.PlayCameraAt = shared.camera.At; shared.camera.FollowCameraValid = false; // Final break just to be sure the loop exits. break; } // // Now that we're done, we need to check again to see if // we should be in FixedOffsetMode. // if (!Time.Paused && InGame.inGame.Terrain.FixedOffsetCamera && !CameraInfo.FirstPersonActive) { CameraInfo.Mode = CameraInfo.Modes.FixedOffset; } // Zero out any offset while running. float t = Math.Min(Time.GameTimeFrameSeconds, 1.0f); shared.camera.HeightOffset = MyMath.Lerp(shared.camera.HeightOffset, 0.0f, t); // bool inputFocus = CommandStack.Peek() == commandMap; // Move the camera. switch (CameraInfo.Mode) { case CameraInfo.Modes.Edit: MoveCameraEditMode(inputFocus, false); break; case CameraInfo.Modes.Actor: MoveCameraActorMode(true, false); break; case CameraInfo.Modes.FixedTarget: MoveCameraFixedTargetMode(inputFocus); break; case CameraInfo.Modes.FixedOffset: MoveCameraFixedOffsetMode(inputFocus); break; case CameraInfo.Modes.MultiTarget: MoveCameraMultiTargetMode(inputFocus, false); break; } shared.camera.Update(); // Update terrain. parent.terrain.Update(shared.camera); // Update the list of objects using our local camera. for (int i = 0; i < updateList.Count; i++) { UpdateObject obj = (UpdateObject)updateList[i]; obj.Update(); } parent.UpdateObjects(); /// Pregame must update after parent.UpdateObjects, in case it /// decides to switchToMiniHub if (InGame.inGame.preGame != null) { InGame.inGame.preGame.Update(); } // Update the particle system. shared.particleSystemManager.Update(); DistortionManager.Update(); FirstPersonEffectMgr.Update(); // This must be done after all brains are updated. Scoreboard.Update(shared.camera); // Update the TextDisplays. Ignored if not active. shared.scrollableTextDisplay.Update(shared.camera); shared.smallTextDisplay.Update(shared.camera); VictoryOverlay.Update(); // Do the input processing after object update because there will be order of operation issue if we don't // // Check if we have input focus. Don't do any input // related update if we don't. if (inputFocus) { // Grab the current state of the gamepad. GamePadInput pad = GamePadInput.GetGamePad0(); // Switch to Mini-Hub? if (Actions.MiniHub.WasPressed) { Actions.MiniHub.ClearAllWasPressedState(); //parent.ResetSim(CurrentLevelFilename()); // Needed to make sure that deactivated objects are actually removed from // the list otherwise they may get saved along with the newly activated ones. //parent.Refresh(BokuGame.gameListManager.updateList, BokuGame.gameListManager.renderList); parent.SwitchToMiniHub(); return; } //handle swipe to return to edit for touch input if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { SwipeGestureRecognizer swipeGesture = TouchGestureManager.Get().SwipeGesture; if (swipeGesture.WasRecognized && swipeGesture.SwipeDirection == Directions.North) { #if NETFX_CORE float halfWidth = (float)BokuGame.bokuGame.Window.ClientBounds.Width * 0.5f; float height = (float)BokuGame.bokuGame.Window.ClientBounds.Height; #else float halfWidth = (float)XNAControl.Instance.ClientSize.Width * 0.5f; float height = (float)XNAControl.Instance.ClientSize.Height; #endif //center half of the screen width-wise float minX = halfWidth - (halfWidth * k_TouchExitAreaWidthPercent); float maxX = halfWidth + (halfWidth * k_TouchExitAreaWidthPercent); //bottom 20% height-wise float minY = height - (height * k_TouchExitAreaHeightPercent); Vector2 pos = swipeGesture.InitialPosition; if (pos.X >= minX && pos.X <= maxX && pos.Y >= minY) { // User did a swipe from the bottom of the screen, enter edit mode InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject; InGame.inGame.CurrentUpdateMode = UpdateMode.TouchEdit; Foley.PlayPressStart(); return; } } // HACKHACK (****) Put in a tap recognizer since swipe seems to fail. { TapGestureRecognizer hackTapGesture = TouchGestureManager.Get().TapGesture; if (hackTapGesture.WasTapped()) { #if NETFX_CORE float halfWidth = (float)BokuGame.bokuGame.Window.ClientBounds.Width * 0.5f; float height = (float)BokuGame.bokuGame.Window.ClientBounds.Height; #else float halfWidth = (float)XNAControl.Instance.ClientSize.Width * 0.5f; float height = (float)XNAControl.Instance.ClientSize.Height; #endif //center area of the screen width-wise float minX = halfWidth - (halfWidth * 0.1f); float maxX = halfWidth + (halfWidth * 0.1f); //bottom 10% height-wise float minY = height - (height * 0.1f); Vector2 pos = hackTapGesture.Position; if (pos.X >= minX && pos.X <= maxX && pos.Y >= minY) { // User did a tap on the bottom of the screen, enter edit mode InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject; InGame.inGame.CurrentUpdateMode = UpdateMode.TouchEdit; Foley.PlayPressStart(); return; } } } } bool gameOver = VictoryOverlay.GameOver; if (Time.Paused && !gameOver) { // We must be in user induced pause mode. if (Actions.Unpause.WasPressed) { Actions.Unpause.ClearAllWasPressedState(); Time.Paused = false; HelpOverlay.Pop(); } } else { if (gameOver) { // Game over man! Let the user restart if they want. if (Actions.Restart.WasPressed) { Actions.Restart.ClearAllWasPressedState(); InGame.inGame.ResetSim(preserveScores: false, removeCreatablesFromScene: true, keepPersistentScores: false); // Since we're going right back into RunSim mode we need to first inline. ApplyInlining(); } } // Open ToolMenu. if (Actions.ToolMenu.WasPressed) { Actions.ToolMenu.ClearAllWasPressedState(); parent.CurrentUpdateMode = UpdateMode.ToolMenu; Foley.PlayPressStart(); return; } // Pause? // We want to make pause hard to get into so it requires both triggers and both stickButtons to be pressed. if ((pad.LeftStickButton.IsPressed && pad.RightStickButton.IsPressed && pad.LeftTriggerButton.IsPressed && pad.RightTriggerButton.IsPressed) || Actions.Pause.WasPressed) { Actions.Pause.ClearAllWasPressedState(); if (!Time.Paused) { Time.Paused = true; HelpOverlay.Push("PauseGame"); GamePadInput.GetGamePad0().IgnoreLeftStickUntilZero(); GamePadInput.GetGamePad0().IgnoreRightStickUntilZero(); } } } } // Force the the HelpOverlay to be correct. if (!Time.Paused || VictoryOverlay.Active) { if (InGame.inGame.PreGame != null && InGame.inGame.PreGame.Active) { if (HelpOverlay.Depth() != 1 || HelpOverlay.Peek() != "RunSimulationPreGame") { HelpOverlay.Clear(); HelpOverlay.Push("RunSimulationPreGame"); } } else { if (HelpOverlay.Depth() != 1 || HelpOverlay.Peek() != "RunSimulation") { HelpOverlay.Clear(); HelpOverlay.Push("RunSimulation"); } } } else { // We're paused. if (HelpOverlay.Depth() != 2 || HelpOverlay.Peek(1) != "RunSimulation") { HelpOverlay.Clear(); HelpOverlay.Push("RunSimulation"); HelpOverlay.Push("PauseGame"); } } // When in run mode, allow the user to click on the "Press [esc] to edit" text as if it was a button. if (MouseInput.Left.WasPressed) { Point mousePos = MouseInput.Position; if (HelpOverlay.MouseHitBottomText(mousePos)) { // Switch to edit mode. InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject; } } TapGestureRecognizer tapGesture = TouchGestureManager.Get().TapGesture; if (tapGesture.WasTapped()) { // JW - Until we have proper Touch help overlays, we are still using the mouse/keyboard // overlays. The mouse handling code for these depends on being able to 'absorb' pressed // info to hide it from later callers. Our touch stuff doesn't (and really shouldn't) // do this. So, we handle cases here based on what type of overlay is being displayed. if (HelpOverlay.Peek() == "RunSimulationPreGame") { // Tap during instructions: just begin game. InGame.inGame.PreGame.Active = false; } // Also test if running sim for tapping on "tap to edit" at bottom. if (HelpOverlay.Peek() == "RunSimulation") { Point pos = new Point((int)tapGesture.Position.X, (int)tapGesture.Position.Y); if (HelpOverlay.MouseHitBottomText(pos)) { // Switch to edit mode. InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject; } } } } // end of RunSimUpdateObj Update()
} // end of ToolMenu c'tor public void Update() { if (active) { // If we're modal, allow the left stick to control the grid. if (XmlOptionsData.ModalToolMenu) { grid.UseLeftStick = true; } else { grid.UseLeftStick = false; } Matrix mat = Matrix.Identity; mat.Translation = new Vector3(0.0f, -2.2f, -10.0f); grid.LocalMatrix = mat; grid.Update(ref worldMatrix); GamePadInput pad = GamePadInput.GetGamePad0(); if (pad.Back.WasPressed) { Deactivate(); InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.RunSim; return; } if (pad.Start.WasPressed) { Deactivate(); InGame.inGame.SwitchToMiniHub(); return; } #if MF_HOSE_TESTS TestXml2(); #endif // MF_HOSE_TESTS // Undo - Redo if (Actions.Redo.WasPressed) { Actions.Redo.ClearAllWasPressedState(); InGame.UnDoStack.ReDo(); } if (Actions.Undo.WasPressed) { Actions.Undo.ClearAllWasPressedState(); InGame.UnDoStack.UnDo(); } if (curIndex != grid.SelectionIndex.X) { curIndex = grid.SelectionIndex.X; lastChangedTime = Time.WallClockTotalSeconds; } // Make sure camera has correct resolution. camera.Resolution = new Point((int)BokuGame.ScreenSize.X, (int)BokuGame.ScreenSize.Y); camera.Update(); } // end if active } // end of ToolMenu Update()
override protected Vector2 StickValue() { return(GamePadInput.GetGamePad(this.playerIndex).RightStick); }
const float kZoomFactor = 1.1f; // Multiplicative factor applied per second. /// <summary> /// Reads user input to orbit and track the camera position. /// </summary> private void OrbitAndTrackCamera() { GamePadInput pad = GamePadInput.GetGamePad0(); float tics = Time.WallClockFrameSeconds; // Right stick to orbit around cursor. // Note in first person mode, the sense of rotation is reversed. float dRotation = (GamePadInput.InvertCamX() ? -pad.RightStick.X : pad.RightStick.X) * tics * kOrbitSpeed; float dPitch = GamePadInput.InvertCamY() ? -pad.RightStick.Y : pad.RightStick.Y; if (CameraInfo.FirstPersonActive) { parent.Camera.DesiredRotation -= dRotation * 2.0f; parent.Camera.FirstPersonDesiredPitchDelta = -dPitch * kOrbitSpeed; } else { parent.Camera.DesiredRotation += dRotation; parent.Camera.DesiredPitch -= dPitch * tics * kOrbitSpeed; } // If the user has programmed the right mouse button, // don't also use it for moving the camera. if (!InGame.inGame.ProgramUsesRightMouse) { parent.MouseEdit.DoCamera(parent.Camera); } if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { bool bAllowCameraMovement = true; bAllowCameraMovement = !TouchVirtualController.IsVirtualControllerActedOn(); SwipeGestureRecognizer swipeGesture = TouchGestureManager.Get().SwipeGesture; if (bAllowCameraMovement && swipeGesture.IdentifiedFinger) { #if NETFX_CORE float halfWidth = (float)BokuGame.bokuGame.Window.ClientBounds.Width * 0.5f; float height = (float)BokuGame.bokuGame.Window.ClientBounds.Height; #else float halfWidth = (float)XNAControl.Instance.ClientSize.Width * 0.5f; float height = (float)XNAControl.Instance.ClientSize.Height; #endif //center half of the screen width-wise float minX = halfWidth - (halfWidth * k_TouchExitAreaWidthPercent); float maxX = halfWidth + (halfWidth * k_TouchExitAreaWidthPercent); //bottom 20% height-wise float minY = height - (height * k_TouchExitAreaHeightPercent); Vector2 pos = swipeGesture.InitialPosition; bAllowCameraMovement = !(pos.X >= minX && pos.X <= maxX && pos.Y >= minY); } if (bAllowCameraMovement) { parent.TouchEdit.DoCamera(parent.Camera); parent.TouchEdit.AddPitchYawByDrag(parent.Camera); parent.TouchEdit.ProcessCameraRotation(parent.Camera); } } // Shoulder buttons track camera in/out. // Don't change zoom while in first person mode unless we got there via zooming in. if (!CameraInfo.FirstPersonActive || CameraInfo.FirstPersonViaZoom) { if (Actions.ZoomOut.IsPressed) { parent.Camera.DesiredDistance *= 1.0f + tics * kZoomFactor; } if (Actions.ZoomIn.IsPressed) { parent.Camera.DesiredDistance *= 1.0f - tics * kZoomFactor; } parent.MouseEdit.DoZoom(parent.Camera); parent.TouchEdit.DoZoom(parent.Camera); } } // end of RunSimUpdateObj OrbitAndTrackCamera()
} // end of RunSimUpdateObj MoveCameraEditMode() private void MoveCameraActorMode(bool inputFocus, bool ignoreRotation) { // Start with any first person actor. If none then follow // the first one on the focus list. GameActor actor = CameraInfo.FirstPersonActor; if (actor == null) { actor = CameraInfo.CameraFocusGameActor; } if (inputFocus) { if (!ignoreRotation) { OrbitAndTrackCamera(); } GamePadInput pad = GamePadInput.GetGamePad0(); if (actor != null) { shared.CursorPosition = actor.Movement.Position; // If we're controlling an actor, align the camera with the actor's heading. // The user is still able to use the right stick to orbit around the actor but // as soon as the stick is let go the camera will return to being directly // behind the actor. if (actor.Chassis.HasFacingDirection) { // Normal, non-first person mode. // Use lighter weighting if the user is pushing on the stick. float lerpWeighting = Time.GameTimeFrameSeconds; // Use the square of the spring strength to give a little more resolution at the low end. lerpWeighting *= pad.RightStick.X == 0.0f ? InGame.CameraSpringStrength * InGame.CameraSpringStrength * 10.0f : 0.5f; lerpWeighting = Math.Min(lerpWeighting, 1.0f); float dtheta = actor.Movement.RotationZ - parent.Camera.DesiredRotation; if (dtheta > MathHelper.Pi) { dtheta -= MathHelper.TwoPi; } if (dtheta < -MathHelper.Pi) { dtheta += MathHelper.TwoPi; } parent.Camera.DesiredRotation = parent.Camera.DesiredRotation + dtheta * lerpWeighting; } } } else { // We may not have input focus but we still need to move the // camera. This may be because we in PreGame mode and want // the camera to snap to the right place before the game starts. if (actor != null) { shared.CursorPosition = actor.Movement.Position; // If we're controlling an actor, align the camera with the actor's heading. float secs = Time.WallClockFrameSeconds; float t = Math.Max(1.0f, 10.0f * secs); parent.Camera.DesiredRotation = MyMath.Lerp(parent.Camera.Rotation, actor.Movement.RotationZ, t); parent.Camera.DesiredAt = MyMath.Lerp(parent.Camera.At, actor.Movement.Position, t); } } // Are we close enough for first person mode? if (CameraInfo.CameraFocusGameActor != null) { float closeEnough = Math.Max(parent.Camera.FirstPersonDistance, 1.5f * CameraInfo.CameraFocusGameActor.CollisionRadius); CameraInfo.FirstPersonViaZoom = parent.Camera.Distance < closeEnough; } shared.KeepCameraAboveGround(); // If we're controlling a bot (or in first person mode) raise our target height by // the chassis eye offset. This keeps the camera out of the ground for bots like // the Fastbot which have their origin at the bottom. if (actor != null) { // Try and smooth out the vertical for the camera. // Note that running into the ground will still cause the camera to jump upward. Vector3 curAt = shared.camera.DesiredAt; Vector3 target = shared.CursorPosition + new Vector3(0, 0, actor.Chassis.EyeOffset); // Only lerp in Z. curAt.X = target.X; curAt.Y = target.Y; float dt = InGame.inGame.PreGameActive ? Time.WallClockFrameSeconds : Time.GameTimeFrameSeconds; dt = Math.Min(1.0f, dt * 20.0f); shared.camera.DesiredAt = MyMath.Lerp(curAt, target, dt); } else { shared.camera.DesiredAt = shared.CursorPosition; } } // end of RunSimUpdateObj MoveCameraActorMode()
void Awake() { S = this; }
} // end of RunSimUpdateObj MoveCameraFixedOffsetMode() private void MoveCameraMultiTargetMode(bool inputFocus, bool ignoreRotation) { Vector3 lookAt = shared.camera.At; Vector3 lookFrom = shared.camera.From; // Find centroid of targets. List <GameActor> focusList = CameraInfo.MergedFollowList; Vector3 min = new Vector3(float.MaxValue); Vector3 max = new Vector3(float.MinValue); for (int i = 0; i < focusList.Count; i++) { Vector3 pos = focusList[i].Movement.Position; if (pos.X < min.X) { min.X = pos.X; } if (pos.X > max.X) { max.X = pos.X; } if (pos.Y < min.Y) { min.Y = pos.Y; } if (pos.Y > max.Y) { max.Y = pos.Y; } if (pos.Z < min.Z) { min.Z = pos.Z; } if (pos.Z > max.Z) { max.Z = pos.Z; } } lookAt = (min + max) / 2.0f; // Now find the "long axis" of the collection of targets. This will be used // as a vector orthogonal to the camera's view direction. // Find the axis between the 2 bots that are furthest apart. Vector3 axis = Vector3.UnitX; float dist = 0.0f; for (int i = 0; i < focusList.Count - 1; i++) { for (int j = i + 1; j < focusList.Count; j++) { Vector3 delta = focusList[i].Movement.Position - focusList[j].Movement.Position; delta.Z = 0.0f; // Ignore vertical. float length = delta.Length(); if (length > dist) { dist = length; axis = delta / length; } } } float secs = Time.WallClockFrameSeconds; if (!ignoreRotation) { GamePadInput pad = GamePadInput.GetGamePad0(); // Adjust pitch. float dPitch = GamePadInput.InvertCamY() ? -pad.RightStick.Y : pad.RightStick.Y; parent.Camera.DesiredPitch -= dPitch * Time.WallClockFrameSeconds * kOrbitSpeed; // Shoulder buttons track camera in/out. if (pad.LeftShoulder.IsPressed) { parent.Camera.DesiredDistance *= 1.0f + Time.WallClockFrameSeconds * kZoomFactor; } if (pad.RightShoulder.IsPressed) { parent.Camera.DesiredDistance *= 1.0f - Time.WallClockFrameSeconds * kZoomFactor; } // Now that we've got the axis, figure out the desired camera rotation. float axisRot = (float)Math.Acos(axis.X); if (axis.Y < 0.0f) { axisRot = MathHelper.TwoPi - axisRot; } // Add pi/2 to get the orthogonal vector. float desiredRot = axisRot + MathHelper.PiOver2; // If we have input focus, let the user push the rotation angle around. if (inputFocus) { float dRotation = pad.RightStick.X * kOrbitSpeed; if (GamePadInput.InvertCamX()) { dRotation = -dRotation; } parent.Camera.Rotation += dRotation * secs * 4.0f; } // Now decide if we want to use this angle for the camera or the exact opposite. // To determine this we see if the delta between the angles is more than pi/2. float dTheta = desiredRot - parent.Camera.Rotation; // Force into +- pi range. while (dTheta > MathHelper.Pi) { dTheta -= MathHelper.TwoPi; } while (dTheta < -MathHelper.Pi) { dTheta += MathHelper.TwoPi; } if (Math.Abs(dTheta) > MathHelper.PiOver2) { // Use opposite. if (dTheta > 0.0f) { dTheta -= MathHelper.Pi; } else { dTheta += MathHelper.Pi; } } desiredRot = parent.Camera.Rotation + dTheta; parent.Camera.DesiredRotation = desiredRot; // Based on rotation, calc new lookFrom position. float dz = (float)Math.Sin(-parent.Camera.Pitch); float dxy = (float)Math.Sqrt(1.0f - dz * dz); Vector3 offset = new Vector3(); offset = new Vector3(-dxy * (float)Math.Cos(parent.Camera.Rotation), -dxy * (float)Math.Sin(parent.Camera.Rotation), dz); lookFrom = lookAt + parent.Camera.Distance * offset; // Now adjust camera distance. bool tooClose = false; for (int i = 0; i < focusList.Count; i++) { BoundingSphere s = focusList[i].BoundingSphere; s.Center += focusList[i].Movement.LocalMatrix.Translation; // Increase the radius to provide a little cushion at the edge of the screen. // For user controlled characters this cushion should be greater. s.Radius *= focusList[i].Movement.UserControlled ? 5.0f : 3.0f; if (shared.camera.Frustum.CullTest(s) != Frustum.CullResult.TotallyInside) { tooClose = true; break; } } const float kCameraZoomInSpeed = 0.1f; const float kCameraZoomOutSpeed = 0.4f; if (tooClose) { parent.Camera.DesiredDistance *= 1.0f + kCameraZoomOutSpeed * secs; } else { const float kMinCameraDist = 20.0f; if (parent.Camera.Distance > kMinCameraDist) { parent.Camera.DesiredDistance *= 1.0f - kCameraZoomInSpeed * secs; } } } parent.Camera.DesiredAt = lookAt; InGame.inGame.Cursor3D.Position = lookAt; } // end of RunSimUpdateObj MoveCameraMultiTargetMode()
} // end of PreGameRacingWithDesc c'tor public override void Update() { if (Active) { if (showingDescription) { // Waiting for A to be pressed. if (Actions.Select.WasPressed) { Actions.Select.ClearAllWasPressedState(); showingDescription = false; startTime = Time.WallClockTotalSeconds; HelpOverlay.Pop(); // Don't let current pressed state leak into game. GamePadInput.IgnoreUntilReleased(Buttons.A); } if (GamePadInput.ActiveMode == GamePadInput.InputMode.KeyboardMouse) { // Check if user click on bottom text. if (MouseInput.Left.WasPressed && HelpOverlay.MouseHitBottomText(MouseInput.Position)) { showingDescription = false; startTime = Time.WallClockTotalSeconds; HelpOverlay.Pop(); MouseInput.Left.ClearAllWasPressedState(); } } if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { // Check if user click on bottom text. if (TouchGestureManager.Get().TapGesture.WasTapped() && HelpOverlay.MouseHitBottomText(TouchInput.GetAsPoint(TouchInput.GetOldestTouch().position)) ) { showingDescription = false; startTime = Time.WallClockTotalSeconds; HelpOverlay.Pop(); } } } else { int oldPhase = phase; phase = (int)Math.Ceiling(startTime + duration - Time.WallClockTotalSeconds); if (oldPhase != phase) { if ((phase < cueNames.Length) && (phase >= 0)) { BokuGame.Audio.GetCue(cueNames[phase]).Play(); } } if (Time.WallClockTotalSeconds > startTime + duration) { // We're done. Active = false; } // Check if user click on bottom text. if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch) { // Check if user click on bottom text. if (TouchGestureManager.Get().TapGesture.WasTapped() && HelpOverlay.MouseHitBottomText(TouchInput.GetAsPoint(TouchInput.GetOldestTouch().position)) ) { Active = false; } } else if (MouseInput.Left.WasPressed && HelpOverlay.MouseHitBottomText(MouseInput.Position)) { Active = false; MouseInput.Left.ClearAllWasPressedState(); } } } base.Update(); } // end of PreGameRacingWithDesc Update()