Some help would be most appreciated. Sprite movement based upon a heading that is given from a touch on the screen. Sprite moves as expected but I am unable to vary the speed, no matter what value I use for currentSpeed. This is in the update method of the sprite. Thanks in advance.
// Distance between two points (Distance formula, Pythagorean Theorem c^2=a^2+b^2, so d=sqrt((x2-x1)^2+(y2-y1)^2)
// Duration (time = distance / rate)
CGPoint adjustedPosition;
adjustedPosition.x = position_.x - sinf(heading);
adjustedPosition.y = position_.y - cosf(heading);
float distance = CGPointDistanceBetweenTwoPoints(adjustedPosition, position_);
float duration = distance / currentSpeed;
position_ = adjustedPosition;
[self runAction:[CCMoveTo actionWithDuration:duration position:position_]];
dont use a moveto or for that matter any action in an update method. Instead, compute the position , something like this:
-(void) update:(ccTime) dt {
// _velocity in points per second.
// heading should be in ccw notation, 0 on x axis, RHS
float deltaX = dt * _velocity * cosf(heading);
float deltaY = dt * _velocity * sinf(heading);
CGPoint adjustedPosition = ccpAdd(self.position, ccp(deltaX,deltaY));
self.position = adjustedPosition;
}
or something similar. This will ease out any variance id dt, for which the only thing you can bet on is that it wont be constant ; but the physics should be right.
Try this for distance:
float distance = ccpLength(ccpSub(adjustedPosition, position_));
Related
Essentially I'm trying to calculate the bisector line between two points. I've got two methods, one works the other doesn't. I can't quite figure out why the other one doesn't work. The one that works is a little more computationally intensive and since this routine is run a lot, I'd like to use the simpler one... except it doesn't work. I'm probably missing something simple but I find this amusing since I seem to have a better grasp of trig than I do of high school algebra.
Note: the function is passed the end points (endPoint1, endPoint2).
Here's the one that works (using trig to calculate the bisector):
CGPoint midPoint = CGPointMake((endPoint1.x + endPoint2.x) / 2, (endPoint1.y + endPoint2.y) / 2);
//Normalize an end point
CGPoint nPoint = CGPointMake(endPoint1.x - endPoint2.x, endPoint1.y - endPoint2.y);
//Find theta and rotate 90°
CGFloat theta = atanf(nPoint.y / nPoint.x);
if (nPoint.x < 0.0f) theta += M_PI;
else if (nPoint.x > 0.0f && nPoint.y < 0.0f) theta += (M_PI * 2);
theta += M_PI_2;
//Calculate another point along new theta and de-normalize the point
CGPoint centerPoint = CGPointMake(cosf(theta) * 10, sinf(theta) * 10);
centerPoint.x += midPoint.x;
centerPoint.y += midPoint.y;
//Create the line definition
LineDef def = LineDefForPoints(midPoint, centerPoint);
Here's the one that doesn't, but I'd like it to:
CGPoint midPoint = CGPointMake((endPoint1.x + endPoint2.x) / 2, (endPoint1.y + endPoint2.y) / 2);
//Calculate the slope and invert
CGFloat m = (endPoint1.y - endPoint2.y) / (endPoint1.x - endPoint2.x);
//Take the negative reciprocal
m = -1/m;
//Calculate another point on the line
CGPoint centerPoint = CGPointMake(midPoint.x + 10, midPoint.y + (m * 10));
//Create the line definition
LineDef def = LineDefForPoints(midPoint, centerPoint);
So I'd swear this should work. The change in Y is equal to m times the change in x. I've calculated the mid point, figured out the slope of the perpendicular line and calculated another point on that line. However the line definitions created aren't equivalent when given the same end points, so I'm missing something.
By the way, LindeDef is a simple struct with three CGFloat variables for the a, b & c components of a straight line. And creating a LineDef from two points is trivial (I happen to be using a block to do this):
LineDef (^LineDefForPoints)(CGPoint, CGPoint) = ^LineDef(CGPoint p1, CGPoint p2){
LineDef line = {0,0,0};
line.a = p2.y - p1.y;
line.b = p1.x - p2.x;
line.c = line.a*p1.x + line.b*p1.y;
return line;
};
Slope-intercept form is fragile for this; use vectors.
〈V〉 = B - A
midpoint = 〈V〉/2 + A
⟂〈V〉 = 〈Vy, -Vx〉
Dammit, it was something simple. I reformatted my actual production code so I could put it on Stack Exchange and in the process edited out my mistake. The code I posted in the question actually works perfectly. Originally the line: m = -1 / m; was folded into the original assignment like so: CGFloat m = -1 / (endPoint1.y - endPoint2.y) / (endPoint1.x - endPoint2.x);. Of course, now the problem is obvious...I forgot parenthesis. I separated the line into two in stack exchange so I could explain my 'reasoning' in the comments, hoping to find the problem.
Sorry, for all the trouble.
I'm creating a game that uses trigonometry to calculate and display distance and degrees in dynamic text boxes. I'm calculating the distance of my cursor from center of a movie clip. And using that center of the movie clip, I'm trying to calculate and display a full 360º as my cursor moves around the swf. I have the distance part of the game working but the part that displays degrees is not working properly. The dynamic text box only display from 90º thru 270º. Instead of going past 270º to 360º/0º to 90º, it just counts back down from 270º to 90º. Below is my actionscript. I'd greatly appreciate any help or suggestions. Thanks!
//Mouse and Dynamic Text Boxes-------------------------
Mouse.hide();
onMouseMove = function () {
feedback.text = "You are moving your mouse";
cursor._x = _xmouse;
cursor._y = _ymouse;
updateAfterEvent();
xmouse_value.text = Math.atan2((a), (b));
ymouse_value.text = Math.round(radians*180/Math.PI)
updateAfterEvent();
};
Mouse.addListener(myListener);
//distance (RANGE)
_root.onEnterFrame = function () {
xmid = Stage.width/2;
ymid = Stage.height/2;
a = _root._ymouse-ymid;
b = _root._xmouse-xmid;
c = Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2));
feedbacka.text = Math.round(a);
feedbackb.text = Math.round(b);
feedbackc.text = Math.round(c/30.4);
updateAfterEvent();
var radians:Number;
var degrees:Number;
//Calculcate Radians
//Radians specify an angle by measuring the length around the path of the circle.
radians = Math.atan2((c), (b))
//calculate degrees
//the angle the circle is in relation to the center point
//update text box inside circle
radians_txt = Math.round(radians*360/Math.PI);
degrees_txt = Math.round(radians*180/Math.PI);
updateAfterEvent();
//getting past 270 degrees
radians2_txt = Math.round(radians/Math.PI);
radians2_txt = Math.floor(radians + -270);
}
The parameters to atan2 should be the delta-y and delta-x between the two points, but you are passing the distance between the two points and the delta-x. Try this instead:
radians = Math.atan2(a, b);
The next problem is to convert the radians into degrees. To convert radians to degrees, you can do this:
degrees_txt = radians * 180 / Math.PI;
Note that atan2 returns from between -Math.PI / 2 to Math.PI / 2. When converted to degrees, this range becomes -180 to 180. To convert to 0 to 360, you can add 360 to the result if it is negative:
if(degrees_txt < 0) degrees_txt += 360;
I'm building a cocos2d iPhone game with lots of bullets and moving enemies and I'm detecting collisions between them. Every sprite can be represented by a circle for collision purposes. I'm considering the following options:
1) Simple Sphere Detection
I detect like this at regular intervals:
-(BOOL) isCollidingSphere:(CCSpriteExt*) obj1 WithSphere:(CCSprite *) obj2
{
float minDistance = obj1.radius + obj2.radius;
float dx = obj2.position.x - obj1.position.x;
float dy = obj2.position.y - obj1.position.y;
if (! (dx > minDistance || dy > minDistance) )
{
float actualDistance = sqrt( dx * dx + dy * dy );
return (actualDistance <= minDistance);
}
return NO;
}
2) Box2d for collision detection only
I create a Box2d body for all sprites as shown in this tutorial: http://www.raywenderlich.com/606/how-to-use-box2d-for-just-collision-detection-with-cocos2d-iphone
My question is simple: If my priority is optimisation, which approach is faster?
Thanks!
If all you need is distance/radius based collision checks, you don't need a physics engine.
You should get rid of the sqrt though. First of all, you're using the square root function that works on doubles. For the float version use sqrtf.
To get rid entirely of the square root, make sure your objects store their radius squared (radiusSquared = radius * radius). That way you don't have to take the square root anymore:
-(BOOL) isCollidingSphere:(CCSpriteExt*) obj1 WithSphere:(CCSprite *) obj2
{
float r1 = obj1.radius;
float r2 = obj2.radius;
float minDistanceSquared = r1 * r1 + r2 * r2 + 2 * r1 * r2;
float dx = obj2.position.x - obj1.position.x;
float dy = obj2.position.y - obj1.position.y;
float actualDistanceSquared = dx * dx + dy * dy;
return (actualDistanceSquared <= minDistanceSquared);
}
Let me just start with the code.
- (NSPoint*) pointFromPoint:(NSPoint*)point withDistance:(float)distance towardAngle:(float)angle; {
float newX = distance * cos(angle);
float newY = distance * sin(angle);
NSPoint * anNSPoint;
anNSPoint.x = newX;
anNSPoint.y = newY;
return thePoint;
}
This should, based on my knowledge, be perfect. It should return and x value of 0 and a y value of 2 if I call this code.
somePoint = [NSPoint pointFromPoint:somePoint withDistance:2 towardAngle:90];
Instead, I get and x value of 1.05 and a y of 1.70. How can I find the x and y coordinates based on an angle and a distance?
Additional note: I have looked on math.stackexchange.com, but the formulas there led me to this. I need the code, not the normal math because I know I will probably screw this up.
A working version of your function, which accepts values in degrees instead of radians, would look like this:
- (NSPoint)pointFromPoint:(NSPoint)origin withDistance:(float)distance towardAngle:(float)angle
{
double radAngle = angle * M_PI / 180.0;
return NSMakePoint(origin.x + distance * cos(radAngle), point.y + distance * sin(radAngle));
}
Your problem is you're giving the angle in degrees (e.g. 90), but the math is expecting it in radians. Try replacing the 90 with M_PI_2
I have some problems figuring out where my error is. I got the following:
Have an image and corresponding GPS coordinates of its top-left and bottom-right vertices.
E.g:
topLeft.longitude = 8.235128;
topLeft.latitude = 49.632383;
bottomRight.longitude = 8.240547;
bottomRight.latitude = 49.629808;
Now a have an Point that lies in that map:
p.longitude = 8.238567;
p.latitude = 49.630664;
I draw my image in landscape fullscreen (1024*748).
Now I want to calculate the exact Pixel position (x,y) of my point.
For doing that I am trying to use the great circle distance approach from here: Link.
CGFloat DegreesToRadians(CGFloat degrees)
{
return degrees * M_PI / 180;
};
- (float) calculateDistanceP1:(CLLocationCoordinate2D)p1 andP2:(CLLocationCoordinate2D)p2 {
double circumference = 40000.0; // Erdumfang in km am Äquator
double distance = 0.0;
double latitude1Rad = DegreesToRadians(p1.latitude);
double longitude1Rad = DegreesToRadians(p1.longitude);
double latititude2Rad = DegreesToRadians(p2.latitude);
double longitude2Rad = DegreesToRadians(p2.longitude);
double logitudeDiff = fabs(longitude1Rad - longitude2Rad);
if (logitudeDiff > M_PI)
{
logitudeDiff = 2.0 * M_PI - logitudeDiff;
}
double angleCalculation =
acos(sin(latititude2Rad) * sin(latitude1Rad) + cos(latititude2Rad) * cos(latitude1Rad) * cos(logitudeDiff));
distance = circumference * angleCalculation / (2.0 * M_PI);
NSLog(#"%f",distance);
return distance;
}
Here is my code for getting the Pixel position:
- (CGPoint) calculatePoint:(CLLocationCoordinate2D)point {
float x_coord;
float y_coord;
CLLocationCoordinate2D x1;
CLLocationCoordinate2D x2;
x1.longitude = p.longitude;
x1.latitude = topLeft.latitude;
x2.longitude = p.longitude;
x2.latitude = bottomRight.latitude;
CLLocationCoordinate2D y1;
CLLocationCoordinate2D y2;
y1.longitude = topLeft.longitude;
y1.latitude = p.latitude;
y2.longitude = bottomRight.longitude;
y2.latitude = p.latitude;
float distanceX = [self calculateDistanceP1:x1 andP2:x2];
float distanceY = [self calculateDistanceP1:y1 andP2:y2];
float distancePX = [self calculateDistanceP1:x1 andP2:p];
float distancePY = [self calculateDistanceP1:y1 andP2:p];
x_coord = fabs(distancePX * (1024 / distanceX))-1;
y_coord = fabs(distancePY * (748 / distanceY))-1;
return CGPointMake(x_coord,y_coord);
}
x1 and x2 are the points on the longitude of p and with latitude of topLeft and bottomRight.
y1 and y2 are the points on the latitude of p and with longitude of topLeft and bottomRight.
So I got the distance between left and right on longitude of p and distance between top and bottom on latitude of p. (Needed for calculate the pixel position)
Now I calculate the distance between x1 and p (my distance between x_0 and x_p) after that I calculate the distance between y1 and p (distance between y_0 and y_p)
Last but not least the Pixel position is calculated and returned.
The Result is, that my point is on the red and NOT on the blue position:
Maybe you find any mistakes or have any suggestions for improving the accuracy.
Maybe I didn't understand your question, but shouldn't you be using the Converting Map Coordinates methods of MKMapView?
See this image
I used your co-ordinates, and simply did the following:
x_coord = 1024 * (p.longitude - topLeft.longitude)/(bottomRight.longitude - topLeft.longitude);
y_coord = 748 - (748 * (p.latitude - bottomRight.latitude)/(topLeft.latitude - bottomRight.latitude));
The red dot markes this point. For such small distances you don't really need to use great circles, and your rounding errors will be making things much more inaccurate