Colliding with obstacles on a map - c++

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.

Related

C++ shooting towards the cursor from points that move around the player

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;

How to wrap x and y around the screen?

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.

Path-finding algorithm for a game

I have this assigment in university where I'm given the code of a C++ game involving pathfinding. The pathfinding is made using a wave function and the assigment requires me to make a certain change to the way pathfinding works.
The assigment requires the pathfinding to always choose the path farthest away from any object other than clear space. Like shown here:
And here's the result I've gotten so far:
Below I've posted the part of the Update function concerning pathfinding as I'm pretty sure that's where I'll have to make a change.
for (int y = 0, o = 0; y < LEVEL_HEIGHT; y++) {
for (int x = 0; x < LEVEL_WIDTH; x++, o++) {
int nCost = !bricks[o].type;
if (nCost) {
for (int j = 0; j < 4; j++)
{
int dx = s_directions[j][0], dy = s_directions[j][1];
if ((y == 0 && dy < 0)
|| (y == LEVEL_HEIGHT - 1 && dy > 0)
|| (x == 0 && dx < 0)
|| (x == LEVEL_WIDTH - 1 && dx > 0)
|| bricks[o + dy * LEVEL_WIDTH + dx].type)
{
nCost = 2;
break;
}
}
}
pfWayCost[o] = (float)nCost;
}
}
Also here is the Wave function if needed for further clarity on the problem.
I'd be very grateful for any ideas on how to proceed, since I've been struggling with this for quite some time now.
Your problem can be reduced to a problem known as minimum-bottle-neck-spanning-tree.
For the reduction do the following:
calculate the costs for every point/cell in space as the minimal distance to an object.
make a graph were edges correspond to the points in the space and the weights of the edges are the costs calculated in the prior step. The vertices of the graph corresponds to the boundaries between cell.
For one dimensional space with 4 cells with costs 10, 20, 3, 5:
|10|20|3|5|
the graph would look like:
A--(w=10)--B--(w=20)--C--(w=3)--D--(w=5)--E
With nodes A-E corresponding to the boundaries of the cells.
run for example the Prim's algorithm to find the MST. You are looking for the direct way from the entry point (in the example above A) to the exit point (E) in the resulting tree.

Error in checking for if mouse is in tolerance

I have a rect, which I want to disappear when it's getting clicked.
I use the following method to control if the mouseX and height*0.9 is in the area of the rectangle when clicked:
//balken is a ArrayList of the object holding the variables for the rectangle
boolean mouseInTolerance()
{
return ((mouseX > balken.get(0).x- balken.get (0).balkenWidth*.5
|| mouseX < balken.get(0).x+ balken.get (0).balkenWidth*.5)
&& (height*.9 > balken.get(0).y- tolerance
|| height*.9 <balken.get(0).y+ tolerance));
However, this returns true no matter where the mouse has been clicked.
Edit: rectMode is set to CENTER
Let's consider this line:
return ((mouseX > balken.get(0).x- balken.get (0).balkenWidth*.5
|| mouseX < balken.get(0).x+ balken.get (0).balkenWidth*.5)
&& (height*.9 > balken.get(0).y- tolerance
|| height*.9 <balken.get(0).y+ tolerance));
Now let's substitute in a value for your variables, just to more easily see what's going on. It doesn't really matter what values we choose, so let's go with these:
balken.get(0).x = 100;
balken.get(0).y = 200;
balken.get(0).balkenWidth = 20;
balken.get(0).balkenHeight = 30;
height = 1000;
tolerance = 10;
Doing the substitution, you get this:
return (mouseX > 90 || mouseX < 110)
&& (900 > 190 || 900 < 210);
Now let's take each half of that:
(mouseX > 90 || mouseX < 110)
When will that ever be false? Can you come up with a number for mouseX that makes this false? It looks like you were trying to determine when mouseX was between these two points, right? Therefore, you want and between these two inequalities, not or.
Similarly:
(900 > 190 || 900 < 210)
You can change that 900 to any value, and this will never be false. Again, you want an and operator in there, not an or.
The reason for this is simple. Let's say we have three X values: LEFT, MIDDLE, and RIGHT. How do we determine when the MIDDLE point is between the LEFT point and the RIGHT point? The MIDDLE point has to be to the right of the LEFT point- in other words, MIDDLE > LEFT. It also has to be to the left of the RIGHT point- in other words, MIDDLE > LEFT && MIDDLE < RIGHT.
The same logic applies to the vertical y value.

Polygon in rectangle algorithm?

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;