// Tells whether this intersects another rectangle at offset public override bool intersects(GameRectangle other, double[] offset) { if (Math.Abs(offset[0]) >= (this.getWidth() + other.getWidth()) / 2) { return(false); } if (Math.Abs(offset[1]) >= (this.getHeight() + other.getHeight()) / 2) { return(false); } return(true); }
private void InitializeField() { outsideRecArr = new GameRectangle[3, 3]; insideRecArr = new GameRectangleInside[3, 3][, ]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Rectangle temp = new Rectangle() { Fill = new SolidColorBrush(Color.FromArgb(150, 0, 0, 0)), Height = BIG_REC_SIZE, Width = BIG_REC_SIZE, Margin = new Thickness((i + 1) * 10 + i * BIG_REC_SIZE, (j + 1) * 10 + j * BIG_REC_SIZE, 0, 0) }; outsideRecArr[i, j] = new GameRectangle(temp, i, j); canvas_play.Children.Add(temp); insideRecArr[i, j] = new GameRectangleInside[3, 3]; for (int m = 0; m < 3; m++) { for (int n = 0; n < 3; n++) { Rectangle temp1 = new Rectangle() { Fill = new SolidColorBrush(Color.FromArgb(255, 150, 150, 150)), Height = SMALL_REC_SIZE, Width = SMALL_REC_SIZE, Margin = new Thickness( (i + 1) * 10 + i * BIG_REC_SIZE + 10 + (m + 1) * 10 + m * SMALL_REC_SIZE, (j + 1) * 10 + j * BIG_REC_SIZE + 10 + (n + 1) * 10 + n * SMALL_REC_SIZE, 0, 0) }; temp1.MouseUp += Cell_Click; insideRecArr[i, j][m, n] = new GameRectangleInside(temp1, i, j, m, n); canvas_play.Children.Add(temp1); } } } } }
// Tells whether a GameCircle would intersect a GameRectangle at offset public override bool intersects(GameRectangle other, double[] offset) { double deltaX = Math.Abs(offset[0]) - other.getWidth() / 2; if (deltaX < 0) { deltaX = 0; } double deltaY = Math.Abs(offset[1]) - other.getHeight() / 2; if (deltaY < 0) { deltaY = 0; } if (deltaX * deltaX + deltaY * deltaY < this.radius * this.radius) { return(true); } else { return(false); } }
// Returns the maximum amount of distance that this can move in the move direction, given a rectangle at offset public override double[] moveTo(GameRectangle other, double[] offset, double[] move) { GameCircle c = this; GameRectangle r = other; double[] mirroredMove = new double[move.Length]; double[] mirroredOffset = new double[move.Length]; int i; // flip the coordinate system so that the offset is positive in all dimensions for (i = 0; i < move.Length; i++) { if (offset[i] >= 0) { mirroredOffset[i] = offset[i]; mirroredMove[i] = move[i]; } else { mirroredOffset[i] = -offset[i]; mirroredMove[i] = -move[i]; } } //System.Collections.Generic.List<double[]> intersections; //double[] tempIntersection; // figure out where it may intersect the left/right wall double width = r.getWidth() / 2 + c.getRadius(); if (mirroredMove[0] > 0 && mirroredOffset[0] >= width) { // calculate where it will intersect this line double[] allowedMove = new double[2]; allowedMove[0] = mirroredOffset[0] - width; // check that it will go far enough to collide if (allowedMove[0] < mirroredMove[0]) { allowedMove[1] = allowedMove[0] * mirroredMove[1] / mirroredMove[0]; // make sure that it actually intersects the line segment and not just the line if (Math.Abs(mirroredOffset[1] - allowedMove[1]) <= r.getHeight() / 2) { // reflect it back correctly and return if (offset[0] < 0) { allowedMove[0] *= -1; } if (offset[1] < 0) { allowedMove[1] *= -1; } return(allowedMove); } } } double height = r.getHeight() / 2 + c.getRadius(); if (mirroredMove[1] > 0 && mirroredOffset[1] >= height) { // calculate where it will intersect this line double[] allowedMove = new double[2]; allowedMove[1] = mirroredOffset[1] - height; // check that it will go far enough to collide if (allowedMove[1] < mirroredMove[1]) { allowedMove[0] = allowedMove[1] * mirroredMove[0] / mirroredMove[1]; // make sure that it actually intersects the line segment and not just the line if (Math.Abs(mirroredOffset[0] - allowedMove[0]) <= r.getWidth() / 2) { // reflect it back correctly and return if (offset[0] < 0) { allowedMove[0] *= -1; } if (offset[1] < 0) { allowedMove[1] *= -1; } return(allowedMove); } } } // figure out where it may intersect the corner arc double length = Math.Sqrt(move[0] * move[0] + move[1] * move[1]); double signedWidth = r.getWidth() / 2; double signedHeight = r.getHeight() / 2; for (i = 0; i < 2; i++) { double lateralOffset = (mirroredOffset[0] - signedWidth) * mirroredMove[1] / length - (mirroredOffset[1] - signedHeight) * mirroredMove[0] / length; // first check that the movement line will reach the arc if (Math.Abs(lateralOffset) <= c.getRadius()) { double forwardOffset = (mirroredOffset[0] - signedWidth) * mirroredMove[0] / length + (mirroredOffset[1] - signedHeight) * mirroredMove[1] / length; // Next check that the movement line is facing the right direction if (forwardOffset >= 0) { double collisionDist = forwardOffset - Math.Sqrt(c.getRadius() * c.getRadius() - lateralOffset * lateralOffset); // Make sure that it is hitting the outside of the arc if ((Math.Abs(mirroredOffset[0] - mirroredMove[0] * collisionDist / length) >= r.getWidth() / 2) && (Math.Abs(mirroredOffset[1] - mirroredMove[1] * collisionDist / length) >= r.getHeight() / 2)) { // If we get here then it is, in fact, moving toward the corner of the rectangle from the outside. Now decide if it wants to move that far // if it doesn't want to move that far, then it can just keep going if (collisionDist >= length) { return(move); } else { // If we get here, it means is would collide with the arc and we need to shorten the length double[] allowedMove = new double[2]; allowedMove[0] = move[0] * collisionDist / length; allowedMove[1] = move[1] * collisionDist / length; return(allowedMove); } } } } // Now alter the coordinates to check the other corner, and repeat if ((mirroredOffset[0] - signedWidth) * mirroredMove[0] >= (mirroredOffset[1] - signedHeight) * mirroredMove[1]) { // switch vertically because we're closer to the left/right edge signedHeight *= -1; } else { // switch vertically because we're closer to the left/right edge signedWidth *= -1; } } // If we get here, there are no collisions and so any move is fine return(move); }
// Returns the maximum amount of distance that this can move in the move direction, given another rectangle at offset public override double[] moveTo(GameRectangle other, double[] offset, double[] move) { GameRectangle r1 = this; GameRectangle r2 = other; //double length = Math.Sqrt(move[0] * move[0] + move[1] * move[1]); double width = (r1.getWidth() + r2.getWidth()) / 2; double height = (r1.getHeight() + r2.getHeight()) / 2; // if they can't collide in this direction then any length is okay if ((Math.Abs(offset[0]) >= width) && (offset[0] * move[0] <= 0)) { return(move); } if ((Math.Abs(offset[1]) >= height) && (offset[1] * move[1] <= 0)) { return(move); } // figure out if any edges do collide in this direction double dir1 = (width - offset[0]) * move[1] - (height - offset[1]) * move[0]; double dir2 = (width - offset[0]) * move[1] - (-height - offset[1]) * move[0]; double dir3 = (-width - offset[0]) * move[1] - (height - offset[1]) * move[0]; double dir4 = (-width - offset[0]) * move[1] - (-height - offset[1]) * move[0]; // If no edges collide then any length is okay if ((dir1 >= 0) && (dir2 >= 0) && (dir3 >= 0) && (dir4 >= 0)) { return(move); } if ((dir1 <= 0) && (dir2 <= 0) && (dir3 <= 0) && (dir4 <= 0)) { return(move); } double[] allowedMove = new double[2]; // figure out whether the top/bottom edges, or the left/right edges will collide if ((Math.Abs(offset[0]) - width) * Math.Abs(move[1]) <= (Math.Abs(offset[1]) - height) * Math.Abs(move[0])) { // check the top/bottom edges and find the closer collision if (offset[1] > 0) { // make sure it is stable with respect to rounding error allowedMove[1] = Math.Min(offset[1] - height, move[1]); } else { // make sure it is stable with respect to rounding error allowedMove[1] = Math.Max(offset[1] + height, move[1]); } // don't force them to move further than desired if (Math.Abs(allowedMove[1]) >= Math.Abs(move[1])) { return(move); } // The reason for the following check is to make it stable with respect to rounding error. The condition should be always true but in reality may not be if ((Math.Abs(offset[0]) >= width) || (Math.Abs(offset[1]) >= height)) { allowedMove[0] = allowedMove[1] * move[0] / move[1]; } else { allowedMove[0] = -allowedMove[1] * move[0] / move[1]; } } else { // check the left/right edges and find the closer collision if (offset[0] > 0) { // make sure it is stable with respect to rounding error allowedMove[0] = Math.Min(offset[0] - width, move[0]); } else { // make sure it is stable with respect to rounding error allowedMove[0] = Math.Max(offset[0] + width, move[0]); } // don't force them to move further than desired if (Math.Abs(allowedMove[0]) >= Math.Abs(move[0])) { return(move); } // The reason for the following check is to make it stable with respect to rounding error. The condition should be always true but in reality may not be if ((Math.Abs(offset[0]) >= width) || (Math.Abs(offset[1]) >= height)) { allowedMove[1] = allowedMove[0] * move[1] / move[0]; } else { allowedMove[1] = -allowedMove[0] * move[1] / move[0]; } } return(allowedMove); }
public virtual bool intersects(GameRectangle other, double[] offset) { return(false); }
public virtual double[] moveTo(GameRectangle other, double[] offset, double[] move) { return(null); }