This is my code so far...
We have the main class, the eye class, the enemy class, the face class, and the message class.
So my question is how do I make a collision, or whatever I have to do for the face class and the enemy class, when they touch the game will stop.
I hope you understand! Anyone help? Appreciate it<3
----------------------------------------------
Here are some leads which might be useful for you.
First you mention a Person class but it is not in the code you shared, so I will assume that you consider an enemy to have touched the person if it touches either the Face or one of the Eyes.
Here according to your display() functions for Enemy, Face and Eye all the objects are some circles (i.e. ellipse() used with the same diameter for both horizontal and vertical diameters). So are you are trying to do is to detect a collision between circles, which is pretty straightforward:
Take two circles with positions (x1, y1) and (x2, y2) and diameters d1 and d2. Those circles are colliding if the distance between their position is less than the sum of their diameter isColliding = dist((x1, y1), (x2, y2)) <= d1 + d2 (if you're not sure it's true you can take a sheet of paper and a pencil and draw circles colliding and not colliding, you should verify this property pretty quickly).
So the first thing you'll need is to write a function which will take four parameters and return a boolean like this:
boolean collideCircles(PVector p1, int d1, PVector p2, int d2)
If you are not familiar with the PVector class have a look at this documentation, this is a way to store your object position components x and y.
In this function you will need to calculate the distance between p1 and p2 which are the position of both of your circles. You can do that with the dist() method of the PVector class and you will need to compare this distance with the sum of the diameters d1 and d2.
Once this function is working you can call it with the objects you need to check for collision (i.e. the 1st eye and all the enemies, the 2nd eye and all the enemies and the face and all the enemies).
Then when this function returns true you'll know that you can stop your game: There are a lot of different ways to do that so it will be up to you to decide which way to go. A first simple way to test is to use noLoop() which stops the processing loop.
The previous part was about the basis of what you need to create, now here are a few advises which might help you:
Once your function collideCircles() is written you could write a new method to the Face class like this boolean collideWithEnemies(Enemy[] enemies) this function would take an array of enemies, it would iterate over this array and call collideCircles() 3 times. p1 and x1 will always be the current enemy and p2, d2 would be successively the position and diameter of each eyes and of the face. You can then call this function from draw() this way at each new frame you will compute your collisions.
As I suggested in the previous point your code would be much easier to use if you used arrays (see the doc) you could use them to store the enemies and the rect() you use in draw() (which I assume are walls)
In every class where you have two properties x and y you could instead use a PVector this is a good habit to take as it will simplify your code and you'll be able to use all the existing methods of the PVector class (to calculate distances, angles and lot of other stuff)
To improve your collideCircles method you could create a class CircularObject which will have only a PVector position and int diameter. The function signature would become boolean collideCicle(CircularObject c1, CircularObject c2). And then you can have your classes Face, Eye and Enemy inheriting from this class (see the doc) and this way you'll be able to call collideCircles directly with your objects like isColliding = collideCircles(face, enemy1)
The function which I described to check for collision works but is inefficient. With a few enemies and two eyes, things should works pretty seamlessly but if your project grows up you will see some slow down. There are a lot of ways to improve that. One simple way to improve the function is to know that the PVector dist() method uses a squared root calculation (because of the formula for the distance between two points, which involves a square root) and this is costly. To avoid this square root calculation you could directly calculate the squared distance between the circles (sqrdDist = (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y)) and check against the squared sum of the diameters of the circles. If you need something even more efficient you'll need to use specific data structures like Quadtrees, but that is not as trivial to use as the method I described before.
Finally your code is badly formatted and that makes it pretty hard to read (your indentations are not consistent, you have a lot of useless empty lines, etc) the IDE or the text editor you are using probably has an auto-formatting feature you should use it you will feel much more comfortable writing and reading your code after that.
One last point: Collision detection in processing is something fairly common and there are a log of resources online you should check here is an example with circles collisions and some additional physics to bounce the balls, the coding train youtube channel has a lot of amazing material about collision and a good search engine should return thousands of relevant material too.
Related
I'm using the centroid of polygons to attach a marker in a map application. This works definitely fine for convex polygons and quite good for many concave polygons.
However, some polygons (banana, donut) obviously don't produce the desired result: The centroid is in these cases outside the polygons area.
Does anybody know a better approach to find a suitable point within any polygons area (which may contain holes!) to attach a marker?
One approach would be to generate and refine a skeleton of the polygon, then use the midpoint of the skeleton to place your marker (and if it's text, to orient the text correctly). This works well for most shapes, including ones with holes, and banana-shaped or tadpole-shaped crescents.
The CGAL library has a 2D Straight Skeleton and Polygon Offsetting module, or you could use PostGIS, for example.
To rephrase comment of ChristopheRoussy we may look for the largest circle inside of the polygon.
The largest circle is the one which cannot grow anymore because it touches three vertices or edges (if it touches only two, it can become bigger or just moved until it touches third).
So if you have few vertices, you can just enumerate all possible triples of vertices/edges, find for each one a circle and then select the largest one.
But it will require creating four functions:
Circle(vertex,vertex,vertex)
Circle(vertex,vertex,edge)
Circle(vertex,edge,edge)
Circle(edge,edge,edge)
All of them are possible, but may require some effort.
Find the extreme ordinates and draw an horizontal line in the middle. It is guaranteed to cross the polygon.
Find the intersection with the sides and sort them by increasing abscissa. Pick a point in the middle of two intersections.
This is an O(N + K Log K) process where K is the number of intersections (usually a very small even number). Pretty straightforward to write.
To increase the chances of a nice placement, you can try three horizontals instead of one an pick the longest intersection segment.
I have no idea how to solve this for any possible shape (and not doing heavy computation), but maybe for simpler shapes like the ones you have shown:
https://en.wikipedia.org/wiki/Force-directed_graph_drawing
Heuristic: This could converge to a reasonable approximation after a while
transform shape border into many points (more = more precise)
start out with many random points inside the polygon
push them until they are furthest away from border points, or just compute distance ... (can be done in parallel)
take best point
Another way could be to use multiple algorithms depending on the nature of the shape (like another one for donuts ...). Also perhaps relying on measuring 'fattest' sections first ?
IMHO would ask this on a math forum.
Similar: Calculate Centroid WITHIN / INSIDE a SpatialPolygon
Similar: How to find two most distant points?
To get a point for a marker I would use Yves Daoust's method.
To get a point that is reliably "within any polygon with holes" I would split polygon into triangles with a reliable library (e.g. OpenGL's GLUtessellator), and then get centroid of triangle with largest area.
If I had time for developing and testing, and I wanted good performance, then I would use a hybrid method: First use Yves Daoust's method to get some candidate points and then test candidates to see if they are within polygon. If all candidates fail, then fall back to slower reliable method (e.g. GLUtesselator).
for (int i = 0; i < n; /*++i*/) {
p = RandomPointInsideConvexHull();
if (IsInsidePolygon(p)) {
++i;
d = DistanceToClosestEdge(p);
if (d > bestD) {
bestP = p;
}
}
}
After running this loop you will approximate solution by bestP. n is parameter to choose. If you want more accurate result you can restart search, but now instead of picking a point inside polygon's convex hull you can pick one in the neighborhood of bestP, say not farther than bestD / 5 (this time you don't need to check if random point is inside polygon).
With an emphasis on finding the time (when the intersection starts), although the position is also important. The bounding boxes (not axis aligned) have a position, rotation, velocity, and angular velocity (rate of rotation). NO accelerations, which should really simplify things... And I could probably remove the angular velocity component as well if necessary. Either a continuous or iterative function would work, but unless the iterative function actively converges toward a solution (or lack thereof), it probably would be too slow.
I looked at the SAT, but it doesn't seem to be built to find the actual time of collision of moving objects. It seems to only work with non-moving snapshots and is designed to work with more complicated objects than rectangles, so it actually seems ill-suited to this problem.
I've considered possibly drawing the trajectory out of each of the 8 points then somehow having a function for if a point is in or out of the other shape and getting a time range of that occurring, but I'm pretty lost on how to go about that. One nice feature would be that it operates entirely with time and ignores the idea of discrete "steps", but it also strikes me as an inefficient approach.
No worries about broad phase (determining if it's worth seeing if these two bounding boxes may overlap), I already have that tackled.
Finding an exact collision time is essentially a nonlinear root-finding problem. This means that you will ultimately need an iterative approach to determine the final collision time -- but the clever bit in designing a collision solver is to avoid the root-solving when it isn't actually necessary...
The SAT is a theorem, not an algorithm: it can be used to guide the design of a collision solver, but it is not one itself. Briefly, it says that, if you can demonstrate a separating axis exists, the objects have not collided. Conversely, if you can show that there is no such axis, then the objects currently do overlap. As you point out, you can use this principle more-or-less directly, to design a binary "yes/no" query as to whether two objects in given positions overlap or not.
The difference with a collision solver is that the problem is animated, or kinetic: object position is a function of time. One way to solve this problem is to start with a valid "yes/no" collision test, treat all the inequalities as functions of time, and use root-finding methods to look for the actual collision times on that basis.
There is a variety of existing methods in published academic literature. I recommend some library research: the best option probably depends on the details of your application.
First of all, instead of thinking of two rectangles moving with speed (x1, y1) and (x2, y2) respectively, you may fix one of them (set its speed to (0, 0) ) and think of another one moving with speed (x2 - x1, y2 - y1).
This way, the situation looks like one rectangle is immovable, and another one is passing by, possibly hitting the first.
Assuming you don't have any angular velocity
Not hard to see, that you can then intersect 4 trajectories of a second rectangle (they are rays starting from different corners of a bounding box in (x2 - x1, y2 - y1) direction) with 4 sides of the first rectangle, standing still. Then you'll have to do the same vice versa - find the intersection of a first rectangle moving in reverse direction - (-(x2 - x1), -(y2 - y1)) with 4 sides of a second rectangle. Choose the minimum distance between the all intersection points you've found (there might be 0-8 of them) and you're done.
Don't forget to consider many special cases - when the sides of both rectangles are parallel, when there's no intersection at all etc.
Note, this all is done in O(1) time, though the calculations are quite complex - 32 intersections of a ray and a segment.
If you really wish your rectangles to rotate with some speed, I would suggest considering what #comingstorm has said: this is a problem of finding roots of a non-linear equation, however, even in such case, if you have a limited angular speed of your rectangles, you may split the task into a series of ternary search subtasks, though I suppose this is just one of possible methods of solving non-linear problems.
I am writing 3D app for OpenGL ES 2.0 where the user sets a path and flies over some terrain. It's basically a flight simulator on rails.
The path is defined by a series of points created from a spline. Every timeslice I advance the current position using interpolation i.e. I interpolate between p0 to p1, then when I reach p1 I interpolate between p1 and p2, then finally back from pN to p0.
I create a view matrix with something analogous to gluLookAt. The eye coord is the current position, the look at is the next position along the path and an up (0, 0, 1). So the camera looks towards where it is flying to next and Z points towards the sky.
But now I want to "bank" as I turn. i.e. the up vector is not necessarily directly straight up but a changes based on the rate of turn. I know my current direction and my last direction so I could increment or decrement the bank by some amount. The dot product would tell me the angle of turn, and the a cross product would tell me if its to the left or right. I could maintain a bank angle and keep it within the range -/+70 degrees, incrementing or decrementing appropriately.
I assume this is the correct approach but I could spend a long time implementing it to find out it isn't.
Am I on the right track and are there samples which demonstrate what I'm attempting to do?
Since you seem to have a nice smooth plane flying in normal conditions you don't need much... You are almost right in your approach and it will look totally natural. All you need is a cross product between 3 sequential points A, B, C: cross = cross(A-B, C-B). Now cross is the vector you need to turn the plane around the "forward" vector: Naturally the plane's up vector is (-gravitation) usually (0,0,1) and forward vector in point B is C-B (if no interpolation is needed) now "side" vector is side = normalized(cross(forward, up)) here is where you use the banking: side = side + cross*planeCorrectionParameter and then up = cross(normalized(side), normalized(forward)). "planeCorrectionParameter" is a parameter you should play with, in reality it would represent some combination of parameters such as dimensions of wings and hull, air density, gravity, speed, mass...
Note that some cross operations above might need swap in parameter order (cross(a,b) should be cross(b,a)) so play around a bit with that.
Your approach sounds correct but it will look unnatural. Take for example a path that looks like a sin function: The plane might be "going" to the left when it's actually going to the right.
I can mention two solutions to your problem. First, you can take the derivative of the spline. I'm assuming your spline is a f(t) function that returns a point (x, y, z). The derivative of a parametric curve is a vector that points to the rotation center: it'll point to the center of a circular path.
A couple of things to note with the above method: the derivative of a straight line is 0, and the vector will also be 0, so you have to fix the up vector manually. Also, you might want to fix this vector so it won't turn upside down.
That works and will look better than your method. But it will still look unnatural for some curves. The best method I can mention is quaternion interpolation, such as Slerp.
At each point of the curve, you also have a "right" vector: the vector that points to the right of the plane. From the curve and this vector, you can calculate the up vector at this point. Then, you use quaternion interpolation to interpolate the up vectors along the curve.
If position and rotation depends only on spline curvature the easiest way will be Numerical differentiation of 3D spline (you will have 2 derivatives one for vertical and one for horizontal components). Your UP and side will be normals to the tangent.
Let's say I have a upright capsule shape (swept sphere) that I would like to cast it along a velocity vector. I would like to be able to find the point of contact and a surface normal for any convex shapes it would intersect along this path. I would also like to find the distance the swept caspule traveled to the point of first contact.
Heres a quick diagram of a capsule being casted against a large convex polyhedra (only one face is drawn)
What kind of algorithm or process could do this? I assume it would be similar to a sphere-cast, but i can't find much on that either.
Since you are considering capsules and convex polyhedra, I suppose you could use something based on GJK. You would get the point of contact and a surface normal during a collision, and the minimum distance between the objects and the associated witness points if there is no collision.
You can also take a look at this publication on Interactive and Continuous Collision Detection for Avatars in Virtual Environments.
Right if its the same as your diagram then finding where it collides is the easy part. Get the circles x and y coordinates and plus '+' the radius of the circle. If that point is at the line of the path then its a collision. The line will have to be found using the line equation here y = mx+c.
The distance can be calculated by setting an intial values of x and y. and then when the object hits set final variables to x and y again. then just the lenght of a line formula to calculate the distance travelled.
The problem is im going on what i know from C++ and i dont know what your programming in.
i think you wanted something else but cant work out what that is from paragraph.
I am making a graphics application in which I can edit a polyline by dragging the control point of it.
However, I'd like to make it a bit easier to use by making it elastic; When dragging a control point, instead of moving a single point, I'd like the points within a certain distance of that point to be moved as well, depending on how hard the control point is 'pulled'.
Does anyone know a simple algorithm for this? It may be quite rudimentary, as the primary requirement is speed.
Actually, knowing how to call such behaviour would also be nice, so I can look it up on google. I tried 'snaking' line, but that seems to refer to active contours, which isn't what I'm looking for.
Thanks
At a simple level you could achieve this with a little help form Hooke's law. You can basically view your polyline as a string, made up of a load of vertices connected by springs:
o-o-o-o-o-o-o-o-o
Each vertex is connected to another vertex by a spring, which will contract if stretched and repel if squashed.
So, when a control point is moved, the connected springs will either expand (stretch) or contract (shrink). This, in turn applies a force to any vertex sharing that spring. So if I pulled the first vertex up and left, the spring would apply a force to the vertex to the right, drawing it closer. This continues to the next (with some energy dissipating) until all springs are 'comfortable'.
That's the basics of it, each time a control point moves you need to solve the equation to all vertices/springs and the points will 'snake' for you.
If you want further examples google for 'Rope Physics' or 'Cloth physics' (as a rope is a 1D cloth). Ignore gravity for your purposes though, obviously.
Basically you are looking for a method to move (deform/transform) multiple points.
Let's assume you have given the direction and strength of the move which would result in dx, dy for the point x, y.
Your transformation will at least two more parameters
The radius r in which the points will be affected
Since the points in the middle would be affected more and at the edge you should define how to interpolate the falloff (linear, normal distribution, etc...)
For linear interpolations the points that are affected would move according to the following formula:
r[i] = sqrt(sqr(x-x[i])+sqr(y-y[i]))
so if r[i] < r
x[i]' = x[i] + dx*(1-r[i]/r)
y[i]' = y[i] + dy*(1-r[i]/r)
this is for linear interpolation dx[i] = dx - r[i]/r