For example, if a moving ball goes beyond the screen, what is the exact method to do it?
I currently do this:
if (x < 0.0) x = screenWidth() - 1;
else if (x >= screenWidth()) x = 0;
// same for y
But I saw this version:
if (x < 0.0) x = x + screenWidth();
else if (x >= screenWidth()) x = x - screenWidth();
// same for y
Isn't the second version doing useless addition/subtraction?
They do slightly different things: one does a cyclic wrapping (the second version) the other one just brings it to the edge (the first version).
Note that the code you are using for the cyclic wrapping may in general be wrong. Consider for example a screen_size = 800; and x = -10000;. Your code will bring it to x = -9200. You probably want to do x = x % screen_size before using your code for the cyclic wrapping, or you could use: ((x % screen_size) + screen_size) % screen_size instead.
In your version you just move the ball to the edge of the screen if it went out of it, but in the other version it keeps the distance that the balls travelled theoretically outside the screen to be considered in its new position. This helps to show the ball as travelling with the same speed.
Related
I'm learning video game design in Kingston University, London, and I'm having an issue with my 2D project. My player character in the project is a sword, that fires smaller daggers towards the cursor, but they appear from the left and right sides of the player character alternating. I want these daggers to always shoot towards the cursor, and appear at the left and right of the player character, no matter its rotation or where the cursor is aiming.
my current code is basically (oversimplified as I don't have it with me).
Dagger = Sword.GetX() + 20
so it takes the player's X coords, adds or subtracts from them, and places a dagger that fires towards the cursor. This presents the issue of them always spawning in the same place, no matter where I am aiming. I want them to dynamically fire from either side of the player character no matter where I aim.
I thought of drawing a line perpendicular to the player character/looking angle and placing the dagger spawns along that, but I'm inept at maths and have no idea of how to do this.
Also sorry if the code baffles you, we are using a custom made game engine called GFC, made by Kingston University.
So you know the coordinates of points A and B and you want to calculate C. With the kind of math you don't know yet but will learn as you make some games, it's reasonably straightforward.
Calculate the direction AB which is (x=B.x-A.x, y=B.y-A.y)
Normalize the AB you just calculated - that is, divide both coordinates by the length (so the length is 1). The length is sqrt(x*x + y*y). If A and B are the same point, this is a divide by zero, which makes sense because there is no right answer, so figure out what you want to do if that happens.
Rotate 90 degrees. The old -x is the new y, and the old y (not -y) is the new x. This is clockwise if X is right and Y is up. If Y is down then it's counter-clockwise. You can reverse the direction by changing which coordinate has a - sign in front of it.
Multiply both x and y by how far away you want C to be from A (for example 20 units).
Add back on point A's coordinates, that we subtracted in step 1. (x += A.x; y += A.y;)
Now you have the coordinates of point C.
In code that might look like this:
float x = B.x-A.x, y = B.y-A.y;
float length = sqrt(x*x + y*y);
if(length < 0.00001) {
// just pick a direction
C.x = A.x + 20;
C.y = A.y;
} else {
x /= length; y /= length;
swap(x, y); y = -y;
x *= 20; y *= 20;
C.x = A.x + x;
C.y = A.y + y;
}
or if you have a vector class with all these functions:
vec2f v = B-A;
if(v.isZero())
C = A + vec2f(20, 0); // just pick a direction
else
C = A + v.normalize().rotate90()*20;
I am currently working on code for use with DWM1000 modules I am using two anchors and one tag I recieve the distance between both anchors to the tag and trying to get the x,y position of the tag. But my x coords for the tag isn't right and seems to be acting like y coord as it changes when i move the tag closer to the anchors I was hoping someone could look at my code and see what I am doing wrong.
float a_r = (pow(-dist_right,2) + pow(dist_left,2) - pow(dist_l_r,2)) / (-2*dist_l_r);
x = dist_l_r/2 - a_r;
float t = pow(dist_right,2) - pow(a_r,2);
if(dist_left < dist_right){
Serial.println("Left");;
}else{
Serial.println("Right");
}
Serial.print("Distance Right: ");Serial.println(dist_right);
Serial.print("Distance Left: ");Serial.println(dist_left);
diff = abs(dist_left - dist_right);
Serial.print("Difference: ");Serial.println(diff);
Serial.print("A_R: ");Serial.println(a_r);
Serial.print("T: ");Serial.println(t);
Serial.print("X: ");Serial.println(x);
Two reference point trilateration yields two solutions - the actual location and a false location. In the case where the reference points form a base line along some impassable barrier such as a wall, then the ambiguity is resolvable by this additional information.
Given:
Attribution: By NavigationGuy - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=75898777
Then
Thus the code:
x = ((dist_left * dist_left) - (dist_right * dist-right) + (dist_l_r * dist_l_r)) /
(2 * dist_l_r) ;
y = sqrt((dist_left * dist_left) - (x * x)) ;
In your code your a_r variable corresponds to x above (my frame of reference is rotated by 90 degrees with respect to yours, but is arbitrary in any case), but your x variable bares no resemblance to y above. Your x variable is proportional to a_r not orthogonal to it, so it is not at all surprising that it varies depending on a_r.
To maintain your frame of reference and variable naming then:
x = sqrt((dist_left * dist_left) - (a_r * a_r)) ;
of if you prefer:
x = sqrt(pow(dist_left,2) - pow(a_r, 2)) ;
I'm trying to make obstacles that stops the player after colliding. Simply, the walls.
I've created collision detection, like this:
if (x > (wall.x1 - wall.boundX) && x < (wall.x + wall.boundX) &&
y >(wall.y1 - wall.boundY) && y < (wall.y + wall.boundY))
{
x = 0;
y = 0;
}
but, as you can see, it just returns my player object to (0,0) on map (by the way, I'm using mouse to control my character). I want it to stop right where he collides and to be unable to move through this wall.
How can I do that?
You will need to separate your if statement to handle each wall separately, and then set the x or y position to the bounds of the wall:
if (x > wall.x1 - wall.boundX)
x = wall.x1 - wall.boundX;
if (x < (wall.x + wall.boundX))
x = wall.x + wall.boundX;
// etc
No matter how far the mouse attempts to move past the bounds of the wall, it will just remain at that position.
Basically what I want to do is illustrated here:
I start with A and B, then B is conformed to A to create C.
The idea is, given TLBR rectangles A, B, make C
I also need to know if it produces an empty rectangle (B outside of A case).
I tried this but it just isn't doing what I want:
if(clipRect.getLeft() > rect.getLeft())
L = clipRect.getLeft();
else
L = rect.getLeft();
if(clipRect.getRight() < rect.getRight())
R = clipRect.getRight();
else
R = rect.getRight();
if(clipRect.getBottom() > rect.getBottom())
B = clipRect.getBottom();
else
B = rect.getBottom();
if(clipRect.getTop() < rect.getTop())
T = clipRect.getTop();
else
T = rect.getTop();
if(L < R && B < T)
{
clipRect = AguiRectangle(0,0,0,0);
}
else
{
clipRect = AguiRectangle::fromTLBR(T,L,B,R);
}
Thanks
You seem to have a mistake in the final condition checking whether or not the intersection rectangle is empty.
You check L < R && B < T, but it seems like the condition for an empty rectangle should be:
L > R || B < T.
By the way, you can make your code a little simpler and easier to read by using Min and Max functions. You have a lot of this pattern:
if (x < y)
a = x;
else
a = y;
Which can be written simply as
a = Min(x, y);
Edit
Another mistake is that you take the maximum bottom and the minimum top. You should be taking the minimum bottom and the maximum top. (Assuming the rectangles correspond to screen coordinates, where the top actuallly has lower y values.
Logically, these are two different problems. I would first write an is_intersected() function returning an appropriate boolean value.
If the rects do intersect, I would then perform a clip operation that resembled the following pseudocode:
C.left.x = max(A.left.x, B.left.x);
C.right.x = min(A.right.x, B.right.x);
C.left.y = max(A.left.y, B.left.y);
C.right.y = min(A.right.y, B.right.y);
I have an algorithm which can find if a point is in a given polygon:
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j, c = 0;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
c = !c;
}
return c;
}
given this, how could I make it check if its within a rectangle defind by Ptopleft and Pbottomright instead of a single point?
Thanks
Basically you know how in Adobe Illustrator you can drag to select all objects that fall within the selection rectangle? well I mean that. –
Can't you just find the minimum and maximum x and y values among the points of the polygon and check to see if any of the values are outside the rectangle's dimensions?
EDIT: duh, I misinterpreted the question. If you want to ensure that the polygon is encosed by a rectangle, do a check for each polygon point. You can do that more cheaply with the minimum/maximum x and y coordinates and checking if that rectangle is within the query rectangle.
EDIT2: Oops, meant horizontal, not vertical edges.
EDIT3: Oops #2, it does handle horizontal edges by avoiding checking edges that are horizontal. If you cross multiply however, you can avoid the special casing as well.
int isPointInRect( Point point, Point ptopleft, Point pbottomright) {
float xp[2] ;
xp[0] = ptopleft.x,
xp[1] = pbottomright.x;
float yp[2] ;
yp[0] = ptopleft.y ;
yp[1] = pbottomright.y ;
return CGlEngineFunctions::PointInPoly(2, xp, yp, point.x, point.y);
}
As mentioned before, for that specific problem, this function is an overkill. However, if you are required to use it, note that:
1. It works only for convex polygons,
2. The arrays holding the polygon's vertices must be sorted such that consecutive points in the array relate to adjacent vertices of your polygon.
3. To work properly, the vertices must be ordered in the "right hand rule" order. That means that when you start "walking" along the edges, you only make left turns.
That said, I think there is an error in the implementation. Instead of:
// c initialized to 0 (false), then...
c = !c;
you should have something like:
// c initialized to 1 (true), then...
// negate your condition:
if ( ! (....))
c = 0;