I'm using C# in Unity to make a game with a hexagonal grid. I'm trying to make the map in the shape of a hexagon rather than a rectangle. However, in order to do this with a grid, I need to apply 6 conditions (one for each side) to the rectangular grid to filter out the tiles which don't fall within the space we've determined to be within the hexagon. For instance, using pseudo-code:
foreach(tile in rectangle) { if((y <= 2/3*x + 0.5) && (condition2) && ...) { Debug.Log("It's a tile in the hexagon!") } }
I'm not great at trig, so I've been stumped on how to approach this for a while. In fact, I can't get a single condition down that would define a side of a hexagon (other than the top and the bottom stretches, which are done by default). Any help would be appreciated. Thanks!
(Additional information: the left and right sides are X and are 0.866 apart; top and bottom points are Z and are 1 apart but are fitted such that every other tile in a row is 0.25 closer to its adjacent row.)
I figured it out! I made a perfect hexagon in desmos: https://www.desmos.com/calculator/8tqplz09tt
Then, I converted this to code:
float standardUnitZ = ((mapSize.z * chunkSize.z) - 1f);
float normalUnitZ = standardUnitZ * (13f/15f);
float thisX = ((cz * mapSize.z) + hz);
float sqrt3 = (float)Math.Sqrt(3f);
if (
(theseFinalCoords.z >= (((1 - (13f / 15f)) * normalUnitZ) / 2))//1 BOTTOM
&& (theseFinalCoords.z <= normalUnitZ - (((1 - (13f/15f)) * normalUnitZ) / 2))//2 TOP
&& (theseFinalCoords.z <= sqrt3*thisX + (normalUnitZ / 2f))//3 TOP LEFT
&& (theseFinalCoords.z >= -sqrt3*thisX + (normalUnitZ / 2f))//4 BOTTOM LEFT
&& (theseFinalCoords.z <= -sqrt3*thisX + 2.2320508075f*normalUnitZ)//5 TOP RIGHT
&& (theseFinalCoords.z >= sqrt3*thisX - 1.2320508075*normalUnitZ)//6 BOTTOM RIGHT
)
A little more work to do possibly, but here's the final result:
Related
So, I've been trying to get my character to look where my mouse cursor is, but it's not working and it's very inconsistent. I'm sorry I don't know how to show video.
Here's the code.
if (CanDirectionChange)
{
Direction.x = Input.GetAxisRaw("Horizontal");
Direction.y = Input.GetAxisRaw("Vertical");
Anim.SetFloat("X", MousePos.x);
Anim.SetFloat("Y", MousePos.y);
Anim.SetFloat("Speed", Direction.sqrMagnitude);
if (MousePos.x>=1 || MousePos.x>=-1 || MousePos.y<=1 || MousePos.y<=-1)
{
Anim.SetFloat("LastX", MousePos.x);
Anim.SetFloat("LastY", MousePos.y);
}
}
The Character looks where the LastX and LastY positions are.
Also the Animator looks like this.
I think the problem is in the incredibly confusing if statement.
if ( MousePos.x>=1 || MousePos.x>=-1 || MousePos.y<=1 || MousePos.y<=-1 )
is your current condition, but the Greater than sign is facing the same way both times. Because of the numerous conditions, your code essentially runs like this:
if ( MousePos.x>=1 || MousePos.y<=-1 )
because whenever MousPos.x is is bigger than 1, it is also bigger than -1, and when MousePos.y is smaller than -1 it is also smaller than 1.
Im assuming the function of the if statement is to prevent looking at it when the mouse cursor is close, so the proper way to do that is
float Dist = Mathf.Sqrt(Mathf.Pow((MousePos.x),2) + Mathf.Pow((MousePos.y), 2));
if (Dist >= LookAtDistance)
The reason behind the square roots and exponents is because it is a circle, where as previously it would have a square shaped ignorance range.
If you want your player to ignore the mouse based on a square shape, the code would look like:
if ( MousePos.x>=1 || MousePos.x<=-1 || MousePos.y>=1 || MousePos.y<=-1 )
I'm currently developing a 2-player Ping-Pong game (in 2D - real simple) from scratch, and it's going good. However Theres a problem I just can't seem to solve - I'm not sure if this should be located here or on MathExchange - anyway here goes.
Initially the ball should be located in the center of the canvas. When pressing a button the ball should be fired off in a completely random direction - but always with the same velocity.
The Ball object has (simplified) 4 fields - The position in X and Y, and the velocity in X and Y. This makes it simple to bounce the ball off the walls when it hits, simple by inverting the velocities.
public void Move()
{
if (X - Radius < 0 || X + Radius > GameWidth)
{
XVelocity = -XVelocity;
}
if (Y - Radius < 0 || Y + Radius > GameHeight)
{
YVelocity = -YVelocity;
}
X+= XVelocity;
Y+= YVelocity;
}
I figured the velocity should be the same in each game, so I figures I would use Pythagoras - the square of the two velocities should always be the same.
SO for the question:
Is there a way to randomly select two numbers (doubles) such that the sum of their squares is always a specific number - more formally:
double x = RandomDouble();
double y = RandomDouble();
if (x^2 + y^2 = 16) {/* should always be true */ }
Any help appreciated :)
Randomly pick an angle theta and multiply that by the magnitude of the distance d you want. Something like:
double theta = rand.NextDouble() * 2.0 * Math.PI;
double x = d * Math.Cos(theta);
double y = d * Math.Sin(theta);
If the constant is C, pick a number x between 0 and sqrt(C).
Solve for the other number y using simple algebra.
why not try this:
double x = RandomDouble();
double y = square(16-x^2);
as your application allow double type.
does this solve your problem?
if not, please let me know
I'm trying to find out if a point (mouse click) is within the boundaries of a box based on the top left x/y and bottom right x/y of the box. The position could be positive or negative. As you move up, y value increases, as you move down, y decreases. As you move right, x value increases, as you move left, x decreases.
Vector2 positions could be negative or positive depending on where is clicked.
I thought this would simply work but it doesn't seem to like negative numbers. Any suggestions? My brain is fried tonight after doing Vector arithmetic all night on other things. I wish I was one of you who seem to understand this without problem. ;)
if(point.x >= topLeft.x && point.y <= topLeft.y &&
point.x <= bottomRight.x && point.y >= bottomRight.y)
{
// is within box
}
Edit
Here is how the top left and bottom right are calculated. As it turns out, the problem was not with the above but rather I forgot to add the position.y to the top left calculation below.
Vector2 topLeft = new Vector2(transform.position.x - (transform.localScale.x/2),
transform.position.y + (transform.localScale.y/2));
Vector2 bottomRight = new Vector2(transform.position.x + (transform.localScale.x/2),
transform.position.y - (transform.localScale.y/2));
For anyone coming across this thread, the above check is correct.
Example 1:
Example 2:
I think you've wrongly inverted the boolean expression. It's easier to check for all cases where the click is outside the box.
Semantically, a certain point is outside of a rectangle if it is:
Higher than the highest point of the rectangle
Lower than the lowestpoint of the rectangle
More left than the left side of the rectangle
More right than the right side of the rectangle
If one of these is true, it's outside the box.
if(
clickPosition.x < topLeft.x
||
clickPosition.x > bottomRight.x
||
clickPosition.y < bottomRight.y
||
clickPosition.y > topLeft.y
)
{
//Now you're sure the click was outside the box.
}
Why not using a Rectangle and then check if it contains the point?
var rectangle = new Rectangle(-100,0,100,-100);
if(rectangle.Contains(-25,-25))
{
// is within box
}
For the rest, it appears your code should work. Then there may be a problem with the the assignment of the values of point, topLeft and bottomRight.
the problem with the negative numbers is that your top left isn't your top left
if you say
topY = max(corner1y, corner2y, corner3y)
bottomY = min (corner1y, corner2y, corner3y)
after that your check will work fine again.
I believe you're using the wrong signs on the Y checks.
If your topleft is 50, 100 and the bottom right is 100, 50, then 80 (y) still must be between 50 and 100, it doesn't matter which direction your Y is moving in relation to the screen, as long as you're also inverting your definition of top left.
if(point.x >= topLeft.x && point.y >= topLeft.y && //flipped sign in the second condition
point.x <= bottomRight.x && point.y <= bottomRight.y) //flipped sign in the second condition
{
// is within box
}
If you're not inverting your definition of top left, your original code is correct even for negative numbers.
I'm working on an assignment for uni where I have to create a Breakout game in Visual Studio 2010 using C# Win Forms. At the moment, I am concentrating on there being only one brick to be destroyed so I have the mechanics down before expanding on it.
To clarify about my current program: I am using a picture box as a Graphics object and a timer to create the animation effect. The ball can skip, at each frame, between 1 and 10 pixels — this is part of creating a random starting vector for the ball.
This works fine until it comes to checking if the ball has 'hit' the brick I have drawn. What I have is an if statement that checks if the ball is at any of the coordinates on the picture box that corresponds to the outline of the brick. I know that the logic is fine because it works some of the time. However, because of the variation in the 'jumping' of the ball's position, I need to add a buffer area of +/- 5 pixels to my if statement.
This is where the problem arises, because my if statement (two, really) is really complicated as it is:
// Checks if ball hits left side or top of brick
if (((x >= brickX) && (x <= (brickX + 50)) && (y == brickY)) ||
((y >= brickY) && (y <= (brickY + 20)) && (x == brickX)))
{
brickHit = true;
}
// Check if ball hits right side or bottom of brick
else if ((((x >= brickX) && (x <= brickX + 50)) && (y == (brickY + 20))) ||
(((y >= brickY) && (y <= brickY + 20)) && (x == brickX + 50)))
{
brickHit = true;
}
For clarification: x and y are the coordinates of the ball and brickX and brickY are the coordinates of the top-left corner of the rectangle brick (which is 50 pixels wide, 10 pixels high).
Is there any way to simplify the above if statements? If I can make them simpler, I know it'll be much easier to add in the 'buffer' (which only needs to be 5 pixels either side of the brick's outline' to allow for the ball's change in position).
If further clarification is needed, please ask — I'm writing this question at 5:12am so I know I might be a little unclear.
One way you could possible simplify this (and I may be misunderstanding your spec), but you can make a Rectangle out of the bounds of the brick and check the Contains for your x,y point.
Rectangle rec = new Rectangle(brickX, brickY, 50, 20);
rec.Offset(-5, -5);
rec.Inflate(10, 10);
if (rec.Contains(new Point(x,y))
{
brickHit = true;
}
brickHit = new Rectangle(brickX,brickY,50,20).Contains(x,y);
Adding a buffer:
int buffer = 5;
brickHit = new Rectangle(brickX,brickY,50,20).Inflate(buffer,buffer).Contains(x,y);
The Rectagle class can come in handy sometimes.
This worked for me:
var rect1 = new System.Drawing.Rectangle(pictureBox1.Location,
pictureBox1.Size);
var rect2 = new System.Drawing.Rectangle(pictureBox2.Location,
pictureBox2.Size);
if (rect1.IntersectsWith(rect2))
{
//code when collided
}
I have a question very similar to this:
How to know if a line intersects a plane in C#?
I am searching for a method (in C#) that tells if a line is intersecting an arbitrary polygon.
I think the algorithm by Chris Marasti-Georg was very helpful, but missing the most important method, i.e. line to line intersection.
Does anyone know of a line intersection method to complete Chris Marasti-Georg's code or have anything similar?
Is there a built-in code for this in C#?
This method is for use with the Bing Maps algorithm enhanced with a forbidden area feature. The resulting path must not pass through the forbidden area (the arbitrary polygon).
There is no builtin code for edge detection built into the .NET framework.
Here's code (ported to C#) that does what you need (the actual algorithm is found at comp.graphics.algorithms on Google groups) :
public static PointF FindLineIntersection(PointF start1, PointF end1, PointF start2, PointF end2)
{
float denom = ((end1.X - start1.X) * (end2.Y - start2.Y)) - ((end1.Y - start1.Y) * (end2.X - start2.X));
// AB & CD are parallel
if (denom == 0)
return PointF.Empty;
float numer = ((start1.Y - start2.Y) * (end2.X - start2.X)) - ((start1.X - start2.X) * (end2.Y - start2.Y));
float r = numer / denom;
float numer2 = ((start1.Y - start2.Y) * (end1.X - start1.X)) - ((start1.X - start2.X) * (end1.Y - start1.Y));
float s = numer2 / denom;
if ((r < 0 || r > 1) || (s < 0 || s > 1))
return PointF.Empty;
// Find intersection point
PointF result = new PointF();
result.X = start1.X + (r * (end1.X - start1.X));
result.Y = start1.Y + (r * (end1.Y - start1.Y));
return result;
}
Slightly off topic, but if the line is infinite I think there's a much simpler solution:
The line does not go through the polygon if all the point lie on the same side of the line.
With help from these two:
Using linq or otherwise, how do check if all list items have the same value and return it, or return an “otherValue” if they don’t?
Determine which side of a line a point lies
I got this little gem:
public class PointsAndLines
{
public static bool IsOutside(Point lineP1, Point lineP2, IEnumerable<Point> region)
{
if (region == null || !region.Any()) return true;
var side = GetSide(lineP1, lineP2, region.First());
return
side == 0
? false
: region.All(x => GetSide(lineP1, lineP2, x) == side);
}
public static int GetSide(Point lineP1, Point lineP2, Point queryP)
{
return Math.Sign((lineP2.X - lineP1.X) * (queryP.Y - lineP1.Y) - (lineP2.Y - lineP1.Y) * (queryP.X - lineP1.X));
}
}
To detect collisions between polygons in our silverlight map project, we're using clipper library:
Free for commercial use, small size, great performance and very easy to use.
Clipper webpage
This article looks like it will help
http://www.codeproject.com/KB/recipes/2dpolyclip.aspx
This code is a two-dimensional polygon-clipping algorithm that determines precisely where a line intersects with a polygon border. This code works for both concave and convex polygons of completely arbitrary shape and is able to handle any line orientation.