using System; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace BouncyCatIsBouncy { class Cat : IDynamicObject { public delegate void EventHandler(); public event EventHandler OnLaunch; public event EventHandler OnDeath; SpriteBatch m_batch; bool m_launched; public bool Launched { get { return m_launched; } } public bool Dead { get; private set; } PhysicsBody m_body; Animation m_animation; RandomCatSounds m_catSounds; SoundEffect m_cannonBlast; Random m_rand = new Random(); float m_rotationAmount; float m_launchDelay = 2000.0f; const int CAT_SIZE = 80; public Vector2 Position { get { return m_body.Position; } set { m_animation.Center = m_body.Position = value; } } public Cat(SpriteBatch batch, Physics simulator) { Debug.Assert(batch != null); m_batch = batch; m_body = new PhysicsBody(); m_body.CoeffRestitution = .95f; m_body.OnCollision += OnCollision; var geom = new PhysicsGeom(m_body, new RadialBB(CAT_SIZE / 2.0f)); simulator.SetPrimary(m_body); } public void Update(float dt) { if (Dead) return; m_animation.Update(dt); m_animation.Rotation += m_rotationAmount * dt; m_animation.Center = m_body.Position; if (m_launched) { if (m_launchDelay > 0.0f) { m_launchDelay -= dt; if (m_launchDelay <= 0.0f) { m_body.ApplyImpulse(m_launchNormal * 1.3f); m_body.Gravity = new Vector2(0, .00025f); m_cannonBlast.Play(); } } else { CheckVelocity(dt); } } } const float TIME_BEFORE_DEAD = 1000.0f; float m_timeSinceMovement = TIME_BEFORE_DEAD; private void CheckVelocity(float dt) { if (m_body.Velocity.LengthSquared() < .01f) { m_timeSinceMovement -= dt; if (m_timeSinceMovement < 0.0f) { m_body.Velocity = m_body.Gravity = Vector2.Zero; Dead = true; if (OnDeath != null) OnDeath(); } } else { m_timeSinceMovement = TIME_BEFORE_DEAD; } } Vector2 m_launchNormal; public void Launch(Vector2 normal) { if (!m_launched) { m_launchNormal = normal; m_launched = true; if (OnLaunch != null) OnLaunch(); m_animation.Animating = true; ApplyRotation(); } } private void OnCollision(PhysicsBody otherBody) { if (Dead) return; ApplyRotation(); if (otherBody.CollisionResponseEnable && m_rand.NextDouble() > .85) { m_catSounds.Play(); } } private void ApplyRotation() { m_rotationAmount = (float)(m_rand.NextDouble() - .5) / 50.0f; } public void Draw() { if (m_launchDelay <= 0.0f) m_animation.Draw(); Debugging.RadialBBRenderer.Draw(m_batch, (RadialBB)m_body.Geometry[0].Bounding); Debugging.DrawVector.Draw(m_batch, m_body.Position, m_body.Position + m_body.Velocity * 100, Color.Green); } public void LoadContent(ContentManager manager) { m_animation = new Animation(m_batch, manager.Load(@"Spritesheets/mittens"), 256, 256); m_animation.Height = m_animation.Width = CAT_SIZE; m_catSounds = new RandomCatSounds(manager); m_cannonBlast = manager.Load(@"Sounds/Misc/cannonlaunch"); } } }