Make a sprite appear where touched and drag it around - windows-phone

Why is it so hard to drag a sprite in cocos2dx! doing this in my touchesbegan method
void HelloWorld::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
CCSprite *splash = CCSprite::spriteWithFile("splash3.png");
CCTouch* pTouch = (CCTouch*)(touches->anyObject());
CCPoint location = pTouch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
splash->setPosition(ccp(location.x,location.y));
this->addChild(splash,5);
}
void HelloWorld::ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
CCSprite *splash = CCSprite::spriteWithFile("splash3.png");
CCTouch* pTouch = (CCTouch*)(touches->anyObject());
CCPoint location = pTouch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
splash->setPosition(ccp(location.x,location.y));
this->addChild(splash,5);
}
what am I doing wrong and whats more to be done? and is there an easier way to do this???

You need to add a sprite only once. You can either keep a global reference or retrieve the sprite using its tag. Also, you may be calculating touch position incorrectly. Try this
void HelloWorld::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
CCSprite *splash = CCSprite::spriteWithFile("splash3.png");
CCPoint location = getPositionFromTouches(touches, event);
splash->setPosition(ccp(location.x,location.y));
this->addChild(splash,5, 100);
}
void HelloWorld::ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
CCSprite *splash = (CCSprite*) getChildByTag(100);
CCPoint location = getPositionFromTouches(touches, event);
splash->setPosition(ccp(location.x,location.y));
}
CCPoint HelloWorld::getPositionFromTouches(CCSet* _touches, CCEvent* event) {
CCArray *allTouches = CCArray::create();
CCSetIterator it;
for( it = _touches->begin(); it != _touches->end(); it++)
{
allTouches->addObject((CCTouch *)*it);
}
//CCArray *allTouches = getAllTouchesFromSet(_touches);
CCTouch* fingerOne = (CCTouch *)allTouches->objectAtIndex(0);
CCPoint pointOne = CCDirector::sharedDirector()->convertToUI(fingerOne->getLocationInView());
CCPoint location = _armadilloSingleton->convertToNodeSpace(pointOne);
return location;
}

spriteWithFile is not there in cocos2d2.0.4.
So can you please update the code according to the latest version of COCOCS2D

Related

Sprite Kit Objective C

