private void BoxCollideWithGround(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { String materialName = ((IPhysicsObject)collidingObject.UserTagObj).MaterialName; if (materialName.Equals("Ground")) { // Set the collision sound volume based on the contact speed SoundEffectInstance instance = Sound.Instance.PlaySoundEffect(bounceSound); // Print a text message on the screen Notifier.AddMessage("Contact with ground"); // Create a 3D text to be rendered Text3DInfo text3d = new Text3DInfo(); text3d.Text = "BOOM!!"; // The larger the contact speed, the longer the 3D text will stay displayed text3d.Duration = 1 * 500; text3d.ElapsedTime = 0; Vector3 contactPosition = Vector3.Zero; baseObject.MainWorldTransform.GetPosition(ref contactPosition); // Scale down the vector font since it's quite large, and display the text // above the contact position text3d.Transform = Matrix.CreateScale(0.03f) * Matrix.CreateTranslation(contactPosition + Vector3.UnitY * 4); // Add this 3D text to the display list text3ds.Add(text3d); } }
/// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { if (text3ds.Count > 0) { // Catch exception in case text3ds becomes empty after deletion in Update try { Text3DInfo[] text3DArray = new Text3DInfo[text3ds.Count]; // Copy the display list to an array since the display list can be modified // at any time text3ds.CopyTo(text3DArray); // Render the 3D texts in the display list in outline style with red color foreach (Text3DInfo text3d in text3DArray) { UI3DRenderer.Write3DText(text3d.Text, vectorFont, UI3DRenderer.Text3DStyle.Outline, Color.Red, text3d.Transform); } } catch (Exception) { } } scene.Draw(gameTime.ElapsedGameTime, gameTime.IsRunningSlowly); }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { base.Initialize(); #if WINDOWS // Display the mouse cursor this.IsMouseVisible = true; #endif // Initialize the GoblinXNA framework State.InitGoblin(graphics, Content, ""); #if WINDOWS_PHONE this.Activated += Sound.Instance.GameActivated; #endif // Initialize the scene graph scene = new Scene(); // Set the background color to CornflowerBlue color. // GraphicsDevice.Clear(...) is called by Scene object with this color. scene.BackgroundColor = Color.CornflowerBlue; #if WINDOWS // We will use the Newton physics engine (http://www.newtondynamics.com) // for processing the physical simulation scene.PhysicsEngine = new NewtonPhysics(); #else scene.PhysicsEngine = new MataliPhysics(); #endif scene.PhysicsEngine.Gravity = 30; #if WINDOWS_PHONE ((MataliPhysics)scene.PhysicsEngine).SimulationTimeStep = 1 / 30f; #endif text3ds = new List <Text3DInfo>(); // Set up the lights used in the scene CreateLights(); // Set up the camera which defines the eye location and viewing frustum CreateCamera(); // Create 3D objects CreateObjects(); #if WINDOWS // Set up physics material interaction specifications between the shooting box and the ground NewtonMaterial physMat = new NewtonMaterial(); physMat.MaterialName1 = "ShootingBox"; physMat.MaterialName2 = "Ground"; physMat.Elasticity = 0.7f; physMat.StaticFriction = 0.8f; physMat.KineticFriction = 0.2f; // Define a callback function that will be called when the two materials contact/collide physMat.ContactProcessCallback = delegate(Vector3 contactPosition, Vector3 contactNormal, float contactSpeed, float colObj1ContactTangentSpeed, float colObj2ContactTangentSpeed, Vector3 colObj1ContactTangentDirection, Vector3 colObj2ContactTangentDirection) { if (contactSpeed > 2) { collisionCount++; } // When a cube box collides with the ground, it can have more than 1 contact points // depending on the collision surface, so we only play sound and add 3D texts once // every four contacts to avoid multiple sound play or text addition for one surface // contact if (collisionCount >= 4) { // Set the collision sound volume based on the contact speed SoundEffectInstance instance = Sound.Instance.PlaySoundEffect(bounceSound); //instance.Volume = contactSpeed / 50f; // Print a text message on the screen Notifier.AddMessage("Contact with speed of " + contactSpeed); // Create a 3D text to be rendered Text3DInfo text3d = new Text3DInfo(); text3d.Text = "BOOM!!"; // The larger the contact speed, the longer the 3D text will stay displayed text3d.Duration = contactSpeed * 500; text3d.ElapsedTime = 0; // Scale down the vector font since it's quite large, and display the text // above the contact position text3d.Transform = Matrix.CreateScale(0.03f) * Matrix.CreateTranslation(contactPosition + Vector3.UnitY * 4); // Add this 3D text to the display list text3ds.Add(text3d); // Reset the count collisionCount = 0; } }; // Add this physics material interaction specifications to the physics engine ((NewtonPhysics)scene.PhysicsEngine).AddPhysicsMaterial(physMat); #endif // Add a mouse click handler for shooting a box model from the mouse location MouseInput.Instance.MouseClickEvent += new HandleMouseClick(MouseClickHandler); // Show some debug information State.ShowFPS = true; // Show debugging messages on the screen State.ShowNotifications = true; // Make the debugging message fade out after 3000 ms (3 seconds) Notifier.FadeOutTime = 3000; }
/// <summary> /// Draws a 3D text with the given font, style, color, transformation, horizontal align, and vertical /// align. /// </summary> /// <remarks> /// This 3D text won't be actually drawn until Flush() method is called. If this method is called before /// base.Draw(...) in your main Game class's Draw(...) function, then it's automatically flushed when /// base.Draw(...) is called. If this method is called after base.Draw(...) function, then you need to /// call Flush() function after calling one or more of this function. Otherwise, the 3D texts drawing will /// be deferred until the next base.Draw(...) or Flush() call. /// </remarks> /// <param name="text">Text string to be displayed in 3D.</param> /// <param name="font">Font to use for the 3D text.</param> /// <param name="style">3D text style (Outline, Fill, or Extrude).</param> /// <param name="color">Color of the 3D text.</param> /// <param name="transform">Transformation of the 3D text.</param> /// <param name="hAlign">The horizontal (x-axis) shifting</param> /// <param name="vAlign"></param> public static void Write3DText(String text, VectorFont font, Text3DStyle style, Color color, Matrix transform, GoblinEnums.HorizontalAlignment hAlign, GoblinEnums.VerticalAlignment vAlign) { if (queued3DTexts == null) { queued3DTexts = new List <Text3DInfo>(); } Text3DInfo textInfo = new Text3DInfo(); Text text3d = null; if (font == null) { throw new ArgumentException("'font' must be non-null value"); } switch (style) { case Text3DStyle.Outline: text3d = font.Outline(text); break; case Text3DStyle.Fill: text3d = font.Fill(text); break; case Text3DStyle.Extrude: text3d = font.Extrude(text); break; } textInfo.text3d = text3d; textInfo.color = color; Matrix shiftTransform = Matrix.Identity; switch (hAlign) { case GoblinEnums.HorizontalAlignment.None: case GoblinEnums.HorizontalAlignment.Left: // The default is aligned to left, so nothing to do break; case GoblinEnums.HorizontalAlignment.Center: shiftTransform.Translation -= Vector3.UnitX * text3d.Width / 2; break; case GoblinEnums.HorizontalAlignment.Right: shiftTransform.Translation -= Vector3.UnitX * text3d.Width; break; } switch (vAlign) { case GoblinEnums.VerticalAlignment.None: case GoblinEnums.VerticalAlignment.Bottom: // The default is aligned to bottom, so nothing to do break; case GoblinEnums.VerticalAlignment.Center: shiftTransform.Translation -= Vector3.UnitY * text3d.Height / 2; break; case GoblinEnums.VerticalAlignment.Top: shiftTransform.Translation -= Vector3.UnitY * text3d.Height; break; } shiftTransform *= MatrixHelper.GetRotationMatrix(transform); transform.Translation += shiftTransform.Translation; textInfo.transform = transform; queued3DTexts.Add(textInfo); }
/// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { if (text3ds.Count > 0) { // Catch exception in case text3ds becomes empty after deletion in Update try { Text3DInfo[] text3DArray = new Text3DInfo[text3ds.Count]; // Copy the display list to an array since the display list can be modified // at any time text3ds.CopyTo(text3DArray); // Render the 3D texts in the display list in outline style with red color foreach (Text3DInfo text3d in text3DArray) UI3DRenderer.Write3DText(text3d.Text, vectorFont, UI3DRenderer.Text3DStyle.Outline, Color.Red, text3d.Transform); } catch (Exception) { } } scene.Draw(gameTime.ElapsedGameTime, gameTime.IsRunningSlowly); Texture2D ch = Content.Load<Texture2D>("crosshairs"); Vector2 position = new Vector2(scene.BackgroundBound.Width/2, scene.BackgroundBound.Height / 2); //hard-coded crosshairs position Notifier.AddMessage((scene.BackgroundBound.Width / 2) + " " + (scene.BackgroundBound.Height / 2)); //how it should work: //Vector2 position = new Vector2(State.Width / 2, State.Height / 2); State.SharedSpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend); State.SharedSpriteBatch.Draw(ch, position, Color.White); State.SharedSpriteBatch.End(); }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { base.Initialize(); #if WINDOWS // Display the mouse cursor this.IsMouseVisible = true; #endif // Initialize the GoblinXNA framework State.InitGoblin(graphics, Content, ""); #if WINDOWS_PHONE this.Activated += Sound.Instance.GameActivated; #endif //State.ThreadOption = (ushort)ThreadOptions.MarkerTracking; // Initialize the scene graph scene = new Scene(); // Set the background color to CornflowerBlue color. // GraphicsDevice.Clear(...) is called by Scene object with this color. scene.BackgroundColor = Color.CornflowerBlue; #if WINDOWS // We will use the Newton physics engine (http://www.newtondynamics.com) // for processing the physical simulation scene.PhysicsEngine = new NewtonPhysics(); #else scene.PhysicsEngine = new MataliPhysics(); #endif scene.PhysicsEngine.Gravity = 30; #if WINDOWS_PHONE ((MataliPhysics)scene.PhysicsEngine).SimulationTimeStep = 1 / 30f; #endif text3ds = new List<Text3DInfo>(); // Set up the lights used in the scene CreateLights(); // Set up the camera which defines the eye location and viewing frustum CreateCamera(); // Create 3D objects CreateObjects(); #if WINDOWS // Set up physics material interaction specifications between the shooting box and the ground NewtonMaterial physMat = new NewtonMaterial(); physMat.MaterialName1 = "ShootingBox"; physMat.MaterialName2 = "Ground"; physMat.Elasticity = 0.7f; physMat.StaticFriction = 0.8f; physMat.KineticFriction = 0.2f; // Define a callback function that will be called when the two materials contact/collide physMat.ContactProcessCallback = delegate(Vector3 contactPosition, Vector3 contactNormal, float contactSpeed, float colObj1ContactTangentSpeed, float colObj2ContactTangentSpeed, Vector3 colObj1ContactTangentDirection, Vector3 colObj2ContactTangentDirection) { if (contactSpeed > 2) collisionCount++; // When a cube box collides with the ground, it can have more than 1 contact points // depending on the collision surface, so we only play sound and add 3D texts once // every four contacts to avoid multiple sound play or text addition for one surface // contact if (collisionCount >= 4) { // Set the collision sound volume based on the contact speed SoundEffectInstance instance = Sound.Instance.PlaySoundEffect(bounceSound); //instance.Volume = contactSpeed / 50f; // Print a text message on the screen Notifier.AddMessage("Contact with speed of " + contactSpeed); // Create a 3D text to be rendered Text3DInfo text3d = new Text3DInfo(); text3d.Text = "BOOM!!"; // The larger the contact speed, the longer the 3D text will stay displayed text3d.Duration = contactSpeed * 500; text3d.ElapsedTime = 0; // Scale down the vector font since it's quite large, and display the text // above the contact position text3d.Transform = Matrix.CreateScale(0.03f) * Matrix.CreateTranslation(contactPosition + Vector3.UnitY * 4); // Add this 3D text to the display list text3ds.Add(text3d); // Reset the count collisionCount = 0; } }; // Add this physics material interaction specifications to the physics engine ((NewtonPhysics)scene.PhysicsEngine).AddPhysicsMaterial(physMat); #endif // Add a mouse click handler for shooting a box model from the mouse location MouseInput.Instance.MouseClickEvent += new HandleMouseClick(MouseClickHandler); State.ThreadOption = (ushort)ThreadOptions.MarkerTracking; // Show some debug information State.ShowFPS = true; // Show debugging messages on the screen State.ShowNotifications = true; // Make the debugging message fade out after 3000 ms (3 seconds) Notifier.FadeOutTime = 3000; }