/Samples/Pong/PongGame.cs
C# | 378 lines | 235 code | 39 blank | 104 comment | 10 complexity | a8f8a73cb0f1d60d085d3d5dcc9ec80a MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using Delta.Engine.Dynamic;
- using Delta.Engine.SettingsNodes;
- using Delta.Utilities.Datatypes;
- using Delta.Engine;
- using Delta.Rendering.Basics.Materials;
- using Delta.Multimedia;
- using Delta.Utilities.Helpers;
- using Delta.InputSystem;
- using Delta.Rendering.Basics.Fonts;
- using Delta.Rendering.Basics.Drawing;
- using Delta.Utilities.Datatypes.Advanced;
-
- namespace Pong
- {
- /// <summary>
- /// Pong game
- /// </summary>
- public class PongGame : DynamicModule
- {
- #region Constants
- /// <summary>
- /// Name of the MoveUp command for player one.
- /// </summary>
- private const string PlayerOneMoveUpDigital = "PlayerOneMoveUpDigital";
- /// <summary>
- /// Name of the MoveDown command for player one.
- /// </summary>
- private const string PlayerOneMoveDownDigital = "PlayerOneMoveDownDigital";
- /// <summary>
- /// Name of the MoveUp command for player two per keyboard or digital
- /// GamePad.
- /// </summary>
- private const string PlayerTwoMoveUpDigital = "PlayerTwoMoveUpDigital";
- /// <summary>
- /// Name of the MoveDown command for player two per keyboard or digital
- /// GamePad.
- /// </summary>
- private const string PlayerTwoMoveDownDigital = "PlayerTwoMoveDownDigital";
- /// <summary>
- /// Name of the MoveUp command for player two per mouse or touch.
- /// </summary>
- private const string PlayerTwoMoveDirect = "PlayerTwoMoveDirect";
- /// <summary>
- /// Name of the command for quitting the game.
- /// </summary>
- private const string CommandQuitGame = "Quit";
- #endregion
-
- #region Private
- #region DrawArea
- /// <summary>
- /// Draw area of the screen in Quadratic Space
- /// </summary>
- private Rectangle DrawArea
- {
- get
- {
- return ScreenSpace.DrawArea;
- } // get
- }
- #endregion
-
- #region PaddleSpeed
- /// <summary>
- /// The speed of the paddle if it will be moved by a digital input device
- /// (Keyboard or GamePad)
- /// </summary>
- private float PaddleSpeed
- {
- get
- {
- return 0.75f * Time.Delta;
- }
- }
-
- /// <summary>
- /// AI speed, much slower ^^
- /// </summary>
- private float AISpeed
- {
- get
- {
- return 0.2f * Time.Delta;
- }
- }
- #endregion
-
- /// <summary>
- /// The background of the game.
- /// </summary>
- private Material2D background;
-
- /// <summary>
- /// Material to visualize the left player paddle.
- /// </summary>
- private Material2DColored leftPaddle;
- /// <summary>
- /// Material to visualize the right player paddle.
- /// </summary>
- private Material2DColored rightPaddle;
-
- #region HalfPaddleSize
- /// <summary>
- /// Half paddle size
- /// </summary>
- private Size HalfPaddleSize
- {
- get
- {
- return leftPaddle.Size * 0.5f;
- } // get
- }
- #endregion
-
- /// <summary>
- /// Center position of the left player paddle.
- /// </summary>
- private Point player1Position;
- /// <summary>
- /// Center position of the right player paddle.
- /// </summary>
- private Point player2Position;
-
- /// <summary>
- /// Current score of the left player.
- /// </summary>
- private int player1Score = 0;
- /// <summary>
- /// Current score of the right player.
- /// </summary>
- private int player2Score = 0;
-
- /// <summary>
- /// Initially player 1 (left paddle) is controlled by the AI until you press
- /// a command/ trigger button for player 2 (then it will only be controlled
- /// by a human).
- /// </summary>
- private bool isPlayer1AI = true;
-
- /// <summary>
- /// Material to visualize the ball in the game.
- /// </summary>
- private Material2DColored ball;
-
- #region HalfBallSize
- /// <summary>
- /// Half ball size
- /// </summary>
- private Size HalfBallSize
- {
- get
- {
- return ball.Size * 0.5f;
- } // get
- }
- #endregion
-
- #region BallRadius
- /// <summary>
- /// Ball radius
- /// </summary>
- private float BallRadius
- {
- get
- {
- return HalfBallSize.Width;
- } // get
- }
- #endregion
-
- /// <summary>
- /// The current position of the ball.
- /// </summary>
- private Point ballPosition;
- /// <summary>
- /// The current velocity of the ball.
- /// </summary>
- private Point ballVelocity;
-
- /// <summary>
- /// The collision sound between the ball and a player paddle.
- /// </summary>
- private Sound sound;
- #endregion
-
- #region Constructor
- /// <summary>
- /// Create pong game
- /// </summary>
- public PongGame()
- : base("PongGame", typeof(IGraphic))
- {
- // Initialize game elements
- background = new Material2D("SpaceBackground");
-
- leftPaddle = new Material2DColored("PongPaddle")
- {
- BlendColor = Color.Red,
- };
- rightPaddle = new Material2DColored("PongPaddle")
- {
- BlendColor = Color.Green,
- };
-
- ball = new Material2DColored("Ball");
- ballPosition = Point.Half;
- ballVelocity = new Point(0.3f, RandomHelper.RandomFloat(-0.2f, 0.2f));
-
- player1Position = new Point(DrawArea.Left + 0.05f, DrawArea.Top + 0.1f);
- player2Position = new Point(DrawArea.Right - 0.05f,
- DrawArea.Bottom - 0.1f);
-
- sound = new Sound("DefaultSound");
-
- RegisterInputCommands();
- }
- #endregion
-
- #region RegisterInputCommands
- /// <summary>
- /// Register input commands
- /// </summary>
- private void RegisterInputCommands()
- {
- // Player One paddle movement (up and down)
- Input.Commands[PlayerOneMoveUpDigital].Add(this, delegate
- {
- player1Position.Y -= PaddleSpeed;
- isPlayer1AI = false;
- });
- Input.Commands[PlayerOneMoveDownDigital].Add(this, delegate
- {
- player1Position.Y += PaddleSpeed;
- isPlayer1AI = false;
- });
-
- // Player two paddle movement (up and down)
- Input.Commands[PlayerTwoMoveUpDigital].Add(this, delegate
- {
- player2Position.Y -= PaddleSpeed;
- });
- Input.Commands[PlayerTwoMoveDownDigital].Add(this, delegate
- {
- player2Position.Y += PaddleSpeed;
- });
-
- // Direct move control via mouse or touch (just for player 2)
- Input.Commands[PlayerTwoMoveDirect].Add(this,
- delegate(CommandTrigger trigger)
- {
- player2Position.Y = trigger.Position.Y;
- });
-
- // Quit game with Escape, Back or Alt+F4
- Input.Commands[CommandQuitGame].Add(this, delegate
- {
- Application.Quit();
- });
- }
- #endregion
-
- #region Run (override)
- /// <summary>
- /// Run
- /// </summary>
- public override void Run()
- {
- Rectangle drawArea = ScreenSpace.DrawArea;
-
- #region AI
- if (isPlayer1AI)
- {
- // The AI does an ridiculously easy thing, it just follows the ball!
- if (player1Position.Y > ballPosition.Y - AISpeed)
- {
- player1Position.Y -= AISpeed;
- }
- else if (player1Position.Y < ballPosition.Y + AISpeed)
- {
- player1Position.Y += AISpeed;
- }
- }
- #endregion
-
- #region Ball physics
- //float deltaTime = Time.Delta > 0.7f ? 0.1f : Time.Delta;
- // Move the ball.
- ballPosition += ballVelocity * Time.Delta;
-
- // Make the ball faster over time.
- ballVelocity *= 1f + (0.07f * Time.Delta);
-
- // Floor and ceiling collision
- if ((ballPosition.Y <= drawArea.Top + BallRadius &&
- ballVelocity.Y < 0f) ||
- (ballPosition.Y >= drawArea.Bottom - BallRadius &&
- ballVelocity.Y > 0f))
- {
- ballVelocity.Y = -ballVelocity.Y;
- }
-
- // Paddle collision
- Rectangle ballCollisionRect = Rectangle.FromCenter(ballPosition,
- // Reduce ball size a bit to make collisions less unnatural at borders
- ball.Size * 0.75f);
-
- // Clamp the paddle to the screen area so it don't will run out of the
- // screen
- player1Position.Y = MathHelper.Clamp(player1Position.Y,
- drawArea.Top + 0.05f, drawArea.Bottom - 0.05f);
- player2Position.Y = MathHelper.Clamp(player2Position.Y,
- drawArea.Top + 0.05f, drawArea.Bottom - 0.05f);
-
- Rectangle paddle1Area = new Rectangle(
- player1Position - HalfPaddleSize, leftPaddle.Size);
- Rectangle paddle2Area = new Rectangle(
- player2Position - HalfPaddleSize, rightPaddle.Size);
-
- if (paddle1Area.Contains(ballCollisionRect) >= ContainmentType.Partial &&
- ballVelocity.X < 0f)
- {
- sound.Play();
- ballVelocity.X = -ballVelocity.X;
- } // if
- if (paddle2Area.Contains(ballCollisionRect) >= ContainmentType.Partial &&
- ballVelocity.X > 0f)
- {
- sound.Play();
- ballVelocity.X = -ballVelocity.X;
- } // if
-
- // Goal collision
- if (ballPosition.X <= drawArea.Left)
- {
- player2Score++;
- ballPosition = Point.Half;
- ballVelocity = new Point(0.3f,
- RandomHelper.RandomFloat(-0.2f, 0.2f));
- } // if
- if (ballPosition.X >= drawArea.Right)
- {
- player1Score++;
- ballPosition = Point.Half;
- ballVelocity = new Point(-0.3f,
- RandomHelper.RandomFloat(-0.2f, 0.2f));
- } // if
-
- if (Settings.Debug.IsDrawDebugInfoModeOn(ProfilingMode.Custom))
- {
- Rect.DrawOutline(paddle1Area, Color.Blue);
- Rect.DrawOutline(paddle2Area, Color.Blue);
- Circle.DrawOutline(ballPosition, BallRadius, Color.Yellow);
- Rect.DrawOutline(ballCollisionRect, Color.Yellow);
- }
- #endregion
-
- #region Drawing
- background.Draw(drawArea);
-
- leftPaddle.Draw(paddle1Area, 180);
- rightPaddle.Draw(paddle2Area);
- Rectangle ballArea = new Rectangle(ballPosition - HalfBallSize,
- ball.Size);
- ball.Draw(ballArea, Time.Milliseconds / 5.0f);
-
- Font textFont = Font.Default;
- textFont.Draw(player1Score + " | SCORE | " + player2Score,
- new Rectangle(0.0f, drawArea.Top, 1.0f, textFont.LineHeight));
- textFont.Draw(
- "Controls: W/S (left player), Cursor keys/GamePad (right player)",
- new Rectangle(0.0f, drawArea.Top + textFont.LineHeight, 1.0f,
- textFont.LineHeight));
- #endregion
- }
- #endregion
- }
- }