I am creating a game using sprite kit but I seem to have trouble with the bodyWithTexture when using it with collisions. bodyWithRectangle and circleOfRadius work fine, but when i use bodyWithTexture it looks like the didBeginContact method is being called more than once.
here is an example of the code i'm using
-(SKNode *) createPlayer
{
level3Player = [SKNode node];
player3Sprite = [SKSpriteNode spriteNodeWithImageNamed:#"character.png"];
level3Player.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:player3Sprite.size.width/2];
level3Player.physicsBody.categoryBitMask = playerCategory3;
level3Player.physicsBody.contactTestBitMask = platformCategory3 | rockCategory;
[level3Player setPosition:CGPointMake(self.size.height/2, screenHeightL3 *11)];
level3Player.physicsBody.affectedByGravity = NO;
player3Sprite.physicsBody.dynamic = YES;
level3Player.zPosition = 2;
[level3Player setScale:0.6];
[level3Player addChild:player3Sprite];
return level3Player;
}
-(void) addRocksL3
{
int randomNumber = arc4random_uniform(300);
rock1 = [SKSpriteNode spriteNodeWithImageNamed:#"AsteroidFire.png"];
rock1.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:rock1.size.width/2];
rock1.position = CGPointMake(self.size.width * 3, randomNumber);
rock1.physicsBody.categoryBitMask = rockCategory;
rock1.physicsBody.contactTestBitMask = playerCategory3;
rock1.physicsBody.dynamic = NO;
rock1.physicsBody.affectedByGravity = NO;
rock1.zPosition = 2;
[rock1 setScale:0.3];
[foregroundLayerL3 addChild:rock1];
[self addChild:rock1];
}
-(void) didBeginContact:(SKPhysicsContact*) contact
{
SKPhysicsBody *firstBody, *secondBody;
if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if((secondBody.categoryBitMask == platformCategory3) | redPlatformCategory)
{
level3Player.physicsBody.velocity = CGVectorMake(0, 100);
level3Player.physicsBody.affectedByGravity = YES;
player3Sprite.texture = [SKTexture textureWithImageNamed:#"goo5.png"];
SKAction *sound1 = [SKAction playSoundFileNamed:#"squish.wav" waitForCompletion:NO];
[self runAction:sound1];
gestureRec3.enabled = YES;
}
if(secondBody.categoryBitMask == rockCategory)
{
gestureRec3.enabled = YES;
playerL3.physicsBody.velocity = CGVectorMake(0, 200);
SKAction *playSound = [SKAction playSoundFileNamed:#"Hurt.wav" waitForCompletion:NO];
[self runAction:playSound];
hitCountL3++;
}
switch (hitCountL3)
{
case 1:
[health1Level3 removeFromParent];
[self healthNodelevel31];
break;
case 2:
[hit1L3 removeFromParent];
[self healthNodeLevel32];
break;
case 3:
[hit2L3 removeFromParent];
player3Sprite.texture = [SKTexture textureWithImageNamed:#"splat.png"];
[self gameOverSplatLevel3];
didDie3 = true;
SKAction *playSplat = [SKAction playSoundFileNamed:#"splat.wav" waitForCompletion:NO];
[self runAction:playSplat];
break;
}
when i use this code my character will sometimes take 1 hit and sometimes take all 3 hits when i collide with the rock. I could use circleOfRadius which works fine, but it's not what I am really looking for. Is there anyway i could use bodyWithTexture so my character only takes 1 hit each time?
If you are experiencing multiple collisions eg. didBeginContact is called multiple times, you have few options...
Without looking at your code, lets say you have a player and a rock. Each time when player collides with rock you want to remove the rock. So, you remove the rock from its parent. But before that, you make this change in your code (pseudo code):
if([rockNode parent]){
[rockNode removeFromParent];
}
The other way would be to subclass SKSpriteNode and make a Rock class and to make a custom boolean property which will change its value once when first collision happens. But this is just unnecessary complication:
if(rockNode.canCollide){
[rockNode removeFromParent];
rockNode.canCollide = NO;
}
I had many problems with correct amount of collisions. Sometimes it would get one, sometimes none. So I tried this and it works. The only thing to change is in didBeginContact method.
I will presume that you declared categories like this:
//define collision categories
static const uint32_t category1 = 0x1 << 0;
static const uint32_t category2 = 0x1 << 1;
static const uint32_t category3 = 0x1 << 2;
Try to replace your code in didBeginContact with this one. I remember that correct collisions finally got to work after I did this.
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKNode *newFirstBody = contact.bodyA.node;
SKNode *newSecondBody = contact.bodyB.node;
uint32_t collision = newFirstBody.physicsBody.categoryBitMask | newSecondBody.physicsBody.categoryBitMask;
if (collision == (category1 | category2))
{
NSLog(#"hit");
}
}
Hope it helps

Detecting on which CCSprite has been clicked

My main screen is Main.ccbi, it contains 3 CCSprite. Now I want that when user clicks on a CCSprite I should know on which he has clicked?
I want to calculate in CCMotionBegin method that on which CCSprite user has clicked.
First store the sprites you have created in a CCArray say mSpriteArray and then you can do something like the following
bool MyClass :: ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
CCPoint currentTouchLocation = pTouch->getLocationInView();
currentTouchLocation = CCDirector::sharedDirector()->convertToGL(currentTouchLocation);
currentTouchLocation = this->convertToNodeSpace(currentTouchLocation);
CCSprite *selectedSprite = getSpriteAtPosition(currentTouchLocation);
return true;
}
CCSprite* MyClass :: getSpriteAtPosition(CCPoint inTouchPosition)
{
CCObject *object;
CCARRAY_FOREACH(mSpriteArray, object)
{
CCSprite *sprite = (CCSprite*)sprite;
if (sprite->boundingBox().containsPoint(inTouchPosition))
{
return sprite;
}
}
return NULL;
}
Hope this helps.

using cocos2d to design shootgame, i can't invoke stopGame method

-(void)spriteMoveFinishedid)sender //when sprite is outside of screen,it's deleted;
{
CCSprite *sprite = (CCSprite *)sender;
if (sprite.tag == 1) //it's enemy;
{
escapeNum++;
[self removeChild:sprite cleanup:YES];
if (escapeNum == 10)
{
[self stopGameEx]; //Because the speed of every enemy isn't same to other and there are bullets,it maybe happens that two sprites disappear at the same time, and the program stop at this with error --- program received signal:“EXC_BAD_ACCESS”。
}
//...........
}
}
How to resolve it?
Inside if loop, change sprite tag to mark it as expired sprite, and some where else remove.
enum
{
kTagExpiredSprite = 999 //any number not ur sprite tag(1)
};
.....
-(void)spriteMoveFinishedid)sender //when sprite is outside of screen,it's deleted;
{
CCSprite *sprite = (CCSprite *)sender;
if (sprite.tag == 1) //it's enemy;
{
escapeNum++;
sprite.tag = kTagExpiredSprite;
if (escapeNum == 10)
{
[self stopGameEx]; //Because the speed of every enemy isn't same to other and there are bullets,it maybe happens that two sprites disappear at the same time, and the program stop at this with error --- program received signal:“EXC_BAD_ACCESS”。
}
//...........
}
}

creating a loop with multiple sprites?

i've got a column of sprites as one sprite goes off the screen i want the same sprite to wrap around the opposite side so that two sprites are showing simultaneously, as one moves of the screen the other comes onto the screen and the other sprite that goes off is no longer visible. I was told to make a ccnode in which to do everything here is my code so far, but none of it works so i think i will need to start from scratch again.
Here is a link to my last question on this for more info: When sliding sprite, if sprite disappears off the side, it will wrap around to the opposite side?
here is my code anyways:
for (int i =0; i<16; ++i) {
MyNode *currentSprite = [c1array objectAtIndex:i];
if (currentSprite.contentSize.height>=320 || currentSprite.position.y-currentSprite.contentSize.height/2<=0 ){
MyNode *Bsprite = currentSprite;
MyNode *Tsprite = currentSprite;
Bsprite.scale = 1.0;
Tsprite.scale = 1.0;
if(currentSprite.position.y >=253){
Bsprite.position = ccp(currentSprite.position.x,-35);
[self addChild:Bsprite];
Bsprite.visible = TRUE;
}
if (currentSprite.position.y <=0) {
Tsprite.position = ccp(currentSprite.position.x,324);
[self addChild:Tsprite];
Tsprite.visible = TRUE;
}
MyNode *isChanging;
if ((Tsprite.visible == TRUE && currentSprite.visible == TRUE) || (Bsprite.visible == TRUE && currentSprite.visible == TRUE)) {
isChanging = TRUE;
}
if (isChanging == FALSE) {
[self removeChild:Tsprite cleanup:YES];
[self removeChild:Bsprite cleanup:YES];
}
}
}
BSprite and TSprite are pointers to the same object (currentSprite). You actually need two separate objects, either by cloning currentSprite or by creating another array in the same manner as c1array.

cocos2d and chipmunk rotate object after collision

hi
im pretty new to both frameworks. but maybe someone can point me into the right direction:
basically i try to bounce a ball of a shape. (works fine)
but it would be great when the ball would rotate, too
here is my (copy & paste) code
// BallLayer.m
#import "BallLayer.h"
void updateShape(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)];
}
}
#implementation BallLayer
-(void)tick:(ccTime)dt{
cpSpaceStep(space, 1.0f/60.0f);
cpSpaceHashEach(space->activeShapes, &updateShape, nil);
}
-(void)setupChipmunk{
cpInitChipmunk();
space = cpSpaceNew();
space->gravity = cpv(0,-2000);
space->elasticIterations = 1;
[self schedule: #selector(tick:) interval: 1.0f/60.0f];
cpBody* ballBody = cpBodyNew(200.0, cpMomentForCircle(100.0, 10, 10, cpvzero));
ballBody->p = cpv(150, 400);
cpSpaceAddBody(space, ballBody);
cpShape* ballShape = cpCircleShapeNew(ballBody, 20.0, cpvzero);
ballShape->e = 0.8;
ballShape->u = 0.8;
ballShape->data = ballSprite;
ballShape->collision_type = 1;
cpSpaceAddShape(space, ballShape);
cpBody* floorBody = cpBodyNew(INFINITY, INFINITY);
floorBody->p = cpv(0, 0);
cpShape* floorShape = cpSegmentShapeNew(floorBody, cpv(0,0), cpv(320,160), 0);
floorShape->e = 0.5;
floorShape->u = 0.1;
floorShape->collision_type = 0;
cpSpaceAddStaticShape(space, floorShape);
floorShape = cpSegmentShapeNew(floorBody, cpv(0,200), cpv(320,0), 0);
cpSpaceAddStaticShape(space, floorShape);
}
-(id)init{
self = [super init];
if(nil != self){
ballSprite = [Sprite spriteWithFile:#"ball2.png"];
[ballSprite setPosition:CGPointMake(150, 400)];
[self add:ballSprite];
[self setupChipmunk];
}
return self;
}
#end
please help me out.
well when i decided psoting it i found the solution :)
void updateShape(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 )];
}
}