How to "round" a 2D Vector to nearest 15 degrees - c#

I'm working on a simple game and I'm trying to simplify part of the 2D collision reaction in the game. When certain objects hit walls, I'm calculating a collision normal (collisionPoint - objectCenter) and reflecting based on that normal. I'm interested in rounding that normal vector to its nearest 15° but I'm not sure of a good way to go about that.
My current thought is doing something like this
float angle = atan2(normal.Y, normal.X) * Rad2Deg;
float newAngle = ((int)(angle + 7.5f) / 15) * 15.0f * Deg2Rad;
vector2 newNormal = vector2(cos(newAngle), sin(newAngle));
Is this a reasonable way to do it? Is there a better way?

Try this:
float roundAngle = 15 * Deg2Rad;
float angle = (float)Math.Atan2(normal.Y, normal.X);
Vector2 newNormal;
if (angle % roundAngle != 0)
{
float newAngle = (float)Math.Round(angle / roundAngle) * roundAngle;
newNormal = new Vector2((float)Math.Cos(newAngle), (float)Math.Sin(newAngle));
}
else
{
newNormal = Vector2.Normalize(normal);
}
You don't need to add 7.5, take this example:
// 4 degrees should round to 0
(4 + 7.5) / 15 == 11.5 / 15 == 0.77
// When this gets rounded up to 1 and multiplied by 15 again, it becomes 15 degrees.
// Don't add 7.5, and you get this:
4 / 15 == 0.27
// When rounded, it becomes 0 and, as such the correct answer
// Now how about a negative number; -12
-12 / 15 == -0.8
// Again, when rounded we get the correct number

