/// <summary> /// Produces an exact clone of this actor. /// </summary> public Actor Clone() { // First we must clone all the behaviors. ActorBehavior[] behaviorClones = new ActorBehavior[behaviors.Count]; for (int i = 0; i < behaviors.Count; ++i) { ActorBehavior behavior = behaviors[i]; behaviorClones[i] = (ActorBehavior)behavior.Clone(); } Actor clone = new Actor(game, behaviorClones); clone.Sprite = sprite; clone.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateBody(physicsBody); clone.physicsGeom = Physics.Collisions.GeomFactory.Instance.CreateGeom(clone.PhysicsBody, physicsGeom); // We need to add the cloned physics body and geometry to the simulator. Physics.PhysicsSimulator physicsSimulator = (Physics.PhysicsSimulator)game.Services.GetService(typeof(Physics.PhysicsSimulator)); physicsSimulator.Add(clone.PhysicsBody); physicsSimulator.Add(clone.PhysicsGeom); // We need to loop through all the behaviors and assign the cloned actor as their parent. foreach (ActorBehavior behavior in clone.Behaviors) { behavior.ParentActor = clone; behavior.Initialize(); } return clone; }
/// <summary> /// Registers a new template. /// </summary> public void AddActorTemplate(Actor template, string name) { actorTemplates[name] = template; }
/// <summary> /// Loads graphics content needed for the game. /// </summary> public override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) { if (content == null) content = new ContentManager(ScreenManager.Game.Services, "Content"); grid = new MassSpringGrid(60, 5f, 100f, 0.5f, new Rectangle(safeAreaWidth, safeAreaHeight, screenSafeWidth, screenSafeHeight)); actorManager = new ActorManager(); #region Allocate graphics content spriteBatch = new SpriteBatch(ScreenManager.GraphicsDevice); lineBatch = new LineBatch(ScreenManager.GraphicsDevice); starTexture = content.Load<Texture2D>("blank"); Animation countdownAnim = new Animation(content, 300, 100); countdownAnim.AddFrame(new AnimationFrame(TimeSpan.FromSeconds(2.0f / 3.0f), "ready")); countdownAnim.AddFrame(new AnimationFrame(TimeSpan.FromSeconds(2.0f / 3.0f), "set")); countdownAnim.AddFrame(new AnimationFrame(TimeSpan.FromSeconds(2.0f / 3.0f), "go")); countdownSprite = new Sprite(); countdownSprite.AddAnimation("default", countdownAnim); countdownSprite.SetCurrentAnimation("default"); #endregion #region Set up lightning boxes playerLightningBox = new LightningBox(new Rectangle(safeAreaWidth + 10, screenHeight - safeAreaHeight - 38 - 150, screenSafeWidth - 30, 150)); computerLightningBox = new LightningBox(new Rectangle(safeAreaWidth + 10, safeAreaHeight + 38, screenSafeWidth - 30, 150)); #endregion #region Collision Categories for physics // Collision Categories: // // 1 = player paddle // 10 = ball // 11 = gravity ball // 12 = obstacle // 13 = computer paddle // 14 = bullet // 20 = screen borders // 21 = player lightning box // 22 = borders for obstacles // 23 = computer lightning box #endregion #region Create Player Paddle Actor Template Actor playerPaddleTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new GamePadPaddleController(actorManager), new DistortGridBehavior(actorManager, grid, DistortGridDetail.High), new ConstrainToRectangleBehavior(actorManager, playerLightningBox.Rectangle, Physics.Enums.CollisionCategories.Cat21) }, content, "paddle", 100, 100 * 0.174089069f); playerPaddleTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateRectangleBody(playerPaddleTemplate.Sprite.Width, playerPaddleTemplate.Sprite.Height, 1); playerPaddleTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateRectangleGeom(playerPaddleTemplate.PhysicsBody, playerPaddleTemplate.Sprite.Width, playerPaddleTemplate.Sprite.Height); playerPaddleTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat1; playerPaddleTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat1 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat11; playerPaddleTemplate.PhysicsBody.LinearDragCoefficient = 0.01f; playerPaddleTemplate.PhysicsBody.RotationalDragCoefficient = 300.0f; actorManager.AddActorTemplate(playerPaddleTemplate, "Player Paddle"); #endregion #region Create Computer Paddle Actor Template Actor computerPaddleTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new DistortGridBehavior(actorManager, grid, DistortGridDetail.High), new ConstrainToRectangleBehavior(actorManager, computerLightningBox.Rectangle, Physics.Enums.CollisionCategories.Cat23), new AIPaddleController(actorManager) }, content, "paddle2", 100, 100 * 0.174089069f); computerPaddleTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateRectangleBody(playerPaddleTemplate.Sprite.Width, playerPaddleTemplate.Sprite.Height, 1); computerPaddleTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateRectangleGeom(playerPaddleTemplate.PhysicsBody, playerPaddleTemplate.Sprite.Width, playerPaddleTemplate.Sprite.Height); computerPaddleTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat13; computerPaddleTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat13 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat11; computerPaddleTemplate.PhysicsBody.LinearDragCoefficient = 0.01f; computerPaddleTemplate.PhysicsBody.RotationalDragCoefficient = 300.0f; actorManager.AddActorTemplate(computerPaddleTemplate, "Computer Paddle"); #endregion #region Create Obstacle Actor Template Actor obstacleActorTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new DistortGridBehavior(actorManager, grid, DistortGridDetail.High), new ConstrainToRectangleBehavior(actorManager, new Rectangle( computerLightningBox.Rectangle.X, computerLightningBox.Rectangle.Y + computerLightningBox.Rectangle.Height, computerLightningBox.Rectangle.Width, playerLightningBox.Rectangle.Y - (computerLightningBox.Rectangle.Y + computerLightningBox.Rectangle.Height)), Physics.Enums.CollisionCategories.Cat22), new ShootOffRandomlyBehavior(actorManager, 300, 350), new InteractWithBlackHolesBehavior(actorManager) }, content, "obstacle", 45.0f, 45.0f); obstacleActorTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateRectangleBody(obstacleActorTemplate.Sprite.Width, obstacleActorTemplate.Sprite.Height, 0.001f); obstacleActorTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateRectangleGeom(obstacleActorTemplate.PhysicsBody, obstacleActorTemplate.Sprite.Width, obstacleActorTemplate.Sprite.Height); obstacleActorTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat12; obstacleActorTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat1 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat11 | Physics.Enums.CollisionCategories.Cat12; obstacleActorTemplate.PhysicsBody.LinearDragCoefficient = 0.0f; actorManager.AddActorTemplate(obstacleActorTemplate, "Obstacle"); #endregion #region Create Ball Actor Template float ballDiameter = 25.0f; Actor ballTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new DistortGridBehavior(actorManager, grid, DistortGridDetail.High), new ConstrainToRectangleBehavior(actorManager, new Rectangle(safeAreaWidth, safeAreaHeight, screenSafeWidth, screenSafeHeight), Physics.Enums.CollisionCategories.Cat20), new ShootOffRandomlyBehavior(actorManager, 300, 301.0f), new InteractWithBlackHolesBehavior(actorManager) }, content, "ball", ballDiameter, ballDiameter); ballTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateCircleBody(ballDiameter / 2.0f, 0.001f); ballTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateCircleGeom(ballTemplate.PhysicsBody, ballDiameter / 2.0f, 16); ballTemplate.PhysicsBody.LinearDragCoefficient = 0.0f; ballTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat10; ballTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat1 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat13; actorManager.AddActorTemplate(ballTemplate, "Ball"); #endregion #region Create Gravity Ball Actor Template float gravityBallDiameter = 55.0f; Actor gravBallTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new BlackHoleBehavior(actorManager, grid), new ConstrainToRectangleBehavior(actorManager, new Rectangle(safeAreaWidth, safeAreaHeight, screenSafeWidth, screenSafeHeight), Physics.Enums.CollisionCategories.Cat20), new LiveTemporarilyBehavior(actorManager, TimeSpan.FromSeconds(2.9f), TimeSpan.FromSeconds(0.5)) }, content, "GravityBall", gravityBallDiameter, 2.0f); gravBallTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateCircleBody(gravityBallDiameter / 2.0f, 3.0f); gravBallTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateCircleGeom(gravBallTemplate.PhysicsBody, gravityBallDiameter / 2.0f, 16); gravBallTemplate.PhysicsBody.LinearDragCoefficient = 0.0f; gravBallTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat11; gravBallTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat11 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat1 | Physics.Enums.CollisionCategories.Cat13; actorManager.AddActorTemplate(gravBallTemplate, "Gravity Ball"); #endregion #region Create Bullet Actor Template float bulletDiameter = 5.0f; Actor bulletTemplate = new Actor(ScreenManager.Game, new ActorBehavior[] { new ConstrainToRectangleBehavior(actorManager, new Rectangle(safeAreaWidth, safeAreaHeight, screenSafeWidth, screenSafeHeight), Physics.Enums.CollisionCategories.Cat20), new DieUponCollisionBehavior(actorManager), new InteractWithBlackHolesBehavior(actorManager) }, content, "projectile", bulletDiameter, bulletDiameter); bulletTemplate.PhysicsBody = Physics.Dynamics.BodyFactory.Instance.CreateCircleBody(bulletDiameter / 2.0f, 0.001f); bulletTemplate.PhysicsGeom = Physics.Collisions.GeomFactory.Instance.CreateCircleGeom(bulletTemplate.PhysicsBody, bulletDiameter / 2.0f, 16); bulletTemplate.PhysicsBody.LinearDragCoefficient = 0.0f; bulletTemplate.PhysicsGeom.CollisionCategories = Physics.Enums.CollisionCategories.Cat14; bulletTemplate.PhysicsGeom.CollidesWith = Physics.Enums.CollisionCategories.Cat1 | Physics.Enums.CollisionCategories.Cat10 | Physics.Enums.CollisionCategories.Cat11 | Physics.Enums.CollisionCategories.Cat12 | Physics.Enums.CollisionCategories.Cat13; actorManager.AddActorTemplate(bulletTemplate, "Bullet"); #endregion #region Place basic gameplay objects playerPaddle = actorManager.InstantiateTemplate("Player Paddle"); playerPaddle.PhysicsBody.Position = new Vector2(safeAreaWidth + screenSafeWidth / 2.0f, screenHeight - safeAreaHeight - 38 - 150 / 2); computerPaddle = actorManager.InstantiateTemplate("Computer Paddle"); computerPaddle.PhysicsBody.Position = new Vector2(safeAreaWidth + screenSafeWidth / 2.0f, safeAreaHeight + 38 + 150 / 2); ball = actorManager.InstantiateTemplate("Ball"); ball.PhysicsBody.Position = new Vector2(safeAreaWidth + screenSafeWidth / 2, safeAreaHeight + screenSafeHeight / 2); PauseBallForNewRound(); ShootOffRandomlyBehavior shootOffBehavior = (ShootOffRandomlyBehavior)ball.GetBehavior(typeof(ShootOffRandomlyBehavior)); shootOffBehavior.JustStarting = false; AIPaddleController ai = (AIPaddleController)computerPaddle.GetBehavior(typeof(AIPaddleController)); ai.Ball = ball; PopulateArenaWithObstacles(); #endregion } // Set the projection matrix for the line batch lineBatch.SetProjection(Matrix.CreateOrthographicOffCenter( 0.0f, ScreenManager.GraphicsDevice.Viewport.Width, ScreenManager.GraphicsDevice.Viewport.Height, 0.0f, 0.0f, 1.0f)); }