How to make a sprite jump inside update loop in Cocos2D - ios

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.

Related

how can i reset a view controller in xcode to its state when i started the app

how can i reset a view controller in xcode to its state when i started the app
#interface Game ()
#end
#implementation Game
-(void)Restart{
Mx = 0;
Mx2 = 0;
My = 0;
My2 = 0;
WizX = 1;
WizY = 0;
}
-(void)MonsterMovment2{
float screen_width2;
float screen_height2;
float vers = [[[UIDevice currentDevice] systemVersion] floatValue];
UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
if (vers < 8 && UIInterfaceOrientationIsLandscape(orient))
{
screen_width2 = [[UIScreen mainScreen] bounds].size.width;
screen_height2 = [[UIScreen mainScreen] bounds].size.height;
}
else
{
screen_width2 = [[UIScreen mainScreen] bounds].size.width;
screen_height2 = [[UIScreen mainScreen] bounds].size.height;
}
Monster2.center = CGPointMake(Monster2.center.x + Mx2, Monster2.center.y + My2);
if (CGRectIntersectsRect(Monster2.frame, Wiz.frame)) {
[self GameOver];
}
if (Monster2.center.x < 10) {
Mx2 = 1;
}
if (Monster2.center.x > screen_width2) {
Mx2 = -1;
}
if (Monster2.center.y > screen_height2) {
My2 = -1;
}
if (Monster2.center.y < 10) {
My2 = 1;
}
}
-(void)MonsterMovment{
float screen_width;
float screen_height;
float vers = [[[UIDevice currentDevice] systemVersion] floatValue];
UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
if (vers < 8 && UIInterfaceOrientationIsLandscape(orient))
{
screen_width = [[UIScreen mainScreen] bounds].size.width;
screen_height = [[UIScreen mainScreen] bounds].size.height;
}
else
{
screen_width = [[UIScreen mainScreen] bounds].size.width;
screen_height = [[UIScreen mainScreen] bounds].size.height;
}
Monster.center = CGPointMake(Monster.center.x + Mx, Monster.center.y + My);
if (CGRectIntersectsRect(Monster2.frame, Monster.frame)) {
Mx = Mx;
My=My;
}
if (CGRectIntersectsRect(Monster.frame, Wiz.frame)) {
[self GameOver];
}
if (Monster.center.x < 10) {
Mx = 1;
}
if (Monster.center.x > screen_width) {
Mx = -1;
}
if (Monster.center.y > screen_height) {
My = -1;
}
if (Monster.center.y < 10) {
My = 1;
}
}
-(void)GameOver{
StartGame.hidden = YES;
[WizMovment invalidate ];
Wiz.hidden = YES;
Exit.hidden = NO;
StartGame.hidden = NO;
if (ScoreNumber > HighScoreNumber) {
[[NSUserDefaults standardUserDefaults] setInteger:ScoreNumber forKey:#"HighScoreSaved"];
HighScore.text = [NSString stringWithFormat:#"High Score: %i", ScoreNumber];
}
[self viewDidLoad];
}
-(void)Score{
ScoreNumber = ScoreNumber + 1;
ScoreLabel.text = [NSString stringWithFormat:#"Score: %i", ScoreNumber];
}
-(void)PlaceFood{
float screen_width;
float screen_height;
float vers = [[[UIDevice currentDevice] systemVersion] floatValue];
UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
if (vers < 8 && UIInterfaceOrientationIsLandscape(orient))
{
screen_height = [[UIScreen mainScreen] bounds].size.width;
screen_width = [[UIScreen mainScreen] bounds].size.height;
}
else
{
screen_width = [[UIScreen mainScreen] bounds].size.width;
screen_height = [[UIScreen mainScreen] bounds].size.height;
}
int height = (int) screen_height;
int widht = (int) screen_width;
FoodX = arc4random() %height;
FoodX = FoodX - 25;
if (25 < FoodX) {
FoodX = 25;
}
FoodY = arc4random() %widht;
FoodY = FoodY -25;
if (25 < FoodY) {
FoodY = 25;
}
Food.center = CGPointMake(FoodX, FoodY);
[Food setFrame:CGRectMake(FoodX, FoodY, Food.frame.size.width, Food.frame.size.height)];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
}
-(void)MoveLeft{
if (WizSideMovment == NO) {
WizX = -1;
WizY = 0;
WizSideMovment = YES;
}
}
-(void)MoveRight{
if (WizSideMovment == NO) {
WizX = 1;
WizY = 0;
WizSideMovment = YES;
}
}
-(void)MoveUp{
if (WizSideMovment == YES) {
WizX = 0;
WizY = -1;
WizSideMovment = NO;
}
}
-(void)MoveDown{
if (WizSideMovment == YES) {
WizX = 0;
WizY = 1;
WizSideMovment = NO;
}
}
-(void)WizMovment{
float screen_width;
float screen_height;
float vers = [[[UIDevice currentDevice] systemVersion] floatValue];
UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
if (vers < 8 && UIInterfaceOrientationIsLandscape(orient))
{
screen_height = [[UIScreen mainScreen] bounds].size.width;
screen_width = [[UIScreen mainScreen] bounds].size.height;
}
else
{
screen_width = [[UIScreen mainScreen] bounds].size.width;
screen_height = [[UIScreen mainScreen] bounds].size.height;
}
Wiz.center = CGPointMake(Wiz.center.x + WizX, Wiz.center.y + WizY);
if (CGRectIntersectsRect(Wiz.frame, Food.frame)) {
[self PlaceFood];
[self Score];
}
if (Wiz.center.x < 1) {
[WizMovment invalidate];
[self performSelector:#selector(GameOver) withObject:self afterDelay:0.5];
}
if (Wiz.center.x > screen_width - 25) {
[WizMovment invalidate];
[self performSelector:#selector(GameOver) withObject:self afterDelay:0.5];
}
if (Wiz.center.y > screen_height - 25) {
[WizMovment invalidate];
[self performSelector:#selector(GameOver) withObject:self afterDelay:0.5];
}
if (Wiz.center.y < 25) {
[WizMovment invalidate];
[self performSelector:#selector(GameOver) withObject:self afterDelay:0.5];
}
}
-(IBAction)Exit:(id)sender{
[self reloadInputViews];
[self Restart];
}
-(IBAction)Start:(id)sender{
int i = rand()%2+1;
NSLog(#"Random Number: %i", i);
if ( (i = 2)) {
i = -1;
}
int w = rand()%2+1;
NSLog(#"Random Number: %i", w);
if ( (w = 2)) {
w = -1;
}
int e = rand()%2+1;
NSLog(#"Random Number: %i", e);
if ( (e = 2)) {
e = -1;
}
int r = rand()%2+1;
NSLog(#"Random Number: %i", r);
if ( (r = 2)) {
r = -1;
}
Mx=i;
Mx2 =w;
My=e;
My2=r;
StartGame.hidden = YES;
Wiz.hidden= NO;
WizX = 1;
WizY = 0;
Food.hidden = NO;
WizMovment = [NSTimer scheduledTimerWithTimeInterval:0.007 target:self selector:#selector(WizMovment) userInfo:nil repeats:YES];
MonsterMovment = [NSTimer scheduledTimerWithTimeInterval:0.007 target:self selector:#selector(MonsterMovment) userInfo:nil repeats:YES];
MonsterMovment2 = [NSTimer scheduledTimerWithTimeInterval:0.007 target:self selector:#selector(MonsterMovment2) userInfo:nil repeats:YES];
[self PlaceFood];
/* int i = rand()%2+1;
NSLog(#"Random Number: %i", i);
if ( (i = 2)) {
i = -1;
}
int w = rand()%2+1;
NSLog(#"Random Number: %i", w);
if ( (w = 2)) {
w = -1;
}
int e = rand()%2+1;
NSLog(#"Random Number: %i", e);
if ( (e = 2)) {
e = -1;
}
int r = rand()%2+1;
NSLog(#"Random Number: %i", r);
if ( (r = 2)) {
r = -1;
}
Mx=i;
Mx2 =w;
My=e;
My2=r;
*/
}
- (void)viewDidLoad {
//[[UIScreen mainScreen] bounds];
Exit.hidden = YES;
HighScoreNumber = [[NSUserDefaults standardUserDefaults] integerForKey:#"HighScoreSaved"];
HighScore.text = [NSString stringWithFormat:#"High Score: %li", (long)HighScoreNumber];
[super viewDidLoad];
// Do any additional setup after loading the view.
Food.hidden = YES;
WizX = 1;
WizY = 0;
WizSideMovment = YES;
UISwipeGestureRecognizer *SwipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(MoveLeft)];
[SwipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[self.view addGestureRecognizer:SwipeLeft];
UISwipeGestureRecognizer *SwipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(MoveRight)];
[SwipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[self.view addGestureRecognizer:SwipeRight];
UISwipeGestureRecognizer *SwipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(MoveUp)];
[SwipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[self.view addGestureRecognizer:SwipeUp];
UISwipeGestureRecognizer *SwipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(MoveDown)];
[SwipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[self.view addGestureRecognizer:SwipeDown];
}
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Simply remove it, create new instance and add again.
Just remove it and re-add it again from the parent will create it brand new, otherwise it's just a case of keeping defaults and reapplying them all on game over.

NodesAtPoint does not find a node

I'm trying to create 10 balloons in my app. I create a random CGPoint to set my node's position and check, in case that already exist a node at this point I try again.
I don't know why, the balloons keep being placed over another balloon.
Any ideia of what I am doing wrong?
Here is my code:
-(void)gerarBaloes:(int)quantidade
{
balloons = [NSMutableArray new];
u_int32_t maxHorizontal = 900;
u_int32_t minHorizontal = 100;
u_int32_t maxVertical = 650;
u_int32_t minVertical = 100;
for (int i=1; i<= quantidade; i++) {
CGPoint posicao = CGPointMake(arc4random_uniform(maxHorizontal - minHorizontal + 1) + minHorizontal, arc4random_uniform(maxVertical - minVertical + 1) + minVertical);
while (![self validPosition:posicao]) {
posicao = CGPointMake(arc4random_uniform(maxHorizontal - minHorizontal + 1) + minHorizontal, arc4random_uniform(maxVertical - minVertical + 1) + minVertical);
}
balao* nBalao = [[balao alloc]initWithPosition:posicao];
SKLabelNode* numero = [[SKLabelNode alloc]initWithFontNamed:#"Arial Rounded MT Bold"];
numero.text = [NSString stringWithFormat:#"%d",i];
numero.zPosition = 1;
nBalao.body.zPosition = 0;
[nBalao addChild:numero];
nBalao.body.name = #"balloon";
[balloons addObject:nBalao];
[self addChild:nBalao];
}
}
And this is my validation method:
-(BOOL)validPosition:(CGPoint)position
{
NSArray* nodes = [self nodesAtPoint:position];
NSLog(#"total de nodes %d",nodes.count);
if (nodes.count > 0) {
for (SKNode* n in nodes) {
if ([n isKindOfClass:[balao class]]) {
return NO;
}
}
return YES;
}else{
return YES;
}
}
Balao.m class:
#implementation balao
-(id)initWithPosition:(CGPoint)pos
{
if (self = [super init]) {
self.position = pos;
int n = arc4random_uniform(4);
_balloonAtlas = [SKTextureAtlas atlasNamed:[NSString stringWithFormat:#"balloon%d",n]];
_explosionFrames = [NSMutableArray array];
int numImages = _balloonAtlas.textureNames.count;
for (int i=1; i<= numImages; i++){
NSString *textureName = [NSString stringWithFormat:#"balloon_%d",i];
SKTexture *temp = [_balloonAtlas textureNamed:textureName];
[_explosionFrames addObject:temp];
}
SKTexture *textInicial = [_explosionFrames[0] copy];
[_explosionFrames removeObjectAtIndex:0];
self.body = [SKSpriteNode spriteNodeWithTexture:textInicial];
[self addChild:_body];
}
return self;
}
- (void)explodeBalloon
{
SKAction* explosao = [SKAction animateWithTextures:_explosionFrames timePerFrame:0.02f resize:NO restore:YES];
[self.body runAction:explosao completion:^(void){
[self removeFromParent];
}];
[self runAction:[SKAction playSoundFileNamed:#"popSound.mp3" waitForCompletion:NO]];
}
This is how the balloons appears:
Edit:
I tried the suggested method, with CGRectCointainsPoint, but it didn't work too. :/
Checking for nodes at a given point is not enough to prevent overlap. You need to check whether the point falls inside the frame of another balloon. You can modify the function like this
-(BOOL)validPosition:(CGPoint)position
{
NSArray* nodes = [self children];
if (nodes.count > 0) {
for (SKNode* n in nodes) {
if ([n isKindOfClass:[balao class]]) {
if (CGRectContainsPoint([n getBalloonFrame], position)) // Changed line
{
return NO
}
}
}
return YES;
}
return YES;
}
CGRectContainsPoint checks whether a given rectangle contains a point.
Inside balao class define the following function. Also note the changed line in the above code.
-(void)getBalloonFrame
{
return CGRectOffset(self.body.frame, self.frame.origin.x, self.frame.origin.y)
}

IOS - Collision Detection on Sprites using Cocos2d

In this game I have asteroids flying down from to top of screen, and a ship you can move freely, but I have added some collision detection and it does not seem to work in the update method when I call [self scheduleupdate];
// Import the interfaces
#import "HelloWorldLayer.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
// HelloWorldLayer implementation
#implementation HelloWorldLayer
// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
if( (self=[super init]) ) {
self.isTouchEnabled = YES;
moveLeft = NO;
moveRight = NO;
speed = 3;
fireSpeed = 8;
fireArray = [[NSMutableArray alloc] init];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *bg = [[CCSprite alloc] initWithFile:#"space_bg.jpg"];
[bg setPosition:ccp(160, 240)];
CGSize imageSize = bg.contentSize;
bg.scaleX = winSize.width / imageSize.width;
bg.scaleY = winSize.height / imageSize.height;
bg.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:bg];
ship = [[CCSprite alloc] initWithFile:#"ship.png"];
[ship setPosition:ccp(100, 100)];
[self addChild:ship];
[self schedule:#selector(fireLoop:)];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(fireCreate)
userInfo:nil
repeats:YES];
asteroidArray = [[NSMutableArray alloc] init];
for(int i = 0; i < 100; ++i) {
CCSprite *asteroid = [[CCSprite alloc] initWithFile:#"asteroid1.png"];
[asteroidArray addObject:asteroid];
}
[self asteroidCreate];
[self scheduleUpdate];
}
return self;
}
CCSpriteBatchNode *spriteSheet;
NSMutableArray *asteroidAnimFrames;
- (float)randomValueBetween:(float)low andValue:(float)high {
return (((float) arc4random() / 0xFFFFFFFFu) * (high - low)) + low;
}
-(void)updtate:(ccTime)dt{
CGPoint shipPosition = [ship position];
for(int i = 0; i < asteroidArray.count; i++){
CCSprite *asteroid = [asteroidArray objectAtIndex:i];
if (CGRectIntersectsRect(ship.boundingBox, asteroid.boundingBox)) {
NSLog(#"hit");
}
}
}
- (void)countDownToCreateNextAsteroid {
int minTime = 1;
int maxTime = 10;
int randomTime = (arc4random() % (3));
id countdownDelay = [CCDelayTime actionWithDuration:randomTime];
id creationMethod = [CCCallFunc actionWithTarget:self selector:#selector(asteroidCreate)];
id countdownToCreateSeq = [CCSequence actions:countdownDelay, creationMethod, nil];
[self stopAllActions];
[self runAction:countdownToCreateSeq];
}
-(void)asteroidCreate {
CGSize winSize = [[CCDirector sharedDirector] winSize];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"asteroids.plist"];
spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"asteroids.png"];
asteroidAnimFrames = [NSMutableArray array];
for(int i=1; i <= 8; i++) {
[asteroidAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"asteroid%d.png", i]]];
}
CCAnimation *moveAsteroidAnim = [CCAnimation animationWithFrames:asteroidAnimFrames delay:0.1f];
CCSprite *asteroid = [CCSprite spriteWithSpriteFrameName:#"asteroid1.png"];
int x = arc4random() % 320;
int y = arc4random() % 480;
asteroid.position = ccp(x, 480);
CCAction *asteroidAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:moveAsteroidAnim restoreOriginalFrame:NO]];
[asteroidArray addObject:asteroid];
int q = arc4random() % 320;
int r = arc4random() % 10;
CCAction *moveAction = [CCMoveTo actionWithDuration:r position:ccp(q, -50)];
id asteroidRemove = [CCCallBlock actionWithBlock:^
{
[asteroid removeFromParentAndCleanup:YES];
[asteroidArray removeObject:asteroid];
}];
id asteroidSeq = [CCSequence actions:moveAction, asteroidRemove, nil];
[asteroid runAction:asteroidSeq];
[asteroid runAction:asteroidAction];
[spriteSheet addChild:asteroid];
[self addChild:spriteSheet];
[self countDownToCreateNextAsteroid];
}
-(void)fireLoop:(ccTime)fl {
if(fireArray.count > 0){
for(int i = 0; i < fireArray.count; i++){
CCSprite *tmpFire = [fireArray objectAtIndex:i];
if(tmpFire.position.y < 500){
[tmpFire setPosition:ccp([tmpFire position].x, [tmpFire position].y + fireSpeed)];
}else{
[fireArray removeObjectAtIndex:i];
}
}
} else {
}
}
-(void)fireCreate{
int shootPositionX = [ship position].x;
int shootPositionY = ([ship position].y) + 35;
CCSprite *fire;
fire = [[CCSprite alloc] initWithFile:#"fire.png"];
[fire setPosition:ccp(shootPositionX, shootPositionY)];
[fireArray addObject:fire];
[self addChild:fire];
[fire release];
}
-(void)gameLoop:(ccTime)dt {
int shipPositionX = 41/2;
if([ship position].x > shipPositionX){
[ship setPosition:ccp([ship position].x - speed, [ship position].y)];
}
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
//if(point.x <= 160){
// moveRight = NO;
// moveLeft = YES;
//}else{
// moveRight =YES;
// moveLeft = NO;
//}
if(allowedToMove)
[ship setPosition:ccp(point.x, point.y + 76)];
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
int shipX = [ship position].x;
int shipY = [ship position].y;
if (CGRectContainsPoint(CGRectMake (shipX - 20.5, shipY - 96, 50, 50), point))
{
allowedToMove = true;
}
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
allowedToMove = false;
}
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
[super dealloc];
}
#pragma mark GameKit delegate
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
#end

Cocos2d 3.0 + Chipmunk + CCAnimation: moving physics body with animated object. How?

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 don't understand Cocos 2D sprite creation behaviour in a loop

with this code monsters don't appear, only hero shows
for (int j = 0; j <= _discrH; j++)
{
for (int i = 0; i <= _discrW; i++)
{
CCSprite * sprite = [CCSprite spriteWithImageNamed:#"monster.png"] ;
sprite.position = ccp([self getCanvasXFromGameI : i],[self getCanvasYFromGameJ : j]);
[_sprites addObject:sprite ];
[self addChild:sprite];
}
}
_hero = [CCSprite spriteWithImageNamed:#"case1.png"];
_hero.position = ccp(0,0);
[self addChild:_hero];
But with this (non-sense) code, the monsters and the hero show, and I don't understand why...
for (int j = 0; j <= _discrH; j++)
{
for (int i = 0; i <= _discrW; i++)
{
CCSprite * sprite = [CCSprite spriteWithImageNamed:#"monster.png"] ;
sprite.position = ccp([self getCanvasXFromGameI : i],[self getCanvasYFromGameJ : j]);
[_sprites addObject:sprite ];
[self addChild:sprite];
}
_hero = [CCSprite spriteWithImageNamed:#"case1.png"];
_hero.position = ccp(0,0);
[self addChild:_hero];
}
Any ideas what I'm doing wrong ?

Resources