[cocos2d-x 3.0正式版]PhysicsBody添加给Sprite后,再次更新Sprite位置,PhysicsBody出现问题

我Sprite的物理设置是这样的:

       
        Collision *pCollision = Collision::create();
        pCollision->setPosition(x, y);
        pCollision->setRandomPositionYWithRange(_collisionRandomPositionYMaxRange);
        auto body = PhysicsBody::createBox(pCollision->getContentSize());
        body->setDynamic(false);
        body->setContactTestBitmask(CONTACT_TESST_BITMASK);
        pCollision->setPhysicsBody(body);
        _collisions->addObject(pCollision);
        this->addChild(pCollision, ZORDER_COLLISION);

```


然后就是更新Sprite的position:

    
     for (int i = 0; i < _collisions->count(); ++ i)
    {
        Collision *pCollision = (Collision *)_collisions->getObjectAtIndex(i);
        pCollision->setPositionX(pCollision->getPositionX() - this->getGroundSpeed());
    }

```


但是结果就是这样的:
 

如果删掉更新Sprite位置的代码,就是好的了,效果如下:
 

现在我就不明白该怎么搞了,之前用box2d是要自己更新的,但是现在我删了PhysicsBody重新添加都有问题的,不懂了,请各位高手知道的帮忙告知下,非常感谢~

自己顶下贴,这个问题是大家都没遇到还是都不知道啊。。。。。。。。

如果你不是自己继承了setPositionX的话,确实没有看出什么端倪来。
而且这种没有贴出Collision来,最好是换成Sprite来试一下,确实是这样就发Sprite相关的代码。

Collision类的代码基本如下了,是继承于Sprite的:

bool Collision::init()
{
    if (Sprite::init())
    {
        this->extraInit();
        return true;
    }
    else
    {
        return false;
    }
}

void Collision::extraInit()
{
    this->initCollisionSprite();
}

void Collision::initCollisionSprite()
{
    this->Sprite::initWithFile(RESOURCE_IMG_COLLISION);
}

void Collision::setRandomPositionYWithRange(float range)
{
    float randomPositionY = CCRANDOM_0_1() * range;
    
    this->setPositionY(randomPositionY);
}

Size Collision::getCollisionSize()
{
    Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(RESOURCE_IMG_COLLISION);
    return texture->getContentSize();
    
}


```


基本没有做什么特别特殊的实情,都是常规设置sprite的方法了。

再自己顶一下,还是没有弄明白这个问题,有没有高手来解释下的,或者有碰到过同类问题的朋友?

由于我在公司的时候没有Coco2dx的环境,没有看到,刚看了下,发现Sprite类是没有重载setPositionX这个方法的。
也就是直接是调用Node 的setPositionX方法。但看setPosition在Sprite里面是会调用SET_DIRTY_RECURSIVELY();
所以请楼主pCollision->setPosition(Point(pCollision->getPositionX() - this->getGroundSpeed(), pCollision->getPositionY()));试一下。
由于平常我习惯了这样调用,所以没有遇见过你这种情况。:2::2::2:

我试了下,没有效果,和之前是一样的,真是纠结,这个问题。

很久之前玩了下 3.0rc0的物理系统,给Node::setPostion打了个补丁:
不过还有别的坑,似乎,也懒的查了。
大概意思是 setPostion 没遍历子节点修改物理世界坐标,导致有些子节点位置不正常,也不知道设计如此还是有问题。
不知你的是不是这个问题

+void Node::adjBodyPosition()
+{

  •   if (_physicsBody)
    
  • {
  •    Node* parent = getParent();
    
  •    Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
    
  •    _physicsBody->setPosition(pos);
    
  • }
  • for( const auto &child: _children)
  •    child->adjBodyPosition();
    

+}

void Node::setPosition(const Point& position)
{
@@ -418,12 +431,7 @@
_transformUpdated = _transformDirty = _inverseDirty = true;

#if CC_USE_PHYSICS

  • if (_physicsBody)
  • {
  •    Node* parent = getParent();
    
  •    Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
    
  •    _physicsBody->setPosition(pos);
    
  • }
  •   this->adjBodyPosition();
    

#endif

我写了个测试了,没有问题:

//Edge
auto sprite = Sprite::create();
auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
body->setDynamic(false);
body->setCollisionBitmask(0x01);
sprite->setPosition(origin + Point(visibleSize.width/2, visibleSize.height/2));
sprite->setPhysicsBody(body);
this->addChild(sprite, 0, 0x01);

//
mTarget = Sprite::create("CloseNormal.png");
body = PhysicsBody::createBox(mTarget->getContentSize());
body->setGravityEnable(false);
body->setCollisionBitmask(0x01);
body->setCategoryBitmask(0x02);
mTarget->setPhysicsBody(body);
mTarget->setPosition(origin + Point(visibleSize.width/2, visibleSize.height/2));
this->addChild(mTarget, 1, 0x02);

/* 这里函数参数貌似变了,太晚了,不研究了!
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = (EventCustom* event, const PhysicsContact& contact){
auto spriteA = dynamic_cast<Sprite*>(contact.getShapeA()->getBody()->getNode());
auto spriteB = dynamic_cast<Sprite*>(contact.getShapeB()->getBody()->getNode());
int tagA = spriteA->getTag();
int tagB = spriteB->getTag();

    CCLOG("A: " + tagA);
    CCLOG("B: " + tagB);

    return true;
};
auto dispatcher = Director::getInstance()->getEventDispatcher();
dispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

*/

this->schedule(schedule_selector(HelloWorld::contactCallback), 0.2f);

这样是没有问题,我是在设置完位置,设置完physicsBody后,不断重新设置sprite的position时出现的问题,只是检测碰撞没有什么问题。

this->schedule(schedule_selector(HelloWorld::contactCallback), 0.2f);
我这里调用了
mTarget->setPositionX(mTarget ->getPositionX() + 5);
没有遇到你说的问题。

奇怪,我再查查,谢谢啦,你也是用的3.0的正式版吗?