Cocos2d 3.0 + Chipmunk + CCAnimation:使用动画对象移动物理体。怎么样? [英] Cocos2d 3.0 + Chipmunk + CCAnimation: moving physics body with animated object. How?

查看:216
本文介绍了Cocos2d 3.0 + Chipmunk + CCAnimation:使用动画对象移动物理体。怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有物理体的船。这艘船是静态物理体。船从CCAnimateMoveTo从左到右移动。当我点击屏幕上我的字符下降。我很好地检测碰撞。但我想要碰撞后我的性格只是落在船上,并继续与它一起移动。字符是动态身体。链接到示例视频:示例视频

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

此处我创建了一个船:

- (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]];
}

角色创建:

- (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;
    }
}

然后检测触摸和碰撞:

- (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;
}


推荐答案

问题,尝试增加摩擦/表面速度等,它没有真正工作得很好。
最后不得不以我自己的方式解决它,每当玩家到达任何身体,你保留一个指针到该身体,如玩家对象的_bodyUnderFeet。
现在,在更新循环中,将_bodyUnderFeet的速度添加到玩家计算的速度。查看zeroVel_x的使用

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

示例代码在这里:

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);
}

这篇关于Cocos2d 3.0 + Chipmunk + CCAnimation:使用动画对象移动物理体。怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