actually this is more correct if you want the nearest 15 degree angle :
do this:
newangle% = INT(((angle%+7.5)/15)*15)
INT ALWAYS rounds DOWN by default this should properly give you the nearest angle in any case that is positive or negative have fun!!
and add the part where you use degree to rad and rad to degree if needed INSIDE the parens (like right next to angle% if that angle is not given in degrees then use some sort of rad2deg multiplier inside there
this is more like how you would do this in basic, with some modification It will work in c code or such, well good luck!!

Related

How do i convert Floor in excel to Unity Mathf?

How do i convert Floor in excel to Unity Mathf? I have a procedural equations like this in Excel:
= FLOOR(MOD(5, 20) * 0.2, 1)
and i want to convert it to C# Script but i can't. I have already tried:
float test = Mathf.Floor((5 % 20) * (1 / 5));
But it's not what i want. The answer that i want is 1 (Like the result from Excel) but in C# Script it is 0. Please give me some suggestions and thanks for that!
1 / 5
is an integer division with result 0! Therefore
Mathf.Floor((5 % 20) * 0);
is obviously also 0.
You should either use a float division by simply using a float value for at least one of the two operands
1f / 5f
or why not simply directly use the float value
0.2f
so your line should be
float test = Mathf.Floor(5 % 20 * 0.2f);
Note: If you would like to get the result directly as an int value you might want to use Mathf.FloorToInt instead.
Just for completeness: Excel's FLOOR has a second parameter significance
The multiple to which you want to round.
In order to also fake that in your line you would do
var result = Mathf.Floor(5 % 20 * 0.2f / significance) * significance;

Calculate GameObject Damage based on distance

I am trying to get a number that x% between a minimum and a maximum number.
So for example if I have the following:
min = 5;
max = 10;
// `c` is a Collider type
float distance = Vector3.Distance(c.transform.position, transform.position);
float percent = distance / radius;
So now what I am looking for, is when object B is closer to the edge of object A's radius for my final number to be closer to 5. When object B is closer to the center of object A, I would like the final number to be closer to 10.
I have the above so far, but I am not sure what the final formula is to get an Object Damage Amount. Basically think of this a proximity mine, the farther you are away the less damage you will take and the closer you are the more damage you will take.
var result = (1.0f - percent) * (max - min) + min;
just make sure that distance is always <= radius (i.e. percent >= 0.0 and percent <= 1.0)

Randomly pick two numbers in a range so that the sum of their squares is constant

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

2d game vector movement C# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm new in game development and I'm stuck in a problem.
I would like to know the new player position each seconds, here an example :
The player start at (2.5;2.5) and he go to (6.5;3.8).
His velocity is by example 2 units per seconds, and I would like to know the player position after 1sec. So something like this :
What I would like to know it's A every seconds but I don't know at all how I can do that...
I hope you will be able to help me, thanks in advance !
His velocity is by example 2 units per seconds.
I assume, that 'unit' means 'vector of length = 1'.
First of all, you need to calculate the AB vector (movement vector):
mov_vec = [xb-xa, yb-ya] = [6.5 - 2.5, 3.8 - 2.5] = [4, 1.3]
So, we know, that total unit did movement by [4, 1.3]. We need to normalize this vector. Normalized vector (unit vector) 'norm_mov_vec' will be codirectional with 'mov_vec', but it's length will be 1. See this link if you want to know more abut unit vectors.
Compute the length of movement vector:
mov_vec_len = sqrt( 4^2 + 1.3^2 ) ~= 4.2059
Compute normalized vector:
norm_mov_vec = [4/4.2059, 1.3/4.2059] ~= [0.9510, 0.3090]
And that's it. 'norm_mov_vec' is your 'unit-movement-vector', so if player is moving in that direction with speed of N units per second, you can very easily compute it's position after T seconds:
pos_after_T_sec_with_speed_N_units_per_sec = start_pos + ( N * T * norm_mov_vec )
EDIT:
Sample code, using Vector2 type from XNA. Can't test it, but I hope you will get the idea:
//In your case:
//start_pos = 'A' point
//end_pos = 'B' point
//time = number of seconds that elapsed
//speed = number of units per second
Vector2 calculatePosition(ref Vector2 start_pos, ref Vector2 end_pos, Uint32 time, Uint32 speed)
{
Vector2 mov_vec = Vector2.Substract(end_pos, start_pos);
Vector2 norm_mov_vec = Vector2.Normalize(mov_vec);
Vector2 delta_vec = norm_mov_vec * time * speed;
return Vector2.Add(start_pos, delta_vec);
}
First you need to work out the total distance covered, that's your vector. A vector is a movement, not two points in space.
Then you just divide each dimension, x and y in this case, by the time taken to do the move in unit of measurement (seconds) to get the distance per second.
Then you multiply each x and y by the number of seconds from 0, i.e. 1 second in your example, to get the position after 1 second.
I don't know what's available to you in your framework or libraries but a good Vector class will be so helpful, you'll want to be able to do math on the vector instance directly, such as:
Point origin = sprite.Position; // Assumes some sprite object with a position.
Point dest = new Point(200,344); // Destination.
Vector totalTranslation = new Vector(dest.X - origin.X, dest.Y - origin.Y);
Vector perSecond = totalTranslation / 60; // assuming takes a minute to move.
Vector distanceMoved = perSecond * 4; // distance moved after 4 seconds.
Point newPosition = new Point(origin.X + distanceMoved.X, origin.Y + distanceMoved.Y);
sprite.Position = newPosition; // Or using some orchestration class...
spriteManager.Move(sprite, newPosition); // ...like this.
Note being able to divide a vector directly. Else you have to divide each spatial dimension of the vector and make a new vector, or make a helper class to do it.
In real life, you might want to calculate based on milliseconds. I wouldn't use a fixed frame counter since it could look juddery, but work everything out based on a timer.
As I say, a good library or immutable Vector struct/class is the key here. Then its a case of thinking about the problem on graph paper.
Also, build up a palette of small functions you can chain together to do cooler, bigger stuff.
Another interesting problem is using an easing function to work out a coordinate after a given time to achieve the effect of a sprite slowing down as it 'lands'.
This is not programming, but vector math mostly, but anyway:
Your player is moving along the vector BA ( Point B minus Point A ) which is
Direction Vector: ( 4.0 / 1.3 )
This vector has a length of:
SquareRoot(4.0 * 4.0 + 1.3 * 1.3) = 4.2
A vector of the same direction and length of one unit would therefore be the vector with both components divided by the length of 4.2:
Direction Vector of length 1: (0.95 / 0.30)
As your player is fast and moves two units, it would be double length:
Direction Vector of length 2: (1.90 / 0.60)
Now each tick, add 1.90 and 0.60 respectively to your player coordinates, until they equal (roughly) the target coordinates.
x-displacement: 6.5-2.5 = 4
y-displacement: 3.8-2.5 = 1.3
Math.sqrt((4n)(4n)+(1.3n)(1.3n)) = 2
n=2/Math.sqrt(17.69)
x-displacement/second = 4n = 8/Math.sqrt(17.69) = 1.90207
y-displacement/second = 1.3n = 2.6/Math.sqrt(17.69) = 0.61817
so after get these values, it is really easy to calculate the position each second
You can use (as a general solution) these simple trigonometry formulae:
x = A.x + v * cos(fi) * t;
y = B.y + v * sin(fi) * t;
fi = atan2(B.y - A.y, B.x - A.x);
sample solution
// Since there's no common 2d Point double based type,
// let (x, y) point be represented as Tuple<Double, Double>
// where Item1 is x, and Item2 is y
public static Tuple<Double, Double> Move(Tuple<Double, Double> fromPoint,
Tuple<Double, Double> toPoint,
Double velocity,
Double time) {
Double fi = Math.Atan2(toPoint.Item2 - fromPoint.Item2, toPoint.Item1 - fromPoint.Item1);
return new Tuple<Double, Double>(
fromPoint.Item1 + velocity * Math.Cos(fi) * time,
fromPoint.Item2 + velocity * Math.Sin(fi) * time);
}
...
for (int t = 0; t < 10; ++t) {
Tuple<Double, Double> position =
Move(new Tuple<Double, Double>(2.5, 2.5),
new Tuple<Double, Double>(6.5, 3.8),
2.0,
t);
Console.Write("t = ");
Console.Write(t);
Console.Write(" x = ");
Console.Write(position.Item1);
Console.Write(" y = ");
Console.Write(position.Item2);
Console.WriteLine();
}

C# - Why is Math.Atan(1) != anything near 45

There is another post here about Atan but I dont see any relevant answers:
C# - Why Math.Atan(Math.Tan(x)) != x?
Isn't Math.Atan the same as tan-1? On my calculator I do:
tan-1(1) and i get 45.
tan(45) = 1
In C#:
Math.Atan(1) = 0.78539816339744828 //
nowhere near the 45.
Math.Tan(45) = 1.6197751905438615 //1
dp over the < Piover2.
Whats happening here?
C# is treating the angles as radians; your calculator is using degrees.
Atan(1) is equal to π/4. This is the correct value when working in radians. The same can be said of the other calculations in the library.
Feel free to convert the values:
double DegreeToRadian(double angle) { return Math.PI * angle / 180.0; }
double RadianToDegree(double angle) { return angle * (180.0 / Math.PI); }
This means that 45 radians is equal to about 2578.31008 degrees, so the tangent you are looking for should be better expressed as tan(π/4) or if you don't mind "cheating": Math.Tan(Math.Atan(1)); // ~= 1. I'm fairly confident that had you tried that yourself, you'd have realized something reasonable was happening, and might have stumbled upon how radians relate to degrees.
Your calculator is in Degrees, C# is doing these calculations in Radians.
To get the correct values:
int angle = 45; //in degrees
int result = Math.Tan(45 * Math.PI/180);
int aTanResult = Math.Atan(result) *180/Math.PI;
Math.Atan returns a value in radians. Your calculator is using degrees. 0.7853... (pi/4) radians is 45 degrees. (And conversely Math.Tan(45) is telling you the tan of 45 radians.)

Categories