ApplyLinearImpulse() working in one direction only - iphone

I am trying to use both b2PrismaticJoint and b2MouseJoint. I need to move my projectile along x-axis to position it for target and want to only swipe vertically without moving the projectile to throw it in that direction. I am using ApplyLinearImpulse() but no matter in which direction i swipe it's direction is always towards top-right. The code is:
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
if (_mouseJoint) {
_world->DestroyJoint(_mouseJoint);
_mouseJoint = NULL;
}
if(_primJoint) {
_world->DestroyJoint(_primJoint);
_primJoint = NULL;
}
if (hit) {
_strikerBody->ApplyLinearImpulse(locationWorld, _strikerBody->GetPosition());
}
}

Looks like your locationWorld vector is pointing in the same direction every time. I think you want something like this:
b2Vec2 impulseDirection = locationWorld - _strikerBody->GetPosition();
impulseDirection.Normalize();
const double Force = 10 * _strikerBody->GetMass(); //or anything you want
_strikerBody->ApplyLinearImpulse( Force*impulseDirection, _strikerBody->GetPosition() );
Now the impulse will be applied to the center of the _strikerBody in the touch direction (relative to the _strikerBody) .

Related

Dpad for sprite kit

I an interested in trying to create a few games, namely in the new sprite kit. However, for the game that I have in mind I would rather use a directional pad vs a joy stick. Since I shall be moving over from Cocos, my old program no longer works (so neither will that dpad). Sadly, I have not come accross any tutorial that may help with implementing one in the new sprite kit (only joy sticks). I was wondering and hoping if anyone came across a simple dpad class from github or something or a helpful link that they would like to share. Thanks
Here's one way:
//Joystick node
- (SKSpriteNode *)controlPadNode
{
SKSpriteNode *controlPadNode = [SKSpriteNode spriteNodeWithImageNamed:#"game-controller-front"];
controlPadNode.position = CGPointMake(controlPadX,controlPadY);
controlPadNode.name = #"controlPadNode";
controlPadNode.zPosition = 1.0;
return controlPadNode;
}
//handle touch events
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
touchX = location.x;
touchY = location.y;
controlButtonDown = true;
}
}
//when touch moves
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
touchX = location.x;
touchY = location.y;
controlButtonDown = true;
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
controlButtonDown = false;
}
}
//update method
-(void)update:(NSTimeInterval)currentTime {
if (controlButtonDown) {
//the control pad
SKNode *controlNode = [self childNodeWithName:#"controlPadNode"];
//the node you want to move
SKNode *node = [self childNodeWithName:#"spaceShipNode"];
//compute the angle between parameters pad and the horizontal
float angle = atan2f (touchY - controlPadY, touchX - controlPadX) ;
//move the control pad for the player to have a sense of movement
SKAction *moveControlPad = [SKAction moveTo:CGPointMake(touchX, touchY) duration:0.00001];
double distance = sqrt(pow((touchX - controlPadX), 2.0) + pow((touchY - controlPadY), 2.0));
//make sure the control pad only moves 40 pixels
if( distance < 40 ){
[controlNode runAction:moveControlPad];
}
//move the ship
SKAction *moveShip = [SKAction moveByX: 6*cosf(angle) y:6*sinf(angle) duration:0.005];
[node runAction: moveShip];
}
}
EDIT:
Also can use this to move the control pad back when touch ends:
if (!controlButtonDown) {
SKNode *controlNode = [self childNodeWithName:#"controlPadNode"];
SKAction *moveControlPad = [SKAction moveTo:CGPointMake(controlPadX, controlPadY) duration:0.00001];
[controlNode runAction:moveControlPad];
}
I've built a small UIKit based game engine before the introduction of SpriteKit. My engine loads cocos2d compatible maps from Tiled, sprites from TexturePacker, and it comes with a joystick that I ported from cocos2d to UIKit. (Mine is based on sneaky-joystick.)
You can grab the whole library on GitHub and pull out the parts you need. It's fairly modular.

cocos 2d detect simoultaneous touch in 2 sprites - like in fruit ninja game

I want to know how can i detect when i touch 2 sprites simoultaneously in cocos2d. Im creating a game similar to fruit ninja and i want to add some bonus points when i smash two sprites simultaneously with my blade. I have tried something like that but it doesn't work:
(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//Add a new body/atlas sprite at the touched location
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
//[self addNewSpriteAtPosition: location];
[_blade dim:YES];
[_bladeSparkle stopSystem];
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
PolygonSprite *sprite = (PolygonSprite*)b->GetUserData();
NSLog(#"sprite entered, exited %d, %d",sprite.sliceEntered,sprite.sliceExited);
if(sprite.type == kTypeTrapPrice && CGRectContainsPoint(sprite.boundingBox, location))
{
NSLog(#"TOUCHED");
noTouch++;
}
}
}
}
// NSLog(#"NO TOUCH %i",noTouch);
[self clearSlices];
}
Have you seen the following tutorial?
http://www.raywenderlich.com/14302/how-to-make-a-game-like-fruit-ninja-with-box2d-and-cocos2d-part-1
Plus there are lots of other great ones there.

cocos2d for iPhone - Touch no longer works correctly after scale

I am rather new to using Cocos2d for iPhone and I am having an issue with touch locations. At the moment I am simply trying to touch and move a sprite on the screen, this works fine when the layer is unmoved as well as when I translate the layer (changing self.position in X direction in my case) however, when I scale my layer (example: self.scale = .5) the touch no longer moves the sprite. I have done a lot of forum searching/google searching and I think my issue has to do with my coordinate transforms (node space/world space etc.) But I am not 100% sure. I did notice that when I scale, if I click the location where the sprite would be without the scale, then I could move the sprite. This leads me to believe that my transforms are not taking the scale into account.
Here is the coordinate transform code I am currently using to get touch locations:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [self convertToNodeSpace:location];
location = [[CCDirector sharedDirector] convertToGL:location];
}
Here is the code that is checking if the location (same location variable as above) is touching a sprite, although I feel much more confident that this code is correct, who knows!
for (CCSprite *sprite in movableSprites) {
if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
NSLog(#"Woohoo, you touched a sprite!");
break;
}
}
Let me know if you need anymore information and thanks for reading!
I think you should double the bounding box with the scale
for (CCSprite *sprite in movableSprites) {
if (CGRectContainsPoint(sprite.boundingBox*sprite.scale, touchLocation)) {
//touch sprite action
}
}
About converting the point, if I need an absolut screen point I always use:
convertToWorldSpace:CGPointZero.
I'm not really sure why you need this on your touch location, I would usually do this on sprites when I need to disregard their position in a parent node.
Other then that, If your game is not real multi-touch game you better use ccTouchBegan and not ccTouchesBegan.
Use this function to get sprite rect.
-(CGRect)getSpriteRect:(CCNode *)inSprite
{
CGRect sprRect = CGRectMake(
inSprite.position.x - inSprite.contentSize.width*inSprite.anchorPoint.x,
inSprite.position.y - inSprite.contentSize.height*inSprite.anchorPoint.y,
inSprite.contentSize.width,
inSprite.contentSize.height
);
return sprRect;
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for (CCSprite *sprite in movableSprites)
{
CGRect rect = [self getSpriteRect:sprite];
if (CGRectContainsPoint(rect, location))
{
NSLog(#"Woohoo, you touched a sprite!");
break;
}
}
}

UIImageView how to track clockwise or counterclockwise user motion

I have successfully implemented rotating a uiimageview using this code from this post
iPhone - Wheel tracking finger jumps to same starting position?
My question to fellow developers is that the user on touch can rotate the image both clockwise and counterclockwise. Is there a way I can detect in which direction is the user moving the view?
Its important to me because I am making a clock app. I let users move the min hand form 0 min all the way to 60 min. When it reaches there I move the hour hand one up. But the user can spin the min hand counter clockwise in which case I need to move the hour hand one down. Any ideas?
you can set a member variable named "lastPoint" to record the point last time you moved
the you can calc the direction next time
CGPoint lastPoint;
- (void) touchedBegin:(NSSet *)touches withEvent:(UIEvent *)event {
lastPoint = [touch locationInView:self.view];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
//you can save the point , then used in next time you want
int tInput = [allTouches count]-1;
UITouch *touch =[[allTouches allObjects] objectAtIndex:tInput];
CGPoint location = [touch locationInView:self.view];
float theAngle = atan2( location.y-imageX.center.y, location.x-imageX.center.x );
float theLastAngle = atan2( lastPoint.y-imageX.center.y, lastPoint.x-imageX.center.x );
lastPoint = location;
// compare theAngle & theLastAngle , so you can know it is clockwise or counterclockwise.
}

How can i rotate body when user touch the screen in cocos2d

I am facing one problem. I have done some coding to rotate cpSegmentShapeNew but its not working . Have a look on the following code,
//**creating shape
testBody = cpBodyNew(INFINITY, INFINITY);
cpShape* testShape = cpSegmentShapeNew(testBody, cpv(230, 82), cpv(193, 46), 0.0f);
testShape->e = 0.0;
testShape->u = 0.0;
testShape->data = flipper;
testShape->collision_type = 2;
cpSpaceAddStaticShape(space, testShape);
//Body moving when user touch
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//event that starts when a finger touchs the screen
UITouch *touch = [touches anyObject];
CGPoint tmpLoc = [touch locationInView: [touch view]];
CGPoint location = [[Director sharedDirector] convertCoordinate:tmpLoc];
ball.position = location;
ballBody->p = location;
[flipper runAction:[RotateTo actionWithDuration:0.1f angle:60]];
cpBodySetAngle(testBody, 60);
cpvrotate(testBody->rot, cpv(100000,0));
return kEventHandled;
}
Please anyone tell me that where i am wrong.
Thanks.
Greetings,
The problem is that you are rotating both objects (sprite + body) through code.
What you need is rotate one, and let the other object know it's happened so it can do it too.
For example, if you move the body, then the method that updates the sprites should look like that:
void updateShapes(void* ptr, void* unused)
{
cpShape* shape = (cpShape*)ptr;
Sprite* sprite = shape->data;
if(sprite)
{
cpBody* body = shape->body;
[sprite setPosition:cpv(body->p.x, body->p.y)];
[sprite setRotation: (float) CC_RADIANS_TO_DEGREES( -body->a )];
}
}
The last line of code updates the rotation. That's the line you are missing.
I hope that helps you or someone else in the future.
Good luck cocos2d mate !
Yohann T.