// public PlacementController(MainFrame motherFrame, ProductAdding pa) { this.motherFrame = motherFrame; productAdding = pa; clickLocation = new Point(0, 0); productAdding.productPanel.knowYourController(this); //Make an event when the selection of the ASSORTMENT or INVENTORY has changed productAdding.productList1.SelectionChanged += new ProductSelectionChanged(this.ChangeSelected); //Select the first product from the product list, and display it in the default info try { ProductInfo defaultInfo = new ProductInfo(ProductModel.List[0]); ChangeSelected(defaultInfo); } catch { } //Make an event that triggers when the list is changed, so that it automatically repaints the screen. placedProductList.CollectionChanged += ppList_CollectionChanged; //TEMP //Fill the staticlyplaced list with walls Vector pointTopLeft = new Vector(0, 0); Vector pointTopRight = new Vector(productAdding.productPanel.Width - 1, 0); Vector pointBottomLeft = new Vector(0, productAdding.productPanel.Height - 1); Vector pointBottomRight = new Vector(productAdding.productPanel.Width - 1, productAdding.productPanel.Height - 1); staticlyPlacedObjectList = new List<PlacedProduct>(); int length = (int)(pointBottomRight.Y - pointTopRight.Y); int width = (int)(pointTopRight.X - pointTopLeft.X); staticlyPlacedObjectList.Add( //Top new PlacedProduct( new ProductModel(0, "", "", width, 1, 1, true), new PointF(width / 2, 0))); staticlyPlacedObjectList.Add( //Right new PlacedProduct( new ProductModel(0, "", "", 1, 1, length, true), new PointF(width, length / 2))); staticlyPlacedObjectList.Add( //Bottom new PlacedProduct( new ProductModel(0, "", "", width, 1, 1, true), new PointF(width / 2, length))); staticlyPlacedObjectList.Add( //Left new PlacedProduct( new ProductModel(0, "", "", 1, 1, length, true), new PointF(0, length / 2))); }
public void Offset(float x, float y) { for (int i = 0; i < points.Count; i++) { Vector p = points[i]; points[i] = new Vector(p.X + x, p.Y + y); } }
public float DistanceTo(Vector vector) { return (float)Math.Sqrt(Math.Pow(vector.X - this.X, 2) + Math.Pow(vector.Y - this.Y, 2)); }
public float DotProduct(Vector vector) { return this.X * vector.X + this.Y * vector.Y; }
public bool Equals(Vector v) { return X == v.X && Y == v.Y; }
public void MoveProduct(PlacedProduct selectedProduct, List<PlacedProduct> placedProducts, Vector deltaVector, int panelWidth, int panelHeight) { //A variable to keep track of collision bool collision = false; //The new location that the product is going towards Point newLocationPoint = new Point( (int)(selectedProduct.Location.X + deltaVector.X), (int)(selectedProduct.Location.Y + deltaVector.Y) ); //Checkes the borders foreach (Polygon wall in selectedProduct.PolyBorder(panelWidth, panelHeight)) { PolygonCollisionController.PolygonCollisionResult result = PolygonCollisionController.PolygonCollision(selectedProduct.Poly, wall, deltaVector); if (result.WillIntersect) { collision = true; break; } } //Loops through each item and determines if it collides with any of them foreach (PlacedProduct collisionTarget in placedProducts) { if (collision) { break; } if (selectedProduct.Product.Collidable == false) //If the selected product is not collidable. For example an 'Energy Socket'. Break out the loop and place it. { break; } if (collisionTarget.Product.Collidable == false) //If the target is not collidable. For example an 'Energy Socket'. Skip this loop and go to the next target. { continue; } PolygonCollisionController.PolygonCollisionResult result = PolygonCollisionController.PolygonCollision(selectedProduct.Poly, collisionTarget.Poly, deltaVector); if (result.WillIntersect) { collision = true; break; } } //Failsafe check at the end if (!collision) { /*selectedProduct.MoveTo(newLocationPoint); */} else { MessageBox.Show("Fail"); } MessageBox.Show(newLocationPoint.ToString()); }
/// <summary> /// Moves the product a certain amount to a certain direction /// </summary> /// <param name="X_Axis">Chooses the axis that the product moves on. True for X-axis. False for Y-axis</param> public static void placement_Move(PlacedProduct targetProduct, bool X_Axis) { int x = 0; int y = 0; if (X_Axis) { x += targetProduct.GridSpace; } else { y += targetProduct.GridSpace; } Vector velocity = new Vector(x, y); Vector playerTranslation1 = velocity; Vector playerTranslation2 = velocity; //Resets the speed, after the velocity has been assigned. if (targetProduct.GridSpace < 0) { targetProduct.GridSpace *= -1; } //Test all product polygons for a collision foreach (PlacedProduct placedP in placedProductList) { //Test if the selected polygon is himself if (placedP.Poly == targetProduct.Poly) { continue; } //Test if the polygon collides with others PolygonCollisionController.PolygonCollisionResult r = PolygonCollisionController.PolygonCollision(targetProduct.Poly, placedP.Poly, velocity); //If it does, alter the speed if (r.WillIntersect) { // playerTranslation1 = velocity + r.MinimumTranslationVector; if (X_Axis) //Moving the x-axis, so set the y-axis velocity to 0 { playerTranslation1.Y = 0; } else //Moving the y-axis, so set the x-axis velocity to 0 { playerTranslation1.X = 0; } //If there is any movement along the Y axis while moving along the X axis, then the polygon collision want to move around the other polygon. Can't let that happen. So set all movement to 0. if (X_Axis && r.MinimumTranslationVector.Y != 0) { playerTranslation1.X = 0; playerTranslation1.Y = 0; } if (!X_Axis && r.MinimumTranslationVector.X != 0) { playerTranslation1.X = 0; playerTranslation1.Y = 0; } //Round down to the closest x pixels playerTranslation1.X = ((int)playerTranslation1.X / targetProduct.GridSpace) * targetProduct.GridSpace; playerTranslation1.Y = ((int)playerTranslation1.Y / targetProduct.GridSpace) * targetProduct.GridSpace; //MessageBox.Show("then " + playerTranslation1.X.ToString() + " and " + playerTranslation1.Y.ToString()); break; } } //Test all product polygons for a collision foreach (PlacedProduct placedO in staticlyPlacedObjectList) { //Test if the selected polygon is himself if (placedO.Poly == targetProduct.Poly) { continue; } //Test if the polygon collides with others PolygonCollisionController.PolygonCollisionResult r = PolygonCollisionController.PolygonCollision(targetProduct.Poly, placedO.Poly, velocity); //If it does, alter the speed if (r.WillIntersect) { // playerTranslation2 = velocity + r.MinimumTranslationVector; if (X_Axis) //Moving the x-axis, so set the y-axis velocity to 0 { playerTranslation2.Y = 0; } else //Moving the y-axis, so set the x-axis velocity to 0 { playerTranslation2.X = 0; } //If there is any movement along the Y axis while moving along the X axis, then the polygon collision want to move around the other polygon. Can't let that happen. So set all movement to 0. if (X_Axis && r.MinimumTranslationVector.Y != 0) { playerTranslation2.X = 0; playerTranslation2.Y = 0; } if (!X_Axis && r.MinimumTranslationVector.X != 0) { playerTranslation2.X = 0; playerTranslation2.Y = 0; } //Round down to the closest x pixels playerTranslation2.X = ((int)playerTranslation2.X / targetProduct.GridSpace) * targetProduct.GridSpace; playerTranslation2.Y = ((int)playerTranslation2.Y / targetProduct.GridSpace) * targetProduct.GridSpace; //MessageBox.Show("then " + playerTranslation2.X.ToString() + " and " + playerTranslation2.Y.ToString()); break; } } //Compares the tanslations /* 1. Makes a new vector 2. compares the two, and chooses the highest for the X and the highest for the Y (it looks for the highest number, even when negative. ie. -10 is higher than 4) 3. If one of the two is 0, then set that Axis to 0 */ //1 Vector playerTranslation = new Vector(); //2 playerTranslation.X = Math.Abs(playerTranslation1.X) > Math.Abs(playerTranslation2.X) ? playerTranslation1.X : playerTranslation2.X; playerTranslation.Y = Math.Abs(playerTranslation1.Y) > Math.Abs(playerTranslation2.Y) ? playerTranslation1.Y : playerTranslation2.Y; //3 if (playerTranslation1.X == 0 || playerTranslation2.X == 0) { playerTranslation.X = 0; } if (playerTranslation1.Y == 0 || playerTranslation2.Y == 0) { playerTranslation.Y = 0; } //Set the polygon points targetProduct.Poly.Offset(playerTranslation); //Update the corner points for (int index = 0; index < targetProduct.Poly.Points.Count; index++) { targetProduct.CornerPoints[index] = new PointF(targetProduct.Poly.Points[index].X, targetProduct.Poly.Points[index].Y); } //Update the center point targetProduct.Location = new PointF(targetProduct.Location.X + playerTranslation.X, targetProduct.Location.Y + playerTranslation.Y); }
/// <summary> /// Event that triggers when the dragdrop object is dragged across the screen. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void event_DragOver(object sender, DragEventArgs e) { //If not ProductModel or PlacedProduct, then exit out, because you can only get the location from them if (!(e.Data.GetDataPresent(typeof(ProductModel)) || e.Data.GetDataPresent((typeof(PlacedProduct))))) { draggingItem = false; return; } else { draggingItem = true; } //Gets the location of the mouse inside of the panel Point newLocation = new Point(e.X, e.Y); newLocation = motherFrame.PointToClient(newLocation); newLocation.X -= productAdding.productPanel.Left; newLocation.Y -= productAdding.productPanel.Top; newLocation.Y -= motherFrame.menuStrip1.Height; newLocation.X /= MovementSpeed; newLocation.X *= MovementSpeed; //Round down to the movement speed. (AKA: Fit into the grid) newLocation.Y /= MovementSpeed; newLocation.Y *= MovementSpeed; //Round down to the movement speed. Color drawImageColor; if (e.Data.GetDataPresent(typeof (ProductModel))) { //Make a new model, size and color ProductModel model = (ProductModel)e.Data.GetData(typeof (ProductModel)); drawImageColor = GetMainCategoryColorIfNeeded(model.ProductCategory.CatId); //Colour in the bitmap and resize it. Graphics gfx = Graphics.FromImage(drawImageGhostBitmap); SolidBrush brush = new SolidBrush(Color.FromArgb(128, drawImageColor.R, drawImageColor.G, drawImageColor.B)); gfx.FillRectangle(brush, new Rectangle(new Point(0, 0), new Size(1000,1000))); //Small dispose brush.Dispose(); gfx.Dispose(); //Set the Bitmap and new location drawImageGhostBitmap = new Bitmap(drawImageGhostBitmap, model.Width, model.Length); drawImageGhostPoint = new Point(newLocation.X - model.Width/2, newLocation.Y - model.Length/2); //Calculates the top left point for the Ghost. } else if (e.Data.GetDataPresent(typeof (PlacedProduct))) { //Get the rotated bitmap PlacedProduct placedP = (PlacedProduct)e.Data.GetData(typeof(PlacedProduct)); drawImageGhostBitmap = placedP.RotatedMap; Vector clickOffsetVector = new Vector((clickLocation.X - placedP.Location.X), (clickLocation.Y - placedP.Location.Y)); //Get the click offset if the user clicked the bottom left of the image //Set the new location drawImageGhostPoint = new Point( newLocation.X - drawImageGhostBitmap.Width/2 - (int) clickOffsetVector.X, newLocation.Y - drawImageGhostBitmap.Height/2 - (int) clickOffsetVector.Y); //Calculates the top left point for the Ghost. } //And then repaint the panel DoRepaintWithGhost(); }
// Check if polygon A is going to collide with polygon B for the given velocity public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector velocity) { PolygonCollisionResult result = new PolygonCollisionResult(); result.Intersect = true; result.WillIntersect = true; int edgeCountA = polygonA.Edges.Count; int edgeCountB = polygonB.Edges.Count; float minIntervalDistance = float.PositiveInfinity; Vector translationAxis = new Vector(); Vector edge; // Loop through all the edges of both polygons for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) { if (edgeIndex < edgeCountA) { edge = polygonA.Edges[edgeIndex]; } else { edge = polygonB.Edges[edgeIndex - edgeCountA]; } // ===== 1. Find if the polygons are currently intersecting ===== // Find the axis perpendicular to the current edge Vector axis = new Vector(-edge.Y, edge.X); axis.Normalize(); // Find the projection of the polygon on the current axis float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; ProjectPolygon(axis, polygonA, ref minA, ref maxA); ProjectPolygon(axis, polygonB, ref minB, ref maxB); // Check if the polygon projections are currentlty intersecting if (IntervalDistance(minA, maxA, minB, maxB) > 0) result.Intersect = false; // ===== 2. Now find if the polygons *will* intersect ===== // Project the velocity on the current axis float velocityProjection = axis.DotProduct(velocity); // Get the projection of polygon A during the movement if (velocityProjection < 0) { minA += velocityProjection; } else { maxA += velocityProjection; } // Do the same test as above for the new projection float intervalDistance = IntervalDistance(minA, maxA, minB, maxB); if (intervalDistance > 0) result.WillIntersect = false; // If the polygons are not intersecting and won't intersect, exit the loop if (!result.Intersect && !result.WillIntersect) break; // Check if the current interval distance is the minimum one. If so store // the interval distance and the current distance. // This will be used to calculate the minimum translation vector intervalDistance = Math.Abs(intervalDistance); if (intervalDistance < minIntervalDistance) { minIntervalDistance = intervalDistance; translationAxis = axis; Vector d = polygonA.Center - polygonB.Center; if (d.DotProduct(translationAxis) < 0) translationAxis = -translationAxis; } } // The minimum translation vector can be used to push the polygons appart. // First moves the polygons by their velocity // then move polygonA by MinimumTranslationVector. if (result.WillIntersect) result.MinimumTranslationVector = translationAxis * minIntervalDistance; return result; }
// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval public static void ProjectPolygon(Vector axis, Polygon polygon, ref float min, ref float max) { // To project a point on an axis use the dot product float d = axis.DotProduct(polygon.Points[0]); min = d; max = d; for (int i = 0; i < polygon.Points.Count; i++) { d = polygon.Points[i].DotProduct(axis); if (d < min) { min = d; } else { if (d > max) { max = d; } } } }
//makes the points move. public void Offset(Vector v) { Offset(v.X, v.Y); }
public List<Polygon> PolyBorder(int width, int height) { //List to return List<Polygon> list = new List<Polygon>(); // //Add the 4 corners // Polygon pTop = new Polygon(); Polygon pRight = new Polygon(); Polygon pBottom = new Polygon(); Polygon pLeft = new Polygon(); //Points for corners Vector pointTopLeft = new Vector(0, 0); Vector pointTopRight = new Vector(width, 0); Vector pointBottomLeft = new Vector(0, height); Vector pointBottomRight = new Vector(width, height); //Add points/vectors pTop.Points.Add(pointTopLeft); pTop.Points.Add(pointTopRight); // pRight.Points.Add(pointTopRight); pRight.Points.Add(pointBottomRight); // pBottom.Points.Add(pointBottomRight); pBottom.Points.Add(pointBottomLeft); // pLeft.Points.Add(pointBottomLeft); pLeft.Points.Add(pointTopLeft); //Build edges pTop.BuildEdges(); pRight.BuildEdges(); pBottom.BuildEdges(); pLeft.BuildEdges(); //Add to the list list.Add(pTop); list.Add(pRight); list.Add(pBottom); list.Add(pLeft); return list; }
public Polygon GetVirtualPolygon(Point newLocation) { Polygon virtualPolygon = new Polygon(); foreach (Vector v in Poly.Points) { virtualPolygon.Points.Add(v); } Vector delta = new Vector(new Vector(newLocation) - new Vector(Location)); virtualPolygon.Offset(delta); virtualPolygon.BuildEdges(); return virtualPolygon; }