- Main Page
- Classes
- Files

- File List

# C:/Users/Andreas Schiffler/Desktop/SVN/NewGamePhysics/PendulumGame/Screens/PendulumGameplayScreen.cs

    00001 //-----------------------------------------------------------------------------
    00002 // PendulumGameplayScreen.cs
    00003 // (A. Schiffler, 2009)
    00004 //-----------------------------------------------------------------------------
    00005
    00006 namespace PendulumGame
    00007 {
    00008     using System;
    00009     using System.IO;
    00010     using System.Text;
    00011     using System.Threading;
    00012     using Microsoft.Xna.Framework;
    00013     using Microsoft.Xna.Framework.Content;
    00014     using Microsoft.Xna.Framework.Graphics;
    00015     using Microsoft.Xna.Framework.Input;
    00016
    00017     using NewGamePhysics.StateManager;
    00018     using NewGamePhysics.Mathematics;
    00019     using NewGamePhysics.Physics;
    00020     using NewGamePhysics.GraphicalElements;
    00021     using NewGamePhysics.PhysicalElements;
    00022     using NewGamePhysics.Utilities;
    00023     using NewGamePhysics.Networking;
    00024
    00025     using Microsoft.DirectX.DirectSound;
    00026
    00030     class PendulumGameplayScreen : GameScreen
    00031     {
    00032         #region Fields
    00033
    00037         private const double MinimumEnergyForEntropyCollection = 10.0;
    00038
    00042         private ContentManager contentManager;
    00043
    00047         private DirectXAudio audioPlayer;
    00048
    00052         private DoubleRegularPendulum animatedDoubleRegularPendulum;
    00053
    00057         private DoubleSquarePendulum animatedDoubleSquarePendulum;
    00058
    00062         private VectorN[] pendulumOrigins = new VectorN[2];
    00063
    00067         private double[] pendulumScales = new double[2];
    00068
    00072         private DoubleRegularPendulumSimulation audioPendulum1 = null;
    00073
    00077         private DoubleSquarePendulumSimulation audioPendulum2 = null;
    00078
    00082         private int[] audioPendulumSamplesRemaining = new int[2];
    00083
    00087         private DotPlotter[] dotPlotters;
    00088
    00092         private Vector2[] dotPlotterDisplacement;
    00093
    00097         private LaplaceOverlay laplaceOverlay;
    00098
    00102         private BloomOverlay bloomOverlay;
    00103
    00107         private EnergyIndicator[] energyIndicators;
    00108
    00112         private ValueIndicator[] valueIndicators;
    00113
    00117         private ShootingGallery shootingGallery;
    00118
    00122         private AdvancedEntropyCollector[] entropyCollectors;
    00123
    00127         private RotationalActionIndicator[] actionIndicators;
    00128
    00132         private Vector2 screenOrigin;
    00133
    00137         private double screenScale;
    00138
    00142         private bool triggerAudio1 = false;
    00143
    00147         private bool triggerAudio2 = false;
    00148
    00149         #endregion
    00150
    00151         #region Initialization
    00152
    00156         public PendulumGameplayScreen()
    00157         {
    00158             TransitionOnTime = TimeSpan.FromSeconds(1.0);
    00159             TransitionOffTime = TimeSpan.FromSeconds(1.0);
    00160
    00161             // Create playback streamer
    00162             this.audioPlayer = new DirectXAudio((Device)null, 22050, (short)16, (short)2);
    00163         }
    00164
    00168         public override void LoadContent()
    00169         {
    00170             if (contentManager == null)
    00171             {
    00172                 contentManager = new ContentManager(ScreenManager.Game.Services, "Content");
    00173             }
    00174
    00175             // Local viewport
    00176             Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
    00177
    00178             // Initialize the game players
    00179             for (int i = 0; i < PendulumGameState.NumPlayers; i++)
    00180             {
    00181                 PendulumGame.State.Players[i] = new GamePlayer();
    00182                 PendulumGame.State.Players[i].ActionMarker = DoublePendulumHinges.Hinge1;
    00183             }
    00184
    00185             // Set gravity
    00186             GravityCalculator gravityCalculator = new GravityCalculator(PendulumGame.State.CurrentCelestialObject);
    00187             PendulumGame.State.CurrentGravity = gravityCalculator.Value;
    00188
    00189             // Create physical element(s)
    00190             double size = 1.0;
    00191             double size2 = 1.0;
    00192             double mass = 1.0;
    00193             double mass2 = 1.0;
    00194
    00195             this.screenOrigin =
    00196                 new Vector2((float)(viewport.Width / 2.0), (float)(viewport.Height / 2.0));
    00197             this.screenScale = 140.0;
    00198
    00199             // Pendulums
    00200             this.animatedDoubleRegularPendulum = new DoubleRegularPendulum(
    00201                 ScreenManager,
    00202                 new Vector2(-2.0f, 0.0f),
    00203                 size,
    00204                 mass,
    00205                 size2,
    00206                 mass2,
    00207                 PendulumGame.State.CurrentGravity,
    00208                 PendulumGame.State.CurrentRotationalFrictionType,
    00209                 screenOrigin,
    00210                 screenScale);
    00211
    00212             this.animatedDoubleSquarePendulum = new DoubleSquarePendulum(
    00213                 ScreenManager,
    00214                 new Vector2(2.0f, 0.0f),
    00215                 size * (82.8427 / 100.0),
    00216                 mass,
    00217                 PendulumGame.State.CurrentGravity,
    00218                 PendulumGame.State.CurrentRotationalFrictionType,
    00219                 screenOrigin,
    00220                 screenScale);
    00221
    00222             // Plotters
    00223             dotPlotters = new DotPlotter[2];
    00224             dotPlotters[0] = new DotPlotter(2 * 1024);
    00225             dotPlotters[1] = new DotPlotter(2 * 1024);
    00226             dotPlotterDisplacement = new Vector2[2];
    00227             dotPlotterDisplacement[0] =
    00228                 new Vector2(0.5f * PendulumGame.State.Scale.X, 0.0f);
    00229             dotPlotterDisplacement[1] =
    00230                 new Vector2(-0.5f * PendulumGame.State.Scale.X, 0.0f);
    00231
    00232             // Energy Indicators
    00233             energyIndicators = new EnergyIndicator[2];
    00234             energyIndicators[0] = new EnergyIndicator(ScreenManager, "E");
    00235             energyIndicators[1] = new EnergyIndicator(ScreenManager, "E");
    00236
    00237             // Indicators
    00238             valueIndicators = new ValueIndicator[8];
    00239             valueIndicators[0] = new ValueIndicator(ScreenManager, "A Angle Inner", "{0,20:####.##} deg", -180, 180);
    00240             valueIndicators[1] = new ValueIndicator(ScreenManager, "B Angle Inner", "{0,20:####.##} deg", -180, 180);
    00241             valueIndicators[2] = new ValueIndicator(ScreenManager, "A Angle Outer", "{0,20:####.##} deg", -180, 180);
    00242             valueIndicators[3] = new ValueIndicator(ScreenManager, "B Angle Outer", "{0,20:####.##} deg", -180, 180);
    00243             valueIndicators[4] = new ValueIndicator(ScreenManager, "A Speed Inner", "{0,20:####.##} 1/s", -20, 20);
    00244             valueIndicators[5] = new ValueIndicator(ScreenManager, "B Speed Inner", "{0,20:####.##} 1/s", -20, 20);
    00245             valueIndicators[6] = new ValueIndicator(ScreenManager, "A Speed Outer", "{0,20:####.##} 1/s", -20, 20);
    00246             valueIndicators[7] = new ValueIndicator(ScreenManager, "B Speed Outer", "{0,20:####.##} 1/s", -20, 20);
    00247
    00248             // Place all indicators at the bottom in the same spot
    00249             float yPos;
    00250             yPos = viewport.Height - EnergyIndicator.Height - 10.0f;
    00251             energyIndicators[0].SetPosition(new Vector2(5.0f, yPos));
    00252             energyIndicators[1].SetPosition(new Vector2(viewport.Width - EnergyIndicator.Width - 5.0f, yPos));
    00253             yPos = viewport.Height - ValueIndicator.Height - 10.0f + 1.0f;
    00254             for (int i = 0; i < 4; i++)
    00255             {
    00256                 valueIndicators[2 * i].SetPosition(new Vector2(25.0f, yPos));
    00257                 valueIndicators[2 * i + 1].SetPosition(new Vector2(viewport.Width - ValueIndicator.Width - 25.0f, yPos));
    00258             }
    00259
    00260             // Create shooting gallery across screen
    00261             float simulationHeight = 0.3f;
    00262             float simulationWidth = 8.0f;
    00263             this.shootingGallery =
    00264                 new ShootingGallery(
    00265                     ScreenManager,
    00266                     new Vector2(-simulationWidth / 2.0f, -2.0f),
    00267                     simulationWidth,
    00268                     simulationHeight,
    00269                     screenOrigin,
    00270                     screenScale);
    00271             this.shootingGallery.TargetConveyerSpeed = 0.005;
    00272             CelestialBody celestialBody =
    00273                 new CelestialBody(PendulumGame.State.CurrentCelestialObject);
    00274             string[] targetTypes = new string[12];
    00275             string[] targetChoices = Enum.GetNames(typeof(ShootingGalleryTargetType));
    00276             for (int i = 0; i < targetTypes.Length; i++)
    00277             {
    00278                 int randomChoice = PendulumGame.State.PhysicalRandomNumberGenerator.Next(
    00279                         0,
    00280                         targetChoices.Length - 1);
    00281                 targetTypes[i] = targetChoices[randomChoice];
    00282             }
    00283
    00284             shootingGallery.Reset(
    00285                 targetTypes,
    00286                 PendulumGame.State.CurrentGravity,
    00287                 celestialBody.GetAtmosphericDensity());
    00288
    00289             PendulumGame.State.PhysicalRandomNumberGenerator.Next(0, 2);
    00290
    00291             // Action indicators
    00292             actionIndicators = new RotationalActionIndicator[2];
    00293             actionIndicators[0] = new RotationalActionIndicator(ScreenManager);
    00294             actionIndicators[1] = new RotationalActionIndicator(ScreenManager);
    00295
    00296             // Random number generators
    00297             entropyCollectors = new AdvancedEntropyCollector[2];
    00298             entropyCollectors[0] = new AdvancedEntropyCollector();
    00299             entropyCollectors[1] = new AdvancedEntropyCollector();
    00300
    00301             // Reset bit count
    00302             PendulumGame.State.SubmittedEntropyBits = 0;
    00303
    00304             // Pick random info link on 'randomness' and send it
    00305             Program.Game.SendRandomInfoLink("Randomness");
    00306
    00307             // Load laplace effect
    00308             this.laplaceOverlay = new LaplaceOverlay(this.ScreenManager);
    00309             this.laplaceOverlay.LoadContent();
    00310
    00311             // Load bloom effect
    00312             this.bloomOverlay = new BloomOverlay(this.ScreenManager);
    00313             this.bloomOverlay.LoadContent();
    00314
    00315             // Reset game time
    00316             ScreenManager.Game.ResetElapsedTime();
    00317
    00318             // Start audio playback
    00319             this.audioPlayer.Play(new PullAudioCallback(PendulumFiller));
    00320         }
    00321
    00325         public override void UnloadContent()
    00326         {
    00327             // Stop playback
    00328             this.audioPlayer.Stop();
    00329
    00330             // Unload laplace effect
    00331             this.laplaceOverlay.UnloadContent();
    00332
    00333             // Unload bloom effect
    00334             this.bloomOverlay.UnloadContent();
    00335
    00336             // Pick random info link on 'randomness' and send it
    00337             Program.Game.SendRandomInfoLink("Randomness");
    00338
    00339             // Maybe send entropy to service
    00340             CheckAndSubmitEntropy(0, 1);
    00341             CheckAndSubmitEntropy(1, 1);
    00342
    00343             // Unload all content
    00344             contentManager.Unload();
    00345
    00346             // Unload base
    00347             base.UnloadContent();
    00348         }
    00349
    00350         #endregion
    00351
    00352         #region Update and Draw
    00353
    00354
    00360         public override void Update(GameTime gameTime, bool otherScreenHasFocus,
    00361                                                        bool coveredByOtherScreen)
    00362         {
    00363             base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
    00364
    00365             if (IsActive)
    00366             {
    00367                 Vector2[] pendulumPoints;
    00368                 double rotation;
    00369
    00370                 // ----------- Update simulations ---------
    00371
    00372                 Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
    00373
    00374                 // Move plotter points
    00375                 dotPlotters[0].MoveDots(dotPlotterDisplacement[0]);
    00376                 dotPlotters[1].MoveDots(dotPlotterDisplacement[1]);
    00377
    00378                 // Player A: Animate double pendulum
    00379
    00380                 // Maybe drive pendulum
    00381                 rotation = animatedDoubleRegularPendulum.Pendulum.Drive(
    00382                         PendulumGame.State.Players[0].ActionMarker,
    00383                         PendulumGame.State.Players[0].ActionIntensity);
    00384
    00385                 // Update action indicator
    00386                 actionIndicators[0].Animate(rotation);
    00387
    00388                 // Update pendulum animation
    00389                 animatedDoubleRegularPendulum.Pendulum.Animate();
    00390
    00391                 // Get pendulum locations in screen coordinates
    00392                 pendulumPoints =
    00393                     animatedDoubleRegularPendulum.Pendulum.GetPosition(this.screenOrigin, this.screenScale);
    00394
    00395                 // Updated Plotter
    00396                 dotPlotters[0].AddDot(pendulumPoints[2], new Color(255, 0, 0), 0);
    00397
    00398                 // Update action indicator position
    00399                 switch (PendulumGame.State.Players[0].ActionMarker)
    00400                 {
    00401                     case DoublePendulumHinges.Hinge1:
    00402                         actionIndicators[0].SetPosition(pendulumPoints[0]);
    00403                         break;
    00404                     case DoublePendulumHinges.Hinge2:
    00405                         actionIndicators[0].SetPosition(pendulumPoints[1]);
    00406                         break;
    00407                 }
    00408
    00409                 // Get pendulum locations in simulation coordinates
    00410                 pendulumPoints =
    00411                     animatedDoubleRegularPendulum.Pendulum.GetPosition();
    00412
    00413                 // Check if Player A hits targets
    00414                 int hitsA = shootingGallery.ShootAtTargets(pendulumPoints[2], 0.01);
    00415                 if (hitsA > 0)
    00416                 {
    00417                     PendulumGame.State.Players[0].Points += hitsA;
    00418
    00419                     // Pick random info link on 'pendulums' and send it
    00420                     Program.Game.SendRandomInfoLink("DoublePendulum");
    00421                 }
    00422
    00423                 // Player B: Animate double square pendulum
    00424
    00425                 // Maybe drive pendulum
    00426                 rotation = animatedDoubleSquarePendulum.Pendulum.Drive(
    00427                         PendulumGame.State.Players[1].ActionMarker,
    00428                         PendulumGame.State.Players[1].ActionIntensity);
    00429
    00430                 // Update action indicator
    00431                 actionIndicators[1].Animate(rotation);
    00432
    00433                 // Update pendulum animation
    00434                 animatedDoubleSquarePendulum.Pendulum.Animate();
    00435
    00436                 // Get pendulum locations in screen coordinates
    00437                 pendulumPoints =
    00438                     animatedDoubleSquarePendulum.Pendulum.GetPosition(this.screenOrigin, this.screenScale);
    00439
    00440                 // Updated Plotter
    00441                 dotPlotters[1].AddDot(pendulumPoints[6], new Color(0, 0, 192), 0);
    00442
    00443                 // Update action indicator position
    00444                 switch (PendulumGame.State.Players[1].ActionMarker)
    00445                 {
    00446                     case DoublePendulumHinges.Hinge1:
    00447                         actionIndicators[1].SetPosition(pendulumPoints[0]);
    00448                         break;
    00449                     case DoublePendulumHinges.Hinge2:
    00450                         actionIndicators[1].SetPosition(pendulumPoints[4]);
    00451                         break;
    00452                 }
    00453
    00454                 // Get pendulum locations in simulation coordinates
    00455                 pendulumPoints =
    00456                     animatedDoubleSquarePendulum.Pendulum.GetPosition();
    00457
    00458                 // Check if Player B hits targets
    00459                 int hitsB = shootingGallery.ShootAtTargets(pendulumPoints[6], 0.01);
    00460                 if (hitsB > 0)
    00461                 {
    00462                     PendulumGame.State.Players[1].Points += hitsB;
    00463
    00464                     // Pick random info link on 'pendulums' and send it
    00465                     Program.Game.SendRandomInfoLink("DoublePendulum");
    00466                 }
    00467
    00468                 // Animate shooting gallery
    00469                 shootingGallery.Update(gameTime);
    00470
    00471                 // Check for game over
    00472                 if (shootingGallery.NumActiveTargets == 0)
    00473                 {
    00474                     // Maybe send entropy to service
    00475                     CheckAndSubmitEntropy(0, 1);
    00476                     CheckAndSubmitEntropy(1, 1);
    00477
    00478                     ScreenManager.AddScreen(
    00479                         new PendulumGameOverScreen(), null);
    00480                 }
    00481
    00482                 // Update all indicator values
    00483                 double e1 = animatedDoubleRegularPendulum.Pendulum.GetEnergy();
    00484                 energyIndicators[0].SetValue(e1);
    00485
    00486                 double e2 = animatedDoubleSquarePendulum.Pendulum.GetEnergy();
    00487                 energyIndicators[1].SetValue(e2);
    00488
    00489                 double[] a1 = animatedDoubleRegularPendulum.Pendulum.GetAngle();
    00490                 valueIndicators[0].SetValue(ToDegree(a1[0]));
    00491                 valueIndicators[2].SetValue(ToDegree(a1[1]));
    00492
    00493                 double[] a2 = animatedDoubleSquarePendulum.Pendulum.GetAngle();
    00494                 valueIndicators[1].SetValue(ToDegree(a2[0]));
    00495                 valueIndicators[3].SetValue(ToDegree(a2[1]));
    00496
    00497                 double[] v1 = animatedDoubleRegularPendulum.Pendulum.GetVelocity();
    00498                 valueIndicators[4].SetValue(v1[0]);
    00499                 valueIndicators[6].SetValue(v1[1]);
    00500
    00501                 double[] v2 = animatedDoubleSquarePendulum.Pendulum.GetVelocity();
    00502                 valueIndicators[5].SetValue(v2[0]);
    00503                 valueIndicators[7].SetValue(v2[1]);
    00504
    00505                 // Pick up randomness
    00506
    00507                 // Enough energy in the pendulum of player A?
    00508                 if (e1 > MinimumEnergyForEntropyCollection)
    00509                 {
    00510                     if (PendulumGame.State.Players[1].ActionIntensityChanged())
    00511                     {
    00512                         CollectEntropyFromPlayerA();
    00513                     }
    00514                 }
    00515
    00516                 // Enough energy in the pendulum of player B
    00517                 if (e2 > MinimumEnergyForEntropyCollection)
    00518                 {
    00519                     if (PendulumGame.State.Players[0].ActionIntensityChanged())
    00520                     {
    00521                         CollectEntropyFromPlayerB();
    00522                     }
    00523                 }
    00524
    00525                 // Active pendulum 1 sound
    00526                 if ((this.audioPendulum1 == null) &&
    00527                     (this.audioPendulumSamplesRemaining[0] == 0))
    00528                 {
    00529                     if ((!PendulumGame.State.RealtimeAudioOnDemand) || (triggerAudio1))
    00530                     {
    00531                         // Reset trigger
    00532                         triggerAudio1 = false;
    00533
    00534                         // Current state
    00535                         double[] angles = this.animatedDoubleRegularPendulum.Pendulum.GetAngle();
    00536                         double[] velocities = this.animatedDoubleRegularPendulum.Pendulum.GetVelocity();
    00537
    00538                         float theta1 = MathHelper.WrapAngle((float)angles[0]);
    00539                         float theta2 = MathHelper.WrapAngle((float)angles[1]);
    00540
    00541                         // New Pendulum
    00542                         DoubleRegularPendulumSimulation audioPendulum =
    00543                             new DoubleRegularPendulumSimulation(
    00544                                 new Vector2(),
    00545                                 0.1, 1.0, 0.1, 1.0,
    00546                                 PendulumGame.State.CurrentGravity,
    00547                                 PendulumGame.State.CurrentRotationalFrictionType);
    00548                         audioPendulum.SetInitialConditions(
    00549                                 (double)theta1, velocities[0], (double)theta2, velocities[1]);
    00550
    00551                         // Activate
    00552                         this.audioPendulumSamplesRemaining[0] = 38000;
    00553                         this.audioPendulum1 = audioPendulum;
    00554                     }
    00555                 }
    00556                 else
    00557                 {
    00558                     if (this.audioPendulumSamplesRemaining[0] == 0)
    00559                     {
    00560                         this.audioPendulum1 = null;
    00561                     }
    00562                 }
    00563
    00564                 // Active pendulum 2 sound
    00565                 if ((this.audioPendulum2 == null) &&
    00566                     (this.audioPendulumSamplesRemaining[1] == 0))
    00567                 {
    00568                     if ((!PendulumGame.State.RealtimeAudioOnDemand) || (triggerAudio2))
    00569                     {
    00570                         // Reset trigger
    00571                         triggerAudio2 = false;
    00572
    00573                         // Current state
    00574                         double[] angles = this.animatedDoubleSquarePendulum.Pendulum.GetAngle();
    00575                         double[] velocities = this.animatedDoubleSquarePendulum.Pendulum.GetVelocity();
    00576
    00577                         float theta1 = MathHelper.WrapAngle((float)angles[0]);
    00578                         float theta2 = MathHelper.WrapAngle((float)angles[1]);
    00579
    00580                         // New Pendulum
    00581                         DoubleSquarePendulumSimulation audioPendulum =
    00582                             new DoubleSquarePendulumSimulation(
    00583                                 new Vector2(),
    00584                                 0.1, 1.0,
    00585                                 PendulumGame.State.CurrentGravity,
    00586                                 PendulumGame.State.CurrentRotationalFrictionType);
    00587                         audioPendulum.SetInitialConditions(
    00588                                 (double)theta1, velocities[0], (double)theta2, velocities[1]);
    00589
    00590                         // Activate
    00591                         this.audioPendulumSamplesRemaining[1] = 44000;
    00592                         this.audioPendulum2 = audioPendulum;
    00593                     }
    00594                 }
    00595                 else
    00596                 {
    00597                     if (this.audioPendulumSamplesRemaining[1] == 0)
    00598                     {
    00599                         this.audioPendulum2 = null;
    00600                     }
    00601                 }
    00602             }
    00603         }
    00604
    00609         public override void HandleInput(InputState input)
    00610         {
    00611             if (input == null)
    00612             {
    00613                 throw new ArgumentNullException("input");
    00614             }
    00615
    00616             PlayerIndex playerIndex;
    00617
    00618             if (input.IsInputCancel(null) || input.IsDisconnected(null))
    00619             {
    00620                 ScreenManager.AddScreen(new PendulumPauseMenuScreen(), null);
    00621             }
    00622             else
    00623             {
    00624                 // Keep track of action intensity
    00625                 for (int i = 0; i < PendulumGameState.NumPlayers; i++)
    00626                 {
    00627                     PendulumGame.State.Players[i].TrackActionIntensity();
    00628                 }
    00629
    00630                 // Player 1 - top actuator
    00631                 if (input.IsNewKeyPress(Keys.Q, null, out playerIndex) ||
    00632                     input.IsNewButtonPress(Buttons.B, PlayerIndex.One, out playerIndex))
    00633                 {
    00634                     PendulumGame.State.Players[0].ActionMarker = DoublePendulumHinges.Hinge1;
    00635                 }
    00636
    00637                 // Player 1 - bottom actuator
    00638                 if (input.IsNewKeyPress(Keys.A, null, out playerIndex) ||
    00639                     input.IsNewButtonPress(Buttons.A, PlayerIndex.One, out playerIndex))
    00640                 {
    00641                     PendulumGame.State.Players[0].ActionMarker = DoublePendulumHinges.Hinge2;
    00642                 }
    00643
    00644                 // Player 2 - top actuator
    00645                 if (input.IsNewKeyPress(Keys.Up, null, out playerIndex) ||
    00646                     input.IsNewButtonPress(Buttons.B, PlayerIndex.Two, out playerIndex) ||
    00647                     (PendulumGame.State.UseOnlyOneGamepad && input.IsNewButtonPress(Buttons.Y, PlayerIndex.One, out playerIndex)))
    00648                 {
    00649                     PendulumGame.State.Players[1].ActionMarker = DoublePendulumHinges.Hinge1;
    00650                 }
    00651
    00652                 // Player 2 - bottom actuator
    00653                 if (input.IsNewKeyPress(Keys.Down, null, out playerIndex) ||
    00654                     input.IsNewButtonPress(Buttons.A, PlayerIndex.Two, out playerIndex) ||
    00655                     (PendulumGame.State.UseOnlyOneGamepad && input.IsNewButtonPress(Buttons.X, PlayerIndex.One, out playerIndex)))
    00656                 {
    00657                     PendulumGame.State.Players[1].ActionMarker = DoublePendulumHinges.Hinge2;
    00658                 }
    00659
    00660                 // Player 1 - swing left or right
    00661                 if (input.IsKeyDown(Keys.Z, null, out playerIndex))
    00662                 {
    00663                     PendulumGame.State.Players[0].ActionIntensity = -1.0;
    00664                 }
    00665                 else if (input.IsKeyDown(Keys.X, null, out playerIndex))
    00666                 {
    00667                     PendulumGame.State.Players[0].ActionIntensity = 1.0;
    00668                 }
    00669                 else
    00670                 {
    00671                     PendulumGame.State.Players[0].ActionIntensity =
    00672                         input.CurrentGamePadStates[0].ThumbSticks.Left.X;
    00673                 }
    00674
    00675                 // Player 2 - swing left or right
    00676                 if (input.IsKeyDown(Keys.Left, null, out playerIndex))
    00677                 {
    00678                     PendulumGame.State.Players[1].ActionIntensity = -1.0;
    00679                 }
    00680                 else if (input.IsKeyDown(Keys.Right, null, out playerIndex))
    00681                 {
    00682                     PendulumGame.State.Players[1].ActionIntensity = 1.0;
    00683                 }
    00684                 else
    00685                 {
    00686
    00687                     // Player 2 - swing with gamepad
    00688                     if (PendulumGame.State.UseOnlyOneGamepad)
    00689                     {
    00690                         PendulumGame.State.Players[1].ActionIntensity =
    00691                             input.CurrentGamePadStates[0].ThumbSticks.Right.X;
    00692                     }
    00693                     else
    00694                     {
    00695                         PendulumGame.State.Players[1].ActionIntensity =
    00696                             input.CurrentGamePadStates[1].ThumbSticks.Left.X;
    00697                     }
    00698                 }
    00699
    00700                 // Keep track of action intensity
    00701                 for (int i = 0; i < PendulumGameState.NumPlayers; i++)
    00702                 {
    00703                     PendulumGame.State.Players[i].TrackActionIntensity();
    00704                 }
    00705
    00706                 // Player 1 - display switch
    00707                 if (input.IsNewKeyPress(Keys.LeftShift, null, out playerIndex) ||
    00708                     input.IsNewButtonPress(Buttons.LeftTrigger, PlayerIndex.One, out playerIndex))
    00709                 {
    00710                     PendulumGame.State.Players[0].SelectedIndicator++;
    00711                     PendulumGame.State.Players[0].SelectedIndicator %= (valueIndicators.Length / 2);
    00712                     triggerAudio1 = true;
    00713                 }
    00714                 else if (input.IsNewButtonPress(Buttons.RightTrigger, PlayerIndex.One, out playerIndex))
    00715                 {
    00716                     PendulumGame.State.Players[0].SelectedIndicator--;
    00717                     if (PendulumGame.State.Players[0].SelectedIndicator < 0)
    00718                     {
    00719                         PendulumGame.State.Players[0].SelectedIndicator += (valueIndicators.Length / 2);
    00720                     }
    00721                 }
    00722
    00723                 // Player 2 - display switch audio trigger
    00724                 if (input.IsNewKeyPress(Keys.RightShift, null, out playerIndex) ||
    00725                     input.IsNewButtonPress(Buttons.LeftTrigger, PlayerIndex.Two, out playerIndex) ||
    00726                     (PendulumGame.State.UseOnlyOneGamepad &&
    00727                      input.IsNewButtonPress(Buttons.RightTrigger, PlayerIndex.One, out playerIndex)))
    00728                 {
    00729                     PendulumGame.State.Players[1].SelectedIndicator++;
    00730                     PendulumGame.State.Players[1].SelectedIndicator %= (valueIndicators.Length / 2);
    00731                     triggerAudio2 = true;
    00732                 }
    00733                 else if (input.IsNewButtonPress(Buttons.RightTrigger, PlayerIndex.Two, out playerIndex))
    00734                 {
    00735                     PendulumGame.State.Players[1].SelectedIndicator--;
    00736                     if (PendulumGame.State.Players[1].SelectedIndicator < 0)
    00737                     {
    00738                         PendulumGame.State.Players[1].SelectedIndicator += (valueIndicators.Length / 2);
    00739                     }
    00740                 }
    00741
    00742                 // Early game-over
    00743                 if (input.IsNewKeyPress(Keys.G, null, out playerIndex))
    00744                 {
    00745                     ScreenManager.AddScreen(
    00746                         new PendulumGameOverScreen(), null);
    00747                 }
    00748             }
    00749         }
    00750
    00754         public override void Draw(GameTime gameTime)
    00755         {
    00756             // This game has a blue background. Why? Because!
    00757             ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
    00758                                                Color.Black, 0, 0);
    00759
    00760             SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
    00761             PrimitiveBatch primitiveBatch = ScreenManager.PrimitiveBatch;
    00762             Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
    00763
    00764             // Draw physical elements
    00765             // Plotter
    00766             dotPlotters[0].Draw(gameTime, primitiveBatch);
    00767             dotPlotters[1].Draw(gameTime, primitiveBatch);
    00768
    00769             // Bloom dot plotters using shaders
    00770             if (!PendulumGame.State.DisablePixelShaderEffects)
    00771             {
    00772                 this.bloomOverlay.Draw(gameTime);
    00773             }
    00774
    00775             // Laplace-render the targets using shaders
    00776             if ((!PendulumGame.State.DisablePixelShaderEffects) &&
    00777                 (this.shootingGallery.NumActiveTargets > 0))
    00778             {
    00779                 shootingGallery.Draw(gameTime);
    00780                 this.laplaceOverlay.Draw(gameTime);
    00781             }
    00782
    00783             // Draw the two pendulums
    00784             animatedDoubleRegularPendulum.Draw(
    00785                 gameTime);
    00786             animatedDoubleSquarePendulum.Draw(
    00787                 gameTime);
    00788
    00789             // Draw action markers
    00790             actionIndicators[0].Draw(gameTime);
    00791             actionIndicators[1].Draw(gameTime);
    00792
    00793             // Draw targets again
    00794             shootingGallery.Draw(gameTime);
    00795
    00796             // Indicators for both players
    00797             energyIndicators[0].Draw(gameTime);
    00798             energyIndicators[1].Draw(gameTime);
    00799             valueIndicators[PendulumGame.State.Players[0].SelectedIndicator * 2].Draw(gameTime);
    00800             valueIndicators[PendulumGame.State.Players[1].SelectedIndicator * 2 + 1].Draw(gameTime);
    00801
    00802             // Separator
    00803             primitiveBatch.Begin(PrimitiveType.LineList);
    00804             primitiveBatch.AddVertex(new Vector2(viewport.Width * 0.5f, viewport.Height - 50.0f), Color.White);
    00805             primitiveBatch.AddVertex(new Vector2(viewport.Width * 0.5f, viewport.Height - 10.0f), Color.White);
    00806             primitiveBatch.End();
    00807
    00808             // Draw entropy state
    00809             DrawEntropyStatus(spriteBatch);
    00810
    00811             // Draw player score
    00812             DrawPlayers(spriteBatch);
    00813
    00814             // If the game is transitioning on or off, fade it out to black.
    00815             if (TransitionPosition > 0)
    00816             {
    00817                 ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);
    00818             }
    00819         }
    00820
    00821         #endregion
    00822
    00826         private void CollectEntropyFromPlayerA()
    00827         {
    00828             entropyCollectors[1].AddValue(
    00829                 animatedDoubleRegularPendulum.Pendulum.GetAngle(PendulumGame.State.Players[1].ActionMarker));
    00830             dotPlotters[0].SetTypeAtHead(1);
    00831         }
    00832
    00836         private void CollectEntropyFromPlayerB()
    00837         {
    00838             entropyCollectors[0].AddValue(
    00839                 animatedDoubleSquarePendulum.Pendulum.GetAngle(PendulumGame.State.Players[0].ActionMarker));
    00840             dotPlotters[1].SetTypeAtHead(1);
    00841         }
    00842
    00851         private void CheckAndSubmitEntropy(int playerIndex, int checkLimit)
    00852         {
    00853             // Get bits
    00854             string entropy = entropyCollectors[playerIndex].ToString();
    00855
    00856             // Maybe submit
    00857             if (entropy.Length >= checkLimit)
    00858             {
    00859                 PendulumGame.State.SubmittedEntropyBits += entropy.Length;
    00860                 Program.Game.SubmitEntropyBits(entropy);
    00861                 entropyCollectors[playerIndex].Reset();
    00862             }
    00863         }
    00864
    00869         private void DrawEntropyStatus(SpriteBatch spriteBatch)
    00870         {
    00871             // Get counts
    00872             int countA = entropyCollectors[0].ValuePoolSize;
    00873             int countB = entropyCollectors[1].ValuePoolSize;
    00874
    00875             SpriteFont font = ScreenManager.Fonts["small"];
    00876             Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
    00877             Color color = Color.White;
    00878             Vector2 origin = new Vector2(0, 0);
    00879             Vector2 position = new Vector2(viewport.Width * 0.28f, viewport.Height - font.LineSpacing - 10.0f);
    00880             string message = "A Collected: " + countA.ToString();
    00881             spriteBatch.Begin();
    00882             spriteBatch.DrawString(
    00883                 font,
    00884                 message,
    00885                 position,
    00886                 color,
    00887                 0,
    00888                 origin,
    00889                 1.0f,
    00890                 SpriteEffects.None,
    00891                 0);
    00892             position = new Vector2(viewport.Width * 0.52f, viewport.Height - font.LineSpacing - 10.0f);
    00893             message = "B Collected: " + countB.ToString();
    00894             spriteBatch.DrawString(
    00895                 font,
    00896                 message,
    00897                 position,
    00898                 color,
    00899                 0,
    00900                 origin,
    00901                 1.0f,
    00902                 SpriteEffects.None,
    00903                 0);
    00904             spriteBatch.End();
    00905         }
    00906
    00911         private void DrawPlayers(SpriteBatch spriteBatch)
    00912         {
    00913             SpriteFont font = ScreenManager.Fonts["small"];
    00914             Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
    00915             Color color = Color.White;
    00916             Vector2 origin = new Vector2(0, 0);
    00917             Vector2 position = new Vector2(viewport.Width * 0.28f, viewport.Height - 2 * font.LineSpacing - 20.0f);
    00918             string message = "Player A: " + PendulumGame.State.Players[0].Points + " points";
    00919             spriteBatch.Begin();
    00920             spriteBatch.DrawString(
    00921                 font,
    00922                 message,
    00923                 position,
    00924                 color,
    00925                 0,
    00926                 origin,
    00927                 1.0f,
    00928                 SpriteEffects.None,
    00929                 0);
    00930             position = new Vector2(viewport.Width * 0.52f, viewport.Height - 2 * font.LineSpacing - 20.0f);
    00931             message = "Player B: " + PendulumGame.State.Players[1].Points + " points";
    00932             spriteBatch.DrawString(
    00933                 font,
    00934                 message,
    00935                 position,
    00936                 color,
    00937                 0,
    00938                 origin,
    00939                 1.0f,
    00940                 SpriteEffects.None,
    00941                 0);
    00942             spriteBatch.End();
    00943         }
    00944
    00950         private double ToDegree(double value)
    00951         {
    00952             value = value * 180.0 / Math.PI;
    00953             if (value < 0.0)
    00954             {
    00955                 while (value < -180.0)
    00956                 {
    00957                     value += 360.0;
    00958                 }
    00959             }
    00960             else
    00961             {
    00962                 while (value > 180.0)
    00963                 {
    00964                     value -= 360.0;
    00965                 }
    00966             }
    00967
    00968             return value;
    00969         }
    00970
    00976         private void PendulumFiller(IntPtr dest, int size)
    00977         {
    00978             // maximum wave amplitude
    00979             const float maxAmplitude = 0.90f;
    00980
    00981             // Calculate number fo 16bit samples
    00982             int samples = size / 2;
    00983
    00984             // Create local buffer
    00985             short[] buffer = new short[samples];
    00986
    00987             // Maybe mix in audio pendulum 1 values into left channel
    00988             if (this.audioPendulum1 != null)
    00989             {
    00990                 int samplePos = 0; // offset for left channel
    00991                 short sampleValue = 0;
    00992                 double[] angles;
    00993                 double[] velocities;
    00994                 float theta;
    00995                 float omega;
    00996                 float fvalue = 0.0f;
    00997                 while ((this.audioPendulumSamplesRemaining[0] > 0) && (samplePos < samples))
    00998                 {
    00999                     // Update audio pendulum
    01000                     this.audioPendulum1.Animate();
    01001
    01002                     // Get values depending on the value indicator which was selected
    01003                     switch (PendulumGame.State.Players[0].SelectedIndicator)
    01004                     {
    01005                         case 0:
    01006                             angles = audioPendulum1.GetAngle();
    01007                             theta = MathHelper.WrapAngle((float)angles[0]);
    01008                             fvalue = theta / (float)Math.PI * maxAmplitude * (float)(short.MaxValue);
    01009                             break;
    01010                         case 1:
    01011                             angles = audioPendulum1.GetAngle();
    01012                             theta = MathHelper.WrapAngle((float)angles[1]);
    01013                             fvalue = theta / (float)Math.PI * maxAmplitude * (float)(short.MaxValue);
    01014                             break;
    01015                         case 2:
    01016                             velocities = audioPendulum1.GetVelocity();
    01017                             omega = (float)velocities[0];
    01018                             fvalue = (float)omega * 0.1f;
    01019                             if (fvalue < -maxAmplitude)
    01020                             {
    01021                                 fvalue = -maxAmplitude;
    01022                             }
    01023                             else if (fvalue > maxAmplitude)
    01024                             {
    01025                                 fvalue = maxAmplitude;
    01026                             }
    01027
    01028                             fvalue *= (float)(short.MaxValue);
    01029                             break;
    01030                         case 3:
    01031                             velocities = audioPendulum1.GetVelocity();
    01032                             omega = (float)velocities[1];
    01033                             fvalue = (float)omega * 0.1f;
    01034                             if (fvalue < -maxAmplitude)
    01035                             {
    01036                                 fvalue = -maxAmplitude;
    01037                             }
    01038                             else if (fvalue > maxAmplitude)
    01039                             {
    01040                                 fvalue = maxAmplitude;
    01041                             }
    01042
    01043                             fvalue *= (float)(short.MaxValue);
    01044                             break;
    01045                         default:
    01046                             fvalue = 0.0f;
    01047                             break;
    01048                     }
    01049
    01050                     sampleValue = Convert.ToInt16(fvalue);
    01051                     buffer[samplePos] = sampleValue;
    01052                     samplePos += 2;
    01053
    01054                     this.audioPendulumSamplesRemaining[0]--;
    01055                 }
    01056             }
    01057
    01058             // Maybe mix in audio pendulum 2 values into right channel
    01059             if (this.audioPendulum2 != null)
    01060             {
    01061                 int samplePos = 1; // offset for right channel
    01062                 short sampleValue = 0;
    01063                 double[] angles;
    01064                 double[] velocities;
    01065                 float theta;
    01066                 float omega;
    01067                 float fvalue = 0.0f;
    01068                 while ((this.audioPendulumSamplesRemaining[1] > 0) && (samplePos < samples))
    01069                 {
    01070                     // Update audio pendulum
    01071                     this.audioPendulum2.Animate();
    01072
    01073                     // Get values depending on the value indicator which was selected
    01074                     switch (PendulumGame.State.Players[1].SelectedIndicator)
    01075                     {
    01076                         case 0:
    01077                             angles = audioPendulum2.GetAngle();
    01078                             theta = MathHelper.WrapAngle((float)angles[0]);
    01079                             fvalue = theta / (float)Math.PI * maxAmplitude * (float)(short.MaxValue);
    01080                             break;
    01081                         case 1:
    01082                             angles = audioPendulum2.GetAngle();
    01083                             theta = MathHelper.WrapAngle((float)angles[1]);
    01084                             fvalue = theta / (float)Math.PI * maxAmplitude * (float)(short.MaxValue);
    01085                             break;
    01086                         case 2:
    01087                             velocities = audioPendulum2.GetVelocity();
    01088                             omega = (float)velocities[0];
    01089                             fvalue = (float)omega * 0.1f;
    01090                             if (fvalue < -maxAmplitude)
    01091                             {
    01092                                 fvalue = -maxAmplitude;
    01093                             }
    01094                             else if (fvalue > maxAmplitude)
    01095                             {
    01096                                 fvalue = maxAmplitude;
    01097                             }
    01098
    01099                             fvalue *= (float)(short.MaxValue);
    01100                             break;
    01101                         case 3:
    01102                             velocities = audioPendulum2.GetVelocity();
    01103                             omega = (float)velocities[1];
    01104                             fvalue = (float)omega * 0.1f;
    01105                             if (fvalue < -maxAmplitude)
    01106                             {
    01107                                 fvalue = -maxAmplitude;
    01108                             }
    01109                             else if (fvalue > maxAmplitude)
    01110                             {
    01111                                 fvalue = maxAmplitude;
    01112                             }
    01113
    01114                             fvalue *= (float)(short.MaxValue);
    01115                             break;
    01116                         default:
    01117                             fvalue = 0.0f;
    01118                             break;
    01119                     }
    01120
    01121
    01122                     sampleValue = Convert.ToInt16(fvalue);
    01123                     buffer[samplePos] = sampleValue;
    01124                     samplePos += 2;
    01125
    01126                     this.audioPendulumSamplesRemaining[1]--;
    01127                 }
    01128             }
    01129
    01130             System.Runtime.InteropServices.Marshal.Copy(buffer, 0, dest, samples);
    01131         }
    01132     }
    01133 }