Check Rotation in iphone SDk - iphone

In my app, i used SMRotatory wheel for rotation. It is working fine as rotation regarding.
But i want to detect that rotation is clockwise or anti-clockwise??
//My code is as follow:
- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
{
CGFloat radians = atan2f(container.transform.b, container.transform.a);
// NSLog(#"rad is %f", radians);
CGPoint pt = [touch locationInView:self];
float dx = pt.x - container.center.x;
float dy = pt.y - container.center.y;
float ang = atan2(dy,dx);
float angleDifference = deltaAngle - ang;
// NSLog(#"%f",angleDifference);
if (angleDifference>=0) {
//NSLog(#"positive");
[[NSUserDefaults standardUserDefaults]setValue:#"positive" forKey:#"CheckValue"];
}
else
{
// NSLog(#"negative");
[[NSUserDefaults standardUserDefaults]setValue:#"negative" forKey:#"CheckValue"];
}
container.transform = CGAffineTransformRotate(startTransform, -angleDifference);
bg.transform=CGAffineTransformRotate(startTransform, -angleDifference);
return YES;
}

Try something like this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentTouch1=[touch locationInView:self.superview];
CGPoint currentTouch2=[touch previousLocationInView:self.superview];
CGFloat x = currentTouch2.x - currentTouch1.x;
CGFloat y = currentTouch2.y - currentTouch1.y;
CGFloat dist = sqrtf(x*x + y*y);
CGFloat cx = currentTouch1.x - self.superview.bounds.size.width / 2;
CGFloat cy = currentTouch2.y - self.superview.bounds.size.height / 2;
CGFloat cdist = sqrtf(cx*cx + cy*cy);
CGFloat angle = atan2(dist, cdist);
//NSLog(#"%f",angle);
CGFloat radians = atan2f(super.transform.b, super.transform.a);
mDegrees = radians * (180 / M_PI);
if (mDegrees < 0.0)
{
mDegrees+=360;
}
NSLog(#"Angle is = %f",angle); //positive is clockwise, negative is counterclockwise
CGAffineTransform transform = CGAffineTransformRotate(self.transform, angle);
self.transform = transform;
touch1 = currentTouch1;
touch2 = currentTouch2;
}

Related

How to rotate and point to cursor location in SpriteKit?

I am working with the SpriteKit's Spaceship Demo and I want it to rotate to the location of where I click on the screen and then move toward it.
The current code I have only makes it move up the screen starting at position 50,50:
sprite.position = CGPointMake(50,50);
SKAction *fly = [SKAction moveByX:0.0F y:50.0F duration:1];
[sprite runAction:[SKAction repeatActionForever:fly];
How would I make it work?
So long answer, this will help you.(I benefited from raywenderlich's book)
//Math Utilities
static inline CGPoint CGPointSubtract(const CGPoint a,
const CGPoint b)
{
return CGPointMake(a.x - b.x, a.y - b.y);
}
static inline CGPoint CGPointMultiplyScalar(const CGPoint a,
const CGFloat b)
{
return CGPointMake(a.x * b, a.y * b);
}
static inline CGFloat CGPointLength(const CGPoint a)
{
return sqrtf(a.x * a.x + a.y * a.y);
}
static inline CGPoint CGPointNormalize(const CGPoint a)
{
CGFloat length = CGPointLength(a);
return CGPointMake(a.x / length, a.y / length);
}
static inline CGPoint CGPointAdd(const CGPoint a,
const CGPoint b)
{
return CGPointMake(a.x + b.x, a.y + b.y);
}
static const float SHIP_SPEED = 60.0;
#implementation yourScene
{
SKSpriteNode *ship;
NSTimeInterval _lastUpdateTime;
NSTimeInterval _dt;
CGPoint _velocity;
CGPoint _lastTouchLocation;
}
-(void)didMoveToView:(SKView *)view
{
ship = [SKSpriteNode spriteNodeWithImageNamed:#"Spaceship"];
ship.position = CGPointMake(50, 50);
[self addChild:ship];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
[self moveShipToward:touchLocation];//Move Toward
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
{
if (_lastUpdateTime) {
_dt = currentTime - _lastUpdateTime;
} else {
_dt = 0;
}
_lastUpdateTime = currentTime;
CGPoint offset = CGPointSubtract(_lastTouchLocation, ship.position);
float distance = CGPointLength(offset);
if (distance < SHIP_SPEED * _dt) {
ship.position = _lastTouchLocation;
_velocity = CGPointZero;
} else {
[self moveSprite:ship velocity:_velocity];
[self rotateSprite:ship toFace:_velocity];
}
}
}
- (void)moveShipToward:(CGPoint)location
{
_lastTouchLocation = location;
CGPoint offset = CGPointSubtract(location, ship.position);
CGPoint direction = CGPointNormalize(offset);
_velocity = CGPointMultiplyScalar(direction, SHIP_SPEED);
}
- (void)moveSprite:(SKSpriteNode *)sprite
velocity:(CGPoint)velocity
{
CGPoint amountToMove = CGPointMultiplyScalar(velocity, _dt);
sprite.position = CGPointAdd(sprite.position, amountToMove);
}
- (void)rotateSprite:(SKSpriteNode *)sprite
toFace:(CGPoint)direction
{
sprite.zRotation = atan2f(direction.y, direction.x);
}

Can't get the bullet image to spawn at right location

hi guys I have this Sprite Kit cannon game that it works perfectly but with one problem. if I point the cannon to a very top or very bottom as you can see in the image, the bullet since it is spawning from the center of the cannon's sprite, it shows clearly that the bullet is being fired not from the cannon's tunnel but from the center of the image, how can I fix this bullet position so that it would always spawn from the mouth of the tunnel.
here is my code so far.
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [_Player position];
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
bullet = [SKSpriteNode spriteNodeWithImageNamed:#"cannonbullet"];
bullet.xScale = 0.06;
bullet.yScale = 0.06;
bullet.position =
CGPointMake(location.x+_Player.zRotation,location.y+_Player.zRotation);
bullet.zPosition = 0;
CGPoint offset = rwSub(touchLocation, bullet.position);
if (offset.x <= 0) return;
[self addChild:bullet];
CGPoint direction = rwNormalize(offset);
CGPoint shootAmount = rwMult(direction, 400);
CGPoint realDest = rwAdd(shootAmount, bullet.position);
float velocity = 480.0/1.0;
float realMoveDuration = self.size.width / velocity;
SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];
SKAction * actionMoveDone = [SKAction removeFromParent];
[bullet runAction:[SKAction sequence:#[actionMove, actionMoveDone]]];
[self animStarter];
}
as you can see in the image the bullet is spawning from a very off location if the cannon is not shooting straight.
Make sure that your cannon's barrel sprite image is lined up with the center X axis of the image (see the picture). You can drag out or copy the image if you want to duplicate the project.
Below is the code to rotate the cannon to the touch location and fire a cannonball once it has reached the the desired rotation angle. I think you are still using the zombie conga code so I used its functions for your convenience.
#import "MyScene.h"
static inline CGPoint CGPointSubtract(const CGPoint a,
const CGPoint b)
{
return CGPointMake(a.x - b.x, a.y - b.y);
}
static inline CGPoint CGPointMultiplyScalar(const CGPoint a,const CGFloat b)
{
return CGPointMake(a.x * b, a.y * b);
}
static inline CGFloat CGPointLength(const CGPoint a)
{
return sqrtf(a.x * a.x + a.y * a.y);
}
static inline CGPoint CGPointNormalize(const CGPoint a)
{
CGFloat length = CGPointLength(a);
return CGPointMake(a.x / length, a.y / length);
}
static inline CGFloat CGPointToAngle(const CGPoint a)
{
return atan2f(a.y, a.x);
}
static inline CGFloat ScalarSign(CGFloat a)
{
return a >= 0 ? 1 : -1;
}
static inline CGFloat ScalarShortestAngleBetween(const CGFloat a, const CGFloat b)
{
CGFloat difference = b - a;
CGFloat angle = fmodf(difference, M_PI * 2);
if (angle >= M_PI) {
angle -= M_PI * 2;
}
return angle;
}
static const float ROTATE_RADIANS_PER_SEC = 4 * M_PI;
static const float MOVE_POINTS_PER_SEC = 120.0;
#implementation MyScene
{
SKSpriteNode *cannon;
NSTimeInterval _lastUpdateTime;
NSTimeInterval _dt;
CGPoint _velocity;
CGPoint _lastTouchLocation;
BOOL fireCannon;
CGPoint destination;
}
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
[self createCannon];
fireCannon = false;
}
return self;
}
-(void)createCannon
{
cannon = [SKSpriteNode spriteNodeWithImageNamed:#"cannon"];
cannon.position = CGPointMake(self.size.height/2, self.size.width/2);
[self addChild:cannon];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
fireCannon = true;
destination = touchLocation;
_lastTouchLocation = touchLocation;
CGPoint offset = CGPointSubtract(touchLocation, cannon.position);
CGPoint direction = CGPointNormalize(offset);
_velocity = CGPointMultiplyScalar(direction, MOVE_POINTS_PER_SEC);
}
-(void)update:(CFTimeInterval)currentTime
{
if (_lastUpdateTime) {
_dt = currentTime - _lastUpdateTime;
} else {
_dt = 0;
}
_lastUpdateTime = currentTime;
[self rotateSprite:cannon toFace:_velocity rotateRadiansPerSec:ROTATE_RADIANS_PER_SEC];
}
- (void)rotateSprite:(SKSpriteNode *)sprite
toFace:(CGPoint)velocity
rotateRadiansPerSec:(CGFloat)rotateRadiansPerSec
{
float targetAngle = CGPointToAngle(velocity);
float shortest = ScalarShortestAngleBetween(cannon.zRotation, targetAngle);
float amtToRotate = rotateRadiansPerSec * _dt;
if (ABS(shortest) < amtToRotate)
{
amtToRotate = ABS(shortest);
}
sprite.zRotation += ScalarSign(shortest) * amtToRotate;
if ((ABS(shortest) == amtToRotate) && (fireCannon == true))
{
fireCannon = false;
[self fire:targetAngle];
}
}
-(void)fire:(float)targetAngle
{
SKSpriteNode *cannonBall = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(5, 5)];
cannonBall.position = cannon.position;
[self addChild:cannonBall];
int x = cannon.position.x + 1000 * cos(targetAngle);
int y = cannon.position.y + 1000 * sin(targetAngle);
[cannonBall runAction:[SKAction moveTo:CGPointMake(x, y) duration:2]];
}
#end

How to shoot arrow in Box2d?

I am trying to shoot arrow with force in left to right direction on Touches Ended method.I applied linear impulse to B2Body, but it is not shooting in correct direction.
Here is my code
(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"ended");
//Add a new body/atlas sprite at the touched location
CGPoint location;
for( UITouch *touch in touches )
{
location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
}
if (fabs(ccpDistance(startTouchPosition, location)) < 3) {
return;
}
CGPoint diff = ccpSub(startTouchPosition, location);
diff = CGPointMake(-diff.x, -diff.y);
//CGFloat distanceX = bird.position.x - 50.0;
// CGFloat distanceY = bird.position.y - 160.0;
CGFloat velocityX = diff.x*-1/5;
CGFloat velocityY = diff.y*-1/5;
b2Vec2 birdVelocity = b2Vec2(velocityX,velocityY);
//make b2Body
CGFloat sphereX = arrow.position.x/PTM_RATIO;
CGFloat sphereY = arrow.position.y/PTM_RATIO;
b2BodyDef bodyDef;
bodyDef.position.Set(sphereX,sphereY);
bodyDef.type = b2_dynamicBody;
int num = 6;
b2Vec2 verts[] = {
b2Vec2(-56.5f / PTM_RATIO, 0.8f / PTM_RATIO),
b2Vec2(-51.9f / PTM_RATIO, -2.6f / PTM_RATIO),
b2Vec2(53.7f / PTM_RATIO, -2.2f / PTM_RATIO),
b2Vec2(58.7f / PTM_RATIO, 0.7f / PTM_RATIO),
b2Vec2(52.5f / PTM_RATIO, 3.0f / PTM_RATIO),
b2Vec2(-55.0f / PTM_RATIO, 1.2f / PTM_RATIO)
};
b2PolygonShape polyShape;
polyShape.Set(verts, num);
b2FixtureDef fixtureDef;
fixtureDef.shape= &polyShape;
fixtureDef.density=4;
fixtureDef.restitution=0.1;
fixtureDef.friction=0.5;
b2Body * physicsBird = world->CreateBody(&bodyDef);
physicsBird->CreateFixture(&fixtureDef);
physicsBird->GetUserData();
arrow.rotation=atan2f(arrow.position.x-startTouchPosition.x,arrow.position.y-startTouchPosition.y)*180/M_PI +90;
direction = arrow.rotation;
b2Vec2 force = b2Vec2(direction, 24.8);
physicsBird->ApplyLinearImpulse(force, physicsBird->GetWorldCenter());
physicsBird->SetLinearDamping(0.4);
}
but it is not working.Please help!

How to implement swipe with UIGestureRecognizer subclass

How do you implement a swipe with an UIGestureRecognizer subclass?
(in case you're wondering why I'd like to do this instead of using UISwipeGestureRecognizer, it's because I want to add swipe recognition to Chameleon's UIKit port)
My first go at it (also on Github):
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
_beganLocation = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint movedLocation = [touch locationInView:self.view];
CGFloat distance = _distance(_beganLocation, movedLocation);
if (distance < SWIPE_MIN_DISTANCE) return;
CGFloat angle = _angle(_beganLocation, movedLocation);
int direction = -1;
if (angle > 270 - SWIPE_MAX_ANGLE && angle < 270 + SWIPE_MAX_ANGLE) {
direction = UISwipeGestureRecognizerDirectionUp;
}
if (angle > 180 - SWIPE_MAX_ANGLE && angle < 180 + SWIPE_MAX_ANGLE) {
direction = UISwipeGestureRecognizerDirectionLeft;
}
if (angle > 90 - SWIPE_MAX_ANGLE && angle < 90 + SWIPE_MAX_ANGLE) {
direction = UISwipeGestureRecognizerDirectionDown;
}
if ((angle > 360 - SWIPE_MAX_ANGLE && angle <= 360) || (angle >= 0 && angle <= SWIPE_MAX_ANGLE)) {
direction = UISwipeGestureRecognizerDirectionRight;
}
if (direction == -1) {
self.state = UIGestureRecognizerStateFailed;
} else {
self.state = self.direction == direction ? UIGestureRecognizerStateRecognized : UIGestureRecognizerStateFailed;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.state = UIGestureRecognizerStateFailed;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
self.state = UIGestureRecognizerStateFailed;
}
Auxiliary functions:
static CGFloat _distance(CGPoint point1,CGPoint point2)
{
CGFloat dx = point2.x - point1.x;
CGFloat dy = point2.y - point1.y;
return sqrt(dx*dx + dy*dy);
};
static CGFloat _angle(CGPoint start, CGPoint end)
{
CGPoint origin = CGPointMake(end.x - start.x, end.y - start.y); // get origin point to origin by subtracting end from start
CGFloat radians = atan2f(origin.y, origin.x); // get bearing in radians
CGFloat degrees = radians * (180.0 / M_PI); // convert to degrees
degrees = (degrees > 0.0 ? degrees : (360.0 + degrees)); // correct discontinuity
return degrees;
}
It should be noted that Chameleon's implementation of gesture recognizers is incomplete and contains logic most likely specific to Twitterrific. Our fork contains further modifications.

How to rotate and resize sprite like photo in lybrary

How can I rotate sprite around his center in cocos2d in ccTouchesMoved. I found some code, but this not what I need. I need to rotate sprite like photo in Photo gallery app.
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *allTouch = [touches allObjects];
if([allTouch count] > 1){
UITouch *touch = [allTouch objectAtIndex:0];
CGPoint point = [touch locationInView: [touch view]];
point = [[CCDirector sharedDirector] convertToGL:point];
float angleRadians = atanf((float)point.y / (float)point.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle = -1 * angleDegrees;
imageFromPicker.rotation = imageFromPicker.rotation + cocosAngle;
}
}
probably is not the best way but im using this:
When I touch the sprite with two fingers, i use the arctan of the two points to rotate the sprite:
first i look for the direction with this function:
static inline int ccw(CGPoint p0, CGPoint p1, CGPoint p2)
{
int dx1, dx2, dy1, dy2;
dx1 = p1.x - p0.x; dy1 = p1.y - p0.y;
dx2 = p2.x - p0.x; dy2 = p2.y - p0.y;
int v1 = dx1 * dy2;
int v2 = dy1 * dx2;
if (v1 > v2)
return 1;
if (v1 < v2)
return -1;
if ((dx1*dx2 < 0) || (dy1*dy2 < 0))
return -1;
if ((dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2))
return 1;
return 0;
}
and after on the ccTouchesMoved method I do this:
if ([allTouches count] == 2) {
rotating=TRUE;
NSArray *twoTouches = [allTouches allObjects];
UITouch *first = [twoTouches objectAtIndex:0];
UITouch *second = [twoTouches objectAtIndex:1];
CGPoint a = [first previousLocationInView:[touch view]];
CGPoint b = [second previousLocationInView:[touch view]];
CGPoint c = [first locationInView:[touch view]];
int direction =ccw(b, a, c);
float pX= fabs(c.x-b.x);
float pY= fabs(c.y-b.y);
float rotation = atan2(pY, pX);
// rotTotal= (rotTotal+rotacion)/10;
if(direction<0)
YourSprite.rotation=(YourSprite.rotation-rotation);
else
YourSprite.rotation=(YourSprite.rotation+rotation);
}
it works for me, hope it works for you too