cocos2D and Box2D : How to get exact touched sprite? - iphone

I am trying to move sprite on touch moved. but when two sprites is there i am geting touch of two sprites. that's why sprites are not moving properly.
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
if (_mouseJoint != NULL) return;
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);
for(int i=0;i<[mutArrFixtures count];i++)
{
b2Fixture *fixture;
[[mutArrFixtures objectAtIndex:i] getValue:&fixture];
if (fixture->TestPoint(locationWorld)){
for(int j=0; j<[mutArrPaddleBody count]; j++)
{
b2Body *body;
[[mutArrPaddleBody objectAtIndex:j] getValue:&body];
b2MouseJointDef md;
if(body == fixture->GetBody())
{
md.bodyA = _groundBody;
md.bodyB = body;
md.target = locationWorld;
md.collideConnected = true;
md.maxForce = 1000.0f * body->GetMass();
_mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
body->SetAwake(true);
}
}
}
}
}
i have an array of b2Fixture mutArrFixtures and also an array mutArrPaddleBody of b2body. but in this if i touch on second sprite i get touch on first sprite and second sprite.. two sprites positions are same...

In touch function, check tag of the sprite. If that is ur right sprite then move. Show me some code that u used for touch movement.
.......
Replace these code with next one
b2Body *body;
[[mutArrPaddleBody objectAtIndex:j] getValue:&body];
b2MouseJointDef md;
if(body == fixture->GetBody())
with
b2Body* body = fixture->GetBody();
CCSprite *sprite = (CCSprite*)body->GetUserData();
if( sprite && sprite.tag == kTagHero)
{
}
Make sure u added tag kTagHero for ur moving sprite.
....
enum gameTag {
kTagHero = 1001
};
and assign sprite.tag = kTagHero
......

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.

Improve Responsiveness of ccTouchesBegan

At the moment, I have a puzzle game, with some objects that are movable using the ccTouchesBegan && ccTouchesMoved method
Called in ccTouchesBegan:
if (CGRectContainsPoint(newBoundingBox, touchLocation))
{
//Set the selectedSprite to the sprite with newBoundingBox
}
Then in ccTouchesMoved i do:
CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
newPos = ccpAdd(selSprite.position, translation);
selectedSprite.position = newPos;
Now this all works fine and dandy, HOWEVER, some of the objects that I am moving are about 140x40px (on the 320x480 iPhone), and sometimes the ccTouchesBegan method won't acknowledge the boundingBox containing the touchLocation.
My question is, Can I increase the size of the boundingBox of the object so that if the user "misses" with there touch a little bit, it will help them out? It's a little frustrating requiring you to be so precise on a touch screen to move an obstacle.
EDIT: for iPhonic:
How I get touchLocation, this is in ccTouchesBegan:
NSSet *touchSet = [event allTouches];
int numberOfTouches = [touchSet count];
CGPoint touchLocation = [self convertTouchToNodeSpace:[touches anyObject]];
allTouches is passed automatically when the a touch begins.
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint location = [self convertTouchToNodeSpace: touch];
for (CCSprite *tempSprite in sprites )
{
//Increase the size of bounding box..
CGRect rect=tempSprite.boundingBox;
rect.size.height=rect.size.height + 20;
rect.size.width=rect.size.width + 20;
if (CGRectContainsPoint(rect, location))
{
//Your stuffs
}
}
}

how many bullets have been fired?

I am super frustrated and I know it is just because I don't know what i am doing with cocos2d. I am following Ray Wenderlich tutorials on cocos2d and I am trying to put it all together. When the screen is tapped,one bullet is fired in the direction of the tap. I am using
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self.officer shootToward:touchLocation];
[self.officer shootNow];
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self.officer shootToward:touchLocation];
[self.officer shootNow];
}
which calls these methods in my Officer class
- (void)shootNow {
// 1
CGFloat angle = ccpToAngle(_shootVector);
_gun.rotation = (-1 * CC_RADIANS_TO_DEGREES(angle)) + 90;
// 2
CGSize winSize = [[CCDirector sharedDirector] winSize];
float mapMax = MAX(winSize.width, winSize.height);
CGPoint actualVector = ccpMult(_shootVector, mapMax);
// 3
float POINTS_PER_SECOND = 300;
float duration = mapMax / POINTS_PER_SECOND;
// 5
for(id item in self.children) {
NSString *bulletName = [NSString stringWithFormat:#"bullet.png"];
CCSprite * bullet = [CCSprite spriteWithSpriteFrameName:bulletName];
//bullet.tag = _type;
bullet.position = ccpAdd(self.position, ccpMult(_shootVector, _gun.contentSize.height));
CCMoveBy * move = [CCMoveBy actionWithDuration:duration position:actualVector];
CCCallBlockN * call = [CCCallBlockN actionWithBlock:^(CCNode *node) {
[node removeFromParentAndCleanup:YES];
}];
[bullet runAction:[CCSequence actions:move, call, nil]];
[self.batchNode addChild:bullet];
//[self addChild:bullet];
[_shotsFired addObject:bullet];
}
}
So I figured it would be a simple for loop go through the 5th step x amount of times then call a reload method. Well that didn't work. So I tried to count the touches on the screen, I figured if I got x amount of taps then call the reload method(which is not written yet)? The problem with that was every time you pressed a different area of the screen the count started over from one. Some please help me through this week long process of pulling my hair out? How do I count the amount of times I have fired the gun?
Couldn't you just make a property on your view controller and then every time the shoot now method is called just add 1 to your property, then reset it to 0 when you call the reload method?

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.

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.