/// <summary> /// sets up and begins new round /// </summary> /// <param name="form">the form being used for the game</param> public static void StartNew(Form form) { LeftMovement1 = false; RightMovement1 = false; LeftMovement2 = false; RightMovement2 = false; LastPlayerHit = Player.Player1; LabelLevels.Text = "Levels Completed: " + LevelsCompleted.ToString(); UpdateScores(); Balls = new List<Ball>(); Blocks = new List<Block>(); FormSize = new Vector(form.Size.Width, form.Size.Height - 100); PictureBox paddle1 = new PictureBox(); form.Controls.Add(paddle1); if (CurrentMode == GameMode.Coop || CurrentMode == GameMode.Versus) // 2 player { PictureBox paddle2 = new PictureBox(); form.Controls.Add(paddle2); PaddleObject2 = new Paddle(paddle2, new Vector(FormSize.X * 0.75f, FormSize.Y)); PaddleObject1 = new Paddle(paddle1, new Vector(FormSize.X * 0.25f, FormSize.Y)); } else // 1 player { PaddleObject1 = new Paddle(paddle1, new Vector(FormSize.X * 0.5f, FormSize.Y)); PaddleObject2 = null; } currentForm = form; BallsInPlay = 0; AddBall(); int blockRows = ((CurrentMode == GameMode.Classic) ? DefaultBlockRows : BlockRows); int blockColumns = ((CurrentMode == GameMode.Classic) ? DefaultBlockColumns : BlockColumns); int blockWidth = (int)FormSize.X / blockColumns; int blockHeight = (int)FormSize.Y / 3 / blockRows; const int blockFrame = 4; for (int x = 0; x < blockColumns; x++) { for (int y = 0; y < blockRows; y++) { float rowPercentage = (float)y / (float)blockRows; PictureBox newPictureBox = new PictureBox(); newPictureBox.BackColor = Color.FromArgb((int)Math.Round(255 * Math.Max(0, 1 - rowPercentage * 2), 0), (int)Math.Round(255 * (1 - 2 * Math.Abs(0.5f - rowPercentage)), 0), (int)Math.Round(255 * Math.Max(0, rowPercentage * 2 - 1), 0)); currentForm.Controls.Add(newPictureBox); Vector newBlockPosition = new Vector(x * blockWidth + blockFrame * 0.5f, y * blockHeight + blockFrame * 0.5f); Vector newBlockSize = new Vector(blockWidth - blockFrame, blockHeight - blockFrame); Block newBlock = new Block(newPictureBox, newBlockPosition, newBlockSize); newBlock.Points = 50 + 50 * (blockRows - y); } } gameThread = new Thread(GameThread); gameThread.IsBackground = true; gameThread.Start(); form.Disposed += delegate { gameThread.Abort(); }; InPlay = true; }
/// <summary> /// calculates collisions between the ball and a block, and finds the block surface tha was hit /// </summary> /// <param name="block">the block being hit</param> /// <param name="newPosition">the position the ball has</param> /// <param name="newVelocity">the velocity the ball is trying to move with</param> /// <param name="collidedRays">a list of rayIDs which have already collided with a surface</param> /// <returns>the position, length and surface of the collision</returns> public CollisionReturn CollidesWithBlock(Block block, Vector newPosition, Vector newVelocity, List<int> collidedRays) { // vector rays of moving ball Ray[] Vectors = new Ray[4]; Vectors[TopEdge] = new Ray(newPosition, newVelocity); Vectors[RightEdge] = new Ray(Vector.Add(newPosition, new Vector(Size.X, 0)), newVelocity); Vectors[BottomEdge] = new Ray(Vector.Add(newPosition, new Vector(0, Size.Y)), newVelocity); Vectors[LeftEdge] = new Ray(Vector.Add(newPosition, new Vector(Size.X, Size.Y)), newVelocity); CollisionReturn collisionReturn = new CollisionReturn(false); int rayID = 0; foreach (Ray ray in Vectors) { int edgeID = 0; if (!collidedRays.Contains(rayID)) // if the ray being used hasn't already collided with a box { // check every edge of the block foreach (Ray edge in block.Edges) { RaycastReturn raycastReturn = Ray.Raycast(ray, edge); // see if the ray meets the edge if (raycastReturn.Intersects) { // if there has already been a collision, check for a shorter one if (collisionReturn.Intersects) { if (raycastReturn.length < collisionReturn.length) // if the ball velocity ray hits this edge before any other ray hits an edge { collisionReturn = new CollisionReturn(raycastReturn); collisionReturn.Edge = edgeID; collisionReturn.Ray = rayID; } } // haven't had a ray collision yet, so use this collision by default else { collisionReturn = new CollisionReturn(raycastReturn); collisionReturn.Edge = edgeID; collisionReturn.Ray = rayID; } } edgeID++; // check next edge } } rayID++; // check next ray } return collisionReturn; // return results }
/// <summary> /// destroys a block and allocates points /// </summary> /// <param name="block">the block being destroyed</param> public static void DestroyBlock(Block block) { if (InPlay) // can only destroy in the game { currentForm.Controls.Remove(block.PictureBox); // remove picturebox Blocks.Remove(block); // remove from block list // if there are more balls to add, add one if (BallsInPlay < MaxBalls) AddBall(); // give the number of points the block is worth if (CurrentMode != GameMode.Versus) Points += block.Points; UpdateScores(); // display the new points // if all the blocks have been destroyed, start a new game if (Blocks.Count <= 0) { FinishCurrent(); System.Threading.Thread.Sleep(1000); LevelsCompleted++; StartNew(currentForm); } } }
// Add blocks to game private void CreateBlocks() { blocks = new List<Block>(); int blocksCount = 120; int cols = 12; int xStartPos = 70; int yStartPos = 30; int step = 5; int row = 0; int col = 0; for (int i = 0; i < blocksCount ; i++) { // Is it a new row if (i % cols == 0 && i > 0) { row++; col = 0; } else if (i > 0) { col++; } // Block position int x = (50 + step) * col + xStartPos; // 0, 55, 110... int y = (20 + step) * row + yStartPos; // 0, 25, 50, 75... // Create a new block Block block = new Block { LocationX = x, LocationY = y }; // Add to blocks blocks.Add(block); // List-collection // Add to canvas canvas.Children.Add(block); // Set location block.SetLocation(); } }