Im making an iPhone app where the user draws a line with their finger (the line will be straight line between where the touch began and ended). I also have a ball which will fall and hit the line. What is the best / easiest way of handling the i) drawing, and ii) collisions?
I am completely new to this and open to any ideas or source code.
I have decided to use CoreGraphics to draw the line, and to store the points in cgpoint arrays. Then, I use the parallel distance formula to calculate when the distance of the ball to the line nears zero (funny, it has never equaled zero, even though the timer repeats every 0.01). Then a collision has taken place, and I use simple applied maths vectors to calculate the resultant is the coefficient of restitution is 1
Related
I'm attempting to write a bouncing ball game using flame in flutter. To detect collisions the onCollision and onCollisionStart methods are provided. What I had hoped is that onCollisionStart would give a precise location when two objects first hit each other. However, instead it gives a list of positions indicating where the two objects overlap after the first game-tick when this happens (i.e. onCollisionStart is called at the same time as onCollision, but is not called a second time if the same two objects are still colliding on the next tick).
This is illustrated in the attached picture. The collision points are marked with red dots. If the ball were moving downwards, then the ball would have hit the top of the rectangle and so should bounce upwards. However, if the ball were moving horizontally, then its first point of contact would have been the top left corner of the box, and the ball would bounce upwards and to the left.
If I want to work out correct angle that the ball should fly off, then I would need to do some clever calculations to work out the point that the ball first started hitting the other object (those calculations would depend on the precise shape of the other object). Is there some way to work out the point at which the two objects first started colliding? Thanks
What you usually need for this is the normal of the collision, but unfortunately we don't have that for the collision detection system yet.
We do have it in the raytracing system though, so what you could do is send out a ray and see how it will bounce and then just bounce the ball in the same way.
If you don't want to use raytracing I suggest that you calculate the direction of the ball, which you might already have, but if you don't you can just store the last position and subtract it from the current position.
After that you need to find the normals of the edges where the intersection points are.
Let's say the ball direction vector is v, and the two normal vectors are n1 and n2.
Calculate the dot product (this is build in to the vector_math library) of the ball direction vector and each of the normal vectors:
dot1 = v.dot(n1)
dot2 = v.dot(n2)
Compare the results of the dot products:
If dot1 > 0, n1 is facing the ball.
If dot2 > 0, n2 is facing the ball.
After that you can use v.reflect(nx) to get the direction where your ball should be going (where nx is the normal facing the ball).
Hopefully we'll have this built-in to Flame soon!
Note : I am coding in Unity, using C# script. I cannot use trigger hit detection using Raycasting because there are a lot of trigger colliders in between the target and source which detect touches and the sort. So the ray hits the other triggers before even reaching it's target, which is not desirable.
What I want to accomplish basically is return a boolean value if a vector line crosses or intersects a particular set of vector coordinates or an area.
For example: Detecting a laser entering into a fog in between it's path when shooting at it's target. The fog is a trigger collider based game object.
Edit: Another example would be to check if a line crosses a 2D box area in a 2D graph. Keep in mind, I cannot use collision detection or Raycast hit here.
There is no need for code, just explain the concept of how it could be accomplished. Though a code snippet is also welcome. Thankyou!
[...] So the ray hits the other triggers before even reaching it's target, which is not desirable.
What about putting that on Layers? You can specify LayerMasks for Raycasts.
You could consider the edges of the 2D box as lines i.e 4 lines and check for intersection of a line with these 4 edges using line to line intersection technique. If the line however is small enough to fit inside the box, and you want to treat it as a valid intersection, then check if the two points of the line is inside the bounds of the box.
I have an object in unity which has a rotation described as the following:
x, y, z, where they are both rotations ranging from 0 to 360 around their respective axis.
Now I'm trying to find out which of the vectors point up the most. Essentially I have a 6-sided dice, on which I use physics to emulate a dice-throw. I now want to find out which of the 6 faces of the die points upwards. I can imagine some rather advanced if sentences, revolving around checking the rotations individually, but I'd like to know if there is a good way to do this?
You can get the face directions with:
transform.up
-transform.up
transform.right
-transform.right
transform.forward
-transform.forward
You need to associate each direction with the appropriate face value. The side facing up will be the one with the greatest Dot Product vs Vector3.up (the world "up" direction). A dot product of 1 means a face is pointing directly up. Note that this only works because all the directions are unit vectors.
Vector3.Dot(Vector3.up, transform.up);
Given that it's only 6 (or 3 if you are clever) if statements to find the max that's probably the best way. If you are considering the general case, i.e. to support any die shape and number of faces, you could store a list of structs with a lambda expression denoting the face direction + the face value then use Linq Max().
You could, as you say, check the rotations directly manually.
Here's an alternative collider-based approach: put invisible children game objects with individual trigger colliders on each face of the die, then whenever one of them collides with the table surface, record the number of the opposite side of the face.
Users can sketch in my app using a very simple tool (move mouse while holding LMB). This results in a series of mousemove events and I record the cursor location at each event. The resulting polyline curve tends to be rather dense, with recorded points almost every other pixel. I'd like to smooth this pixelated polyline, but I don't want to smooth intended kinks. So how do I figure out where the kinks are?
The image shows the recorded trail (red pixels) and the 'implied' shape as a human would understand it. People tend to slow down near corners, so there is usually even more noise here than on the straight bits.
Polyline tracker http://www.freeimagehosting.net/uploads/c83c6b462a.png
What you're describing may be related to gesture recognition techniques, so you could search on them for ideas.
The obvious approach is to apply a curve fit, but that will have the effect of smoothing away all the interesting details and kinks. Another approach suggested is to look at speeds and accelerations, but that can get hairy (direction changes can be very fast or very slow and deliberate)
A fairly basic but effective approach is to simplify the samples directly into a polyline.
For example, work your way through the samples (e.g.) from sample 1 to sample 4, and check if all 4 samples lie within a reasonable error of the straight line between 1 & 4. If they do, then extend this to points 1..5 and repeat until such a time as the straight line from the start point to the end point no longer provides a resonable approximation to the curve defined by those samples. Create a line segment up to the previous sample point and start accumulating a new line segment.
You have to be careful about your thresholds when the samples are too close to each other, so you might want to adjust the sensitivity when regarding samples fewer than 4-5 pixels away from each other.
This will give you a set of straight lines that will follow the original path fairly accurately.
If you require additional smoothing, or want to create a scalable vector graphic, then you can then curve-fit from the polyline. First, identify the kinks (the places in your polyline where the angle between one line and the next is sharp - e.g. anything over 140 degrees is considered a smooth curve, anything less than that is considered a kink) and break the polyline at those discontinuities. Then curve-fit each of these sub-sections of the original gesture to smooth them. This will have the effect of smoothing the smooth stuff and sharpening the kinks. (You could go further and insert small smooth corner fillets instead of these sharp joints to reduce the sharpness of the joins)
Brute force, but it may just achieve what you want.
Rather than trying to do this from the resultant data, have you considered looking at the timing of the data as it comes in? If the mouse stops or slows noticably, you use the trend since the last 'kink' (the last time the mouse slowed) to establish the direction of travel. If the user goes off in a new direction, you call it a kink, otherwise, you ignore the current slowing trend and start waiting for the next one.
Well, one way would be to use a true curve-fitting algorithm. Generate a bezier curve (with exact endpoints, using Catmull-Rom or something similar), then optimize & recursively subdivide (using distance from actual line points as a cost metric). This may be too complicated for your use-case, though.
Record the order the pixels are drawn in. Then, compute the slope between pixels that are "near" but not "close". I'm guessing a graph of the slope between pixel(i) and pixel(i+7) might exhibit easily identifable "jumps" around kinks in the curve.
I have a NSArray of points that make up a path. I can detect when it self-intersects. When this happens, I try to fill the path.
First I used CoreGraphics, now I'm using openGl to draw a triangle array. Doesn't work well as you can see in the image.
How do I fill only the circular area while leaving the "tail" alone? I was thinking of a reverse flood fill but don't think CG has any API functions for this...
Maybe instead of actually drawing the path you can just approximate the diameter of the path and draw a circle with your approximation.
Here is some code to detect a circle gesture on the iPhone:
http://www.mobileorchard.com/iphone-circle-gesture-detection/
Record all of the points in a doubly-linked list. When it comes time to fill, walk the list from the start and find the point that's closest to the end. Then, lineto that point, then lineto each point in reverse order, stopping with the second point in the list. The fill will implicitly close the path, which will jump from where you left off (the second point) back to the start (first) point.
This is just off the top of my head; you can play with a couple of variations on this to see what works best. You might record the closest previous node in each node, but this could get expensive for many nodes.