I want every spritenode the user creates come with a left and right edge bitmask. Other bitmasks work, but this one don't.
Below the method for creating a new spritenode, which is called in TouchesBegin
-(void)spawnBrick
{
brick = [[BrickNodeOne alloc] init];
brick.name = #"Brick";
NSArray *array = [self objectForKeyedSubscript:#"Brick"];
BrickNodeOne *oldBrick;
if ([array count] > 0) {
oldBrick = [array objectAtIndex:([array count]-1)];
}
brick.position = CGPointMake(brick.size.width / 2, (brick.size.height + oldBrick.position.y)-15);
brick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(brick.size.width, brick.size.height)];
brick.physicsBody.categoryBitMask = kBrickCategory;
brick.physicsBody.contactTestBitMask = kCarCategory;
brick.physicsBody.collisionBitMask = 0;
[self addChild:brick];
SKAction *moveTo = [SKAction moveByX:0.0 y:-125.0 duration:1.0];
[brick runAction:[SKAction repeatActionForever:moveTo]withKey:#"moveDown"];
_brickRightEdge = [[SKNode alloc] init];
_brickRightEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(brick.size.width, 0.0) toPoint:CGPointMake(brick.size.width, brick.size.height)];
_brickRightEdge.physicsBody.dynamic = NO;
_brickRightEdge.physicsBody.categoryBitMask = brickRightEdgeCategory;
_brickRightEdge.physicsBody.contactTestBitMask = kCarCategory;
_brickRightEdge.position = brick.position;
[brick addChild:_brickRightEdge];
_brickLeftEdge = [[SKNode alloc] init];
_brickLeftEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(0.0, 0.0) toPoint:CGPointMake(0.0, brick.size.height)];
_brickLeftEdge.physicsBody.dynamic = NO;
_brickLeftEdge.position = brick.position;
_brickLeftEdge.physicsBody.categoryBitMask = brickLeftEdgeCategory;
_brickLeftEdge.physicsBody.contactTestBitMask = kCarCategory;
[brick addChild:_brickLeftEdge];
}
The car spritenode which I want collision detection with the brick right and left edge is declared in didMoveToView
SKSpriteNode *car = [SKSpriteNode spriteNodeWithImageNamed:#"HighWayCar_Red"];
car.position = CGPointMake(self.size.width / 2, 120);
car.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:car.size];
car.physicsBody.categoryBitMask = kCarCategory;
car.physicsBody.contactTestBitMask = kWaterCategory | brickLeftEdgeCategory | brickRightEdgeCategory;
car.physicsBody.collisionBitMask = 0;
car.physicsBody.dynamic = NO;
car.zPosition = 2;
[self addChild:car];
Code DidBeginContact
if (firstBody.categoryBitMask == kCarCategory && secondBody.categoryBitMask == brickLeftEdgeCategory) {
NSLog(#"HIT");
}
if (firstBody.categoryBitMask == kCarCategory && secondBody.categoryBitMask == brickRightEdgeCategory) {
NSLog(#"HIT");
}
Update for comment
I declared `SKPhysicsContactDelegate` in the header file. Set the delegate in `didMoveToView`
Bitmasks:
static const uint32_t kBrickCategory = 0x1 << 0;
static const uint32_t leftEdgeCategory = 0x1 << 1;
static const uint32_t rightEdgeCategory = 0x1 << 2;
static const uint32_t brickLeftEdgeCategory = 0x1 << 3;
static const uint32_t brickRightEdgeCategory = 0x1 << 4;
static const uint32_t kCarCategory = 0x1 << 5;
static const uint32_t kWaterCategory = 0x1 << 6;
Related
I have two SKSpriteNode first Hero
+(id)hero
{
NSMutableArray *walkFrames = [NSMutableArray array];
SKTextureAtlas *heroAnimatedAtlas = [SKTextureAtlas atlasNamed:#"HeroImages"];
int numImages = (int)heroAnimatedAtlas.textureNames.count;
for (int i=1; i <= numImages; i++) {
NSString *textureName = [NSString stringWithFormat:#"hero%d", i];
SKTexture *temp = [heroAnimatedAtlas textureNamed:textureName];
[walkFrames addObject:temp];
}
Hero *hero = [Hero spriteNodeWithTexture:walkFrames[0]];
hero.heroWalkingFrames = walkFrames;
hero.name =#"Hero";
hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hero.size];
hero.physicsBody.categoryBitMask = heroCategory;
hero.physicsBody.categoryBitMask = obstacleCategory | groundCategory | homeCategory | ~goodiesCategory;
return hero;
}
and second is Coin
SKSpriteNode *coin = [SKSpriteNode spriteNodeWithImageNamed:#"coin"];
coin.size = CGSizeMake(10,10);
coin.position = CGPointMake(100,100);
coin.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:coin.size];
coin.physicsBody.contactTestBitMask = coinCategory;
coin.physicsBody.dynamic=NO;
coin.name = #"coin";
[self.world addChild:coin];
And I am able to get collision detection by
if([contact.bodyA.node.name isEqual: #"coin"] || [contact.bodyB.node.name isEqual: #"coin"])
{
//[self LevelComplete];
SKNode* coinNode ;
if ([contact.bodyA.node.name isEqual: #"coin"]) {
coinNode=contact.bodyA.node;
}
else{
coinNode=contact.bodyB.node;
}
[coinNode removeFromParent];
NSLog(#"Coin touched");
}
Now my problem is every time hero jump and touch the coin it will go down to ground instead to continue jump and reach the height that it should, I know I am missing something here but don't know what it is, So anyone can please show me the right direction to correct this effect .
Create an extra "nilCategory" and set the collisionBitMask of your coin..
coin.physicsBody.collisionBitMask = nilCategory;
I hope you can help, have a block moving across and it jumps to avoid obstacles and collect coins.
It's collision with the obstacles is working correctly and the below gameOver is working correctly.
-(void)didBeginContact:(SKPhysicsContact *)contact
{
if ([contact.bodyA.node.name isEqualToString:#"coins"] || [contact.bodyB.node.name isEqualToString:#"coins"]) {
[self coinCollected]; //THIS IS NOT WORKING
NSLog(#"contacted"); //THIS IS NOT WORKING
}
else if ([contact.bodyA.node.name isEqualToString:#"ground"] || [contact.bodyB.node.name isEqualToString:#"ground"]) {
[hero land];
}
else {
NSLog (#"dead");
[self gameOver];
[self runAction:[SKAction playSoundFileNamed:#"gameover.wav" waitForCompletion:NO]];
}
}
My PMWorldGenenerator file looks as below:
#import "PMWorldGenerator.h"
#interface PMWorldGenerator ()
#property double currentGroundX;
#property double currentObstacleX;
#property double coinX;
#property SKNode *world;
#end
#implementation PMWorldGenerator
static const uint32_t obstacleCategory = 0x1 << 1;
static const uint32_t groundCategory = 0x1 << 2;
static const uint32_t coinCategory = 0x1 << 3;
+ (id)generatorWithWorld:(SKNode *)world {
PMWorldGenerator *generator = [PMWorldGenerator node];
generator.currentGroundX = 0;
generator.currentObstacleX = 400;
generator.coinX = 50;
generator.world = world;
return generator;
}
-(void)populate
{
for (int i = 0; i <3; i++)
[self generate];
}
-(void)generate
{
SKSpriteNode *ground = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(self.scene.frame.size.width, self.scene.frame.size.height/2.7)];
ground.name = #"ground";
ground.position = CGPointMake(self.currentGroundX, -self.scene.frame.size.height/2 + ground.frame.size.height/2);
ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
ground.physicsBody.categoryBitMask = groundCategory;
ground.physicsBody.dynamic = NO;
[self.world addChild:ground];
self.currentGroundX += ground.frame.size.width;
SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(10,10)];
obstacle.name = #"obstacle";
obstacle.position = CGPointMake(self.currentObstacleX/5, ground.position.y + ground.frame.size.height/2 + obstacle.frame.size.height/2 + 5);
obstacle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle.size];
obstacle.physicsBody.dynamic = NO;
obstacle.physicsBody.categoryBitMask = obstacleCategory;
[self.world addChild:obstacle];
self.currentObstacleX += 550 ;
SKSpriteNode *coins = [SKSpriteNode spriteNodeWithColor:[UIColor yellowColor] size:CGSizeMake(4, 4)];
coins.name = #"coins";
coins.position = CGPointMake(self.coinX+80, ground.position.y + ground.frame.size.height/2 + obstacle.frame.size.height/2 + 25);
coins.physicsBody.categoryBitMask = coinCategory;
coins.physicsBody.dynamic = YES;
SKAction *revolution = [SKAction rotateByAngle:M_PI_4*10 duration:3];
SKAction *repeatRotate = [SKAction repeatActionForever:revolution];
[coins runAction:repeatRotate];
[self.world addChild:coins];
self.coinX += 550;
}
and lastly my PMHero file:
#import "PMHero.h"
#interface PMHero ()
#end
#implementation PMHero
static const uint32_t heroCategory = 0x1 << 0;
static const uint32_t obstacleCategory = 0x1 << 1;
static const uint32_t groundCategory = 0x1 << 2;
static const uint32_t coinCategory = 0x1 << 3;
+(id)hero
{
PMHero *hero = [PMHero spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(12,12)];
hero.name = #"hero";
hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hero.size];
hero.physicsBody.categoryBitMask = heroCategory;
hero.physicsBody.contactTestBitMask = obstacleCategory | groundCategory | coinCategory;
return hero;
}
I have done exactly what I had done for my obstacles and ground for the "coins", but it doesn't detect any collisions with them in my didBeginContact
You haven't added your physics body for coins
SKSpriteNode *coins = [SKSpriteNode spriteNodeWithColor:[UIColor yellowColor] size:CGSizeMake(4, 4)];
coins.name = #"coins";
coins.position = CGPointMake(self.coinX+80, ground.position.y + ground.frame.size.height/2 + obstacle.frame.size.height/2 + 25);
coins.physicsBody = [SKPhysicsBody bodyWith...//need code here
coins.physicsBody.categoryBitMask = coinCategory;
coins.physicsBody.dynamic = NO;
coins.physicsBody.collisionBitMask = 0;
SKAction *revolution = [SKAction rotateByAngle:M_PI_4*10 duration:3];
SKAction *repeatRotate = [SKAction repeatActionForever:revolution];
[coins runAction:repeatRotate];
[self.world addChild:coins];
I am trying to get the value from my custom class SKNode object. The problem is when I touch on the object no matter what is gives me the same value regardless of the object I touch on.
(blue button) and I cannot get the buttonID,buttonType that I set earlier.
Everything works well, except when I need to get the buttonType, buttonID of the object I touch or drag over.
I am not sure where I am going wrong, any help or push in the right direction would be great. Thanks.
here is my custom class .h file.
#import <SpriteKit/SpriteKit.h>
#interface ButtonNode : SKNode {
SKNode *buttonCustom;
}
#property int buttonType, buttonColumn, buttonID, xPos, yPos;
#property NSString *buttonName;
-(id)initWithButtonType:(int)buttonType;
#end
Here is my custom class .m file
#import "ButtonNode.h"
#define kBoxSize CGSizeMake(40, 40)
#implementation ButtonNode
#synthesize buttonColumn,buttonType,buttonID,xPos,yPos,buttonName;
static const uint32_t blueCategory = 1 << 0;
static const uint32_t redCategory = 1 << 1;
static const uint32_t greenCategory = 1 << 2;
static const uint32_t yellowCategory = 1 << 3;
-(id)initWithButtonType:(int)buttonType {
self = [super init];
if (buttonType == 1) {
NSLog(#"BLUE BUTTON CREATE");
[self addButtonBlue];
}
if (buttonType == 2) {
NSLog(#"RED BUTTON CREATE");
[self addButtonRed];
}
if (buttonType == 3) {
NSLog(#"Green BUTTON CREATE");
[self addButtonGreen];
}
if (buttonType == 4) {
NSLog(#"Yellow BUTTON CREATE");
[self addButtonYellow];
}
return self;
}
- (void) addButtonBlue {
SKSpriteNode *rect;
//button type 1
rect = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:kBoxSize];
int tmpInt = [[NSDate date] timeIntervalSince1970];
NSString *tmpName = [NSString stringWithFormat:#"%i", tmpInt];
rect.name = tmpName; //unique name.
rect.name = #"1";
rect.physicsBody.categoryBitMask = blueCategory;
rect.physicsBody.contactTestBitMask = blueCategory;
rect.physicsBody.collisionBitMask = blueCategory | redCategory | yellowCategory | greenCategory;
rect.position = CGPointMake(xPos , yPos );
[self addChild:rect];
}
- (void) addButtonRed {
SKSpriteNode *rect;
//button type 2
rect = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:kBoxSize];
int tmpInt = [[NSDate date] timeIntervalSince1970];
NSString *tmpName = [NSString stringWithFormat:#"%i", tmpInt];
rect.name = tmpName; //unique name.
rect.name = #"2";
rect.physicsBody.categoryBitMask = redCategory;
rect.physicsBody.contactTestBitMask = redCategory;
rect.physicsBody.collisionBitMask = blueCategory | redCategory | yellowCategory | greenCategory;
rect.position = CGPointMake(xPos , yPos );
[self addChild:rect];
}
- (void) addButtonGreen {
SKSpriteNode *rect;
//button type 3
rect = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:kBoxSize];
int tmpInt = [[NSDate date] timeIntervalSince1970];
NSString *tmpName = [NSString stringWithFormat:#"%i", tmpInt];
rect.name = tmpName; //unique name.
rect.name = #"3";
rect.physicsBody.categoryBitMask = greenCategory;
rect.physicsBody.contactTestBitMask = greenCategory;
rect.physicsBody.collisionBitMask = blueCategory | redCategory | yellowCategory | greenCategory;
rect.position = CGPointMake(xPos , yPos );
[self addChild:rect];
}
- (void) addButtonYellow {
SKSpriteNode *rect;
//button type 4
rect = [SKSpriteNode spriteNodeWithColor:[UIColor yellowColor] size:kBoxSize];
int tmpInt = [[NSDate date] timeIntervalSince1970];
NSString *tmpName = [NSString stringWithFormat:#"%i", tmpInt];
rect.name = tmpName; //unique name.
rect.name = #"4";
rect.physicsBody.mass = 1;
rect.physicsBody.categoryBitMask = yellowCategory;
rect.physicsBody.contactTestBitMask = yellowCategory;
rect.physicsBody.collisionBitMask = blueCategory | redCategory | yellowCategory | greenCategory;
rect.position = CGPointMake(xPos , yPos );
[self addChild:rect];
}
#end
Here is where I create the buttons.
(at top of file with rest of global ivar )
ButtonNode * newButton;
for (int i = 1; i <= 6; i++) {
//create random Int
int tmpInt = arc4random() %3;
NSLog(#"tmp %i" ,tmpInt);
column1.position = CGPointMake(100, self.frame.size.height - 40);
if (tmpInt == 0) {
//button type 1
newButton = [[ButtonNode alloc] initWithButtonType:1];
newButton.xPos = column1.position.x;
newButton.yPos = column1.position.y *i;
newButton.buttonID = 344224351; //unique name
newButton.buttonColumn = 2;
newButton.buttonType = 1;
[column1 addChild:newButton];
blueTotal++;
totalButtons++;
column1Total++;
}
if (tmpInt == 1) {
//button type 2
newButton = [[ButtonNode alloc] initWithButtonType:2];
newButton.xPos = column1.position.x;
newButton.yPos = column1.position.y *i;
newButton.buttonID = 344224351; //unique name
newButton.buttonColumn = 2;
newButton.buttonType = 1;
[column1 addChild:newButton];
redTotal++;
totalButtons++;
column1Total++;
}
}
Here is the Part that is not working correctly.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
UITouch* touch = [touches anyObject];
CGPoint loc = [touch locationInNode:self];
NSArray *nodes = [self nodesAtPoint:loc];
for (SKNode *nod in nodes) {
NSString *tmp = nod.name;
if (tmp.length !=0) {
NSString * tmpType = nod.name;
if ([tmpType isEqualToString:#"1"]) {
NSLog(#"Node Type: %#", nod.name);
previousButton = #"1";
NSLog (#"%d",newButton.buttonType);
}
if ([tmpType isEqualToString:#"2"]) {
NSLog(#"Node Type: %#", nod.name);
previousButton = #"2";
NSLog (#"%d",newButton.buttonType);
}
if ([tmpType isEqualToString:#"3"]) {
NSLog(#"Node Type: %#", nod.name);
previousButton = #"3";
NSLog (#"%d",newButton.buttonType);
}
if ([tmpType isEqualToString:#"4"]) {
NSLog(#"Node Type: %#", nod.name);
previousButton = #"4";
NSLog (#"%d",newButton.buttonType);
}
}
}
}
}
A SKNode does not have those properties.
Try this just inside your for loop :
ButtonNode *myButton = (ButtonNode *)nod;
That will cast nod correctly as a ButtonNode, and you can use myButton like this :
NSLog(#"%d",myButton.buttonType);
Then you should be able to access the properties you have defined in the ButtonNode class.
You might only want to do that cast if you are sure it's a ButtonNode, but was just trying to help you understand why those properties would NEVER be accessible given your current code.
Also, your usage of newButton in that loop in touchesBegan is not what I think you 'think' it is. It's going to be the last button created, not the current node being stored in nod in the loop.
I have a boat with attached physics body. This boat is static physics body. Boat moving with CCAnimateMoveTo from left to right. When I tap on screen my character fall down. I detect collisions well. But I want that after collision my character just fall on boat and keep moving with it. Character is dynamic body. Link to sample video: Sample video
Here I create a boat:
- (void)createBoat
{
currentBoat = [CCSprite spriteWithImageNamed:#"Boat.png"];
currentBoat.position = ccp(0 - currentBoat.boundingBox.size.width, winSize.height * 0.2);
// currentBoat.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){0, 0, currentBoat.contentSize.width, currentBoat.contentSize.height * 0.5} cornerRadius:0];
CGPoint shape[6];
shape[0] = ccp(0, 30);
shape[1] = ccp(64, 10);
shape[2] = ccp(128, 30);
shape[3] = ccp(128, 0);
shape[4] = ccp(0, 0);
shape[5] = ccp(0, 30);
currentBoat.physicsBody = [CCPhysicsBody bodyWithPolylineFromPoints:shape count:6 cornerRadius:0 looped:NO];
currentBoat.physicsBody.type = CCPhysicsBodyTypeStatic;
currentBoat.physicsBody.collisionGroup = #"BoatGroup";
currentBoat.physicsBody.collisionType = #"BoatCollision";
[physicsWorld addChild:currentBoat z:PHYSICS_Z+3];
id actionMoveBoat = [[CCActionMoveTo alloc] initWithDuration:5.0f position:ccp(winSize.width + currentBoat.boundingBox.size.width, currentBoat.position.y)];
id actionMethod = [CCActionCallFunc actionWithTarget:self selector:#selector(createBoat)];
[currentBoat runAction:[CCActionSequence actions:actionMoveBoat, [[CCActionRemove alloc] init], actionMethod, nil]];
}
Character creation:
- (void)createCharacter
{
if (needCharacter)
{
CCSprite *newCharacter = [CCSprite spriteWithImageNamed:#"Character.png"];
newCharacter.opacity = 0;
newCharacter.position = ccp(winSize.width * 0.5, winSize.height * 0.76);
newCharacter.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, newCharacter.contentSize} cornerRadius:0];
newCharacter.physicsBody.affectedByGravity = NO;
newCharacter.physicsBody.allowsRotation = YES;
newCharacter.physicsBody.collisionGroup = #"playerGroup";
newCharacter.physicsBody.collisionType = #"playerCollision";
[physicsWorld addChild:newCharacter z:PHYSICS_Z+4];
id actionFadeIn = [[CCActionFadeIn alloc] initWithDuration:0.5];
[newCharacter runAction:actionFadeIn];
[allCharacters addObject:newCharacter];
needCharacter = false;
touchDone = false;
}
}
Then detection touch and collision:
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCNode *lastCharacter = [allCharacters lastObject];
if (!touchDone)
{
[lastCharacter.physicsBody applyImpulse:ccp(0, 300)];
lastCharacter.physicsBody.type = CCPhysicsBodyTypeDynamic;
lastCharacter.physicsBody.affectedByGravity = YES;
touchDone = true;
}
}
- (BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair playerCollision:(CCNode *)currentCharacterC BoatCollision:(CCNode *)currentBoatC {
currentCharacterC.physicsBody.collisionType = #"tmpCollision";
CCLOG(#"score++");
if ([allCharacters containsObject:currentCharacterC])
{
score++;
[scores setString:[NSString stringWithFormat:#"%d", score]];
[allCharacters removeAllObjects];
if (lives != 0)
{
needCharacter = true;
[self createCharacter];
}
}
CCLOG(#"allCharacters = %#", allCharacters);
return YES;
}
well I too faced the same problem, tried increasing the friction/surface velocity etc, it didn't really work well.
Finally had to resolve it my own way, whenever player lands on any body, you keep a pointer to that body as say _bodyUnderFeet of the player object.
Now, in the update loop add the velocity of the _bodyUnderFeet to the players calculated velocity. See the use of zeroVel_x
Sample code is here:
void Player::update(float dt)
{
float zeroVel_x = 0;
if(_bodyUnderFeet != NULL)
{
zeroVel_x = _bodyUnderFeet->v.x;
}
cpBody *bd = getCPBody();
assert(bd);
//log("Body angle %f", bd->a);
//check forward backward or at rest
float accel = _accelGround;
if(_onGroundBoost < UP_BOOST)
{
accel = _accelAir;
}
if(_touchPressedB)
{
if(!isFlippedX())
{
setFlippedX(true);
}
//cpBodySetVel(bd, cpv(cpBodyGetVel(bd).x - accel*0.25, 0));
cpVect bdv = cpBodyGetVel(bd);
bdv.x = bdv.x - zeroVel_x;
if(bdv.x > 0) bdv.x = 0;
if(bdv.x > -_maxVelocity.x)
cpBodySetVel(bd, cpv(zeroVel_x + bdv.x - accel*0.25, bdv.y));
}
else if(_touchPressedF)
{
if(isFlippedX())
{
setFlippedX(false);
}
//cpBodySetVel(bd, cpv(cpBodyGetVel(bd).x + accel*0.25, 0));
cpVect bdv = cpBodyGetVel(bd);
bdv.x = bdv.x - zeroVel_x;
if(bdv.x < 0) bdv.x = 0;
if(bdv.x < _maxVelocity.x)
cpBodySetVel(bd, cpv(zeroVel_x+bdv.x + accel*0.25, bdv.y));
}
else
{
cpFloat bd_x = cpBodyGetVel(bd).x;
bd_x = bd_x - zeroVel_x;
if(bd_x>0)
{
if(bd_x > accel*0.25)
{
cpBodySetVel(bd, cpv(zeroVel_x+bd_x - accel*0.25, cpBodyGetVel(bd).y));
}
else
{
cpBodySetVel(bd, cpv(zeroVel_x+0, cpBodyGetVel(bd).y));
}
}
else if(bd_x < 0)
{
if(bd_x < accel*0.25)
{
cpBodySetVel(bd, cpv(zeroVel_x+bd_x + accel*0.25, cpBodyGetVel(bd).y));
}
else
{
cpBodySetVel(bd, cpv(zeroVel_x+0, cpBodyGetVel(bd).y));
}
}
}
//check jump
if(_touchPressedJ)
{
if(_onGroundBoost)
{
cpVect bdv = cpBodyGetVel(bd);
if(bdv.y < 0) bdv.y = 0;
if((bdv.y + _accelUp) < _maxVelocity.y)
{
cpBodySetVel(bd, cpv(bdv.x, bdv.y + _accelUp));
--_onGroundBoost;
}
else
{
cpBodySetVel(bd, cpv(bdv.x, _maxVelocity.y));
_onGroundBoost = 0;
}
}
}
//check shots
if(_touchPressedS)
{
if(!_bulletFired)
{
}
}
//check home
if(_touchPressedH)
{
}
boundRotation(bd);
}
I think,
you can increase the friction between man and boat after he fall down. and reduce the elasticity . then the boat can 'take' the man go together...
just a trick.
I have a ball sprite that falls from the top and a boy underneath it. When the ball hits the boy's head I want it to follow a parabolic path. I tried using CCJumpTo as follows but I cannot get it to work. I'm calling the action inside the update loop. Am I not allowed to do that? Cant I call CCJumpTo inside the update loop?
- (void) jump
{
if(!method_called)
{
method_called=TRUE;
CCActionInterval *jump1 = [CCJumpTo actionWithDuration:3 position:CGPointMake(400, 400) height:150 jumps:1];
[_ball runAction:jump1];
NSLog(#"something");
}
else
{
NSLog(#"do nothing");
}
}
- (void)update:(ccTime)dt
{
time ++;
if ( dpad.leftJoystick.velocity.x > 0 && x < 2000 ) {
x = x + 10;
} else if ( dpad.leftJoystick.velocity.x < 0 && x > 0 ) {
x = x - 10;
}
if (x > 10 && x < 2000)
_boy.position = ccp(x, 100);
_ball.position = ccp(ball_x, ball_y);
ball_y = _ball.position.y - (speed * rebound);
_boy.anchorPoint = ccp(0, 0);
CGRect boyBox = CGRectMake(_boy.position.x, _boy.position.y, [_boy boundingBox].size.width, [_boy boundingBox].size.height);
_ball.anchorPoint = ccp(0, 0);
CGRect ballBox = CGRectMake(_ball.position.x, _ball.position.y, [_ball boundingBox].size.width, [_ball boundingBox].size.height);
if (CGRectIntersectsRect(boyBox, ballBox) && flag == 0)
{
rebound = -rebound;
flag = 1;
topFlag = 0;
[_ball stopAllActions];
[self jump];
}
if (_ball.position.y > 700 && topFlag == 0)
{
rebound = -rebound;
flag = 0;
topFlag = 1;
}
}
Thanks in advance.
EDIT:
Here's my init method
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
self.ball = [CCSprite spriteWithFile:#"ball.png"
rect:CGRectMake(0, 0, 50, 50)];
self.ball.position = ccp(275, 999);
[self addChild:self.ball];
x = 0;
ball_y = 650;
ball_x = 300;
rebound = 1;
flag = 0;
topFlag = 0;
speed = 5;
time = 0;
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"boy.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"boy.png"];
//spriteSheet.scaleX = 0.5;
//spriteSheet.scaleY = 0.5;
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i) {
[walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"boy%d.png", i]]];
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:.1f];
self.boy = [CCSprite spriteWithSpriteFrameName:#"boy1.png"];
_boy.position = ccp(100000, 100000);
self.walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
[_boy runAction:_walkAction];
_boy.flipX = YES;
[spriteSheet addChild:_boy];
dpad = [[MyJoystick alloc] init];
[self addChild:dpad z:10];
[self schedule:#selector(update:)];
}
[self addChild:spriteSheet];
}
return self;
}
Keep your action code inside a method and call it from update method using a boolean variable so that it would be called once only. Something like this:
take a boolean variable method_called in .h file:
-(void)update:(ccTime)dt
{
_boy.anchorPoint = ccp(0, 0);
CGRect boyBox = CGRectMake(_boy.position.x, _boy.position.y, [_boy boundingBox].size.width, [_boy boundingBox].size.height);
_ball.anchorPoint = ccp(0, 0);
CGRect ballBox = CGRectMake(_ball.position.x, _ball.position.y, [_ball boundingBox].size.width, [_ball boundingBox].size.height);
if (CGRectIntersectsRect(boyBox, ballBox) && flag == 0)
{
flag = 1; topFlag = 0;
[self callJumpAction];
}
}
-(void)callJumpAction
{
if(!method_called)
{
method_called=true;
CCActionInterval *jump1 = [CCJumpTo actionWithDuration:3 position:CGPointMake(400, 400) height:150 jumps:1];
[_ball runAction:jump1];
}
else
{
NSLog(#"do nothing");
}
}
Hope this will help.