Перемещение Box2d тела, как объекты CCSprite

В cocos2d вы можете облегчить CCSprites и перемещать их разными способами. Самое главное - они могут иметь ослабление в / из. Для большинства игр это желательно для плавного движения и т. Д.

id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];

При перемещении тела box2d прикрепленный к нему спрайт обновляется после шага box2d (). Перемещение спрайта, а затем обновление тела здесь не вариант, так как он полностью противоречит цели физической основы.

Итак, другой вариант, который я успешно реализовал, - это рассчитать смещение, скорость и ускорение спрайта, рассматривая его как механический объект самостоятельно. Каждый раз, когда я вызываю свой метод update () для спрайта, чтобы персонаж мог решить, куда двигаться и т. Д., Мой суперкласс также сохраняет предыдущую позицию и скорость. Они сохраняются как совместимые с box2d значения путем деления на PTM_RATIO.

В подклассе CCSprite, называемом FMSprite:

-(CGPoint) displacement {
    return ccpSub(self.position, lastPos);
}

-(b2Vec2) getSpriteVelocity:(ccTime)dt {
    return b2Vec2(self.displacement.x / dt / PTM_RATIO,
                  self.displacement.y / dt / PTM_RATIO);
}

-(b2Vec2) getSpriteAccel:(ccTime)dt {
    b2Vec2 currVel = [self getSpriteVelocity:dt];
    if (dt == 0) {
        return b2Vec2(0,0);
    } else {    
        float accelX = (currVel.x - lastVel.x)/dt;
        float accelY = (currVel.y - lastVel.y)/dt;
        return b2Vec2(accelX, accelY);
    }
}

// This is called each update()
-(void) updateLast:(ccTime)dt {
    // MUST store lastVel before lastPos is updated since it uses displacement
    lastVel = [self getSpriteVelocity:dt];
    lastPos = ccp(self.X, self.Y);
}

// Leave this method untouched in subclasses
-(void) update:(ccTime)dt {
    [self updateObject:dt];

    // Store previous update values
    [self updateLast:dt];
}

// Override this method in subclasses for custom functionality
-(void) updateObject:(ccTime)dt {

}

Затем я подкласс "FMSprite" в "FMObject", который хранит b2Body и т. Д.

Чтобы переместить тело, я должен сначала переместить спрайт и отследить его ускорение, благодаря которому я могу найти требуемую силу (используя массу), необходимую для движения спрайта. Поскольку я не могу переместить спрайт объекта (который синхронизирован с телом), я создаю другой спрайт, называемый «маяком», добавляю его в качестве дочернего к объекту и перемещаю его. Все, что нам нужно сделать, - это иметь функцию для синхронизации положения тела box2d с этим спрайтом маяка, используя силы, которые я упоминал ранее.

-(void) followBeaconWithDelta:(ccTime)dt {
    float forceX = [beacon getSpriteAccel:dt].x * self.mass;
    float forceY = [beacon getSpriteAccel:dt].y * self.mass;
    [self addForce:b2Vec2(forceX, forceY)];
}

Результат блестящий, плавное замедление движения тела b2, куда бы вы ни захотели, без использования каких-либо собственных сил, а скорее копирование CCSprite и копирование его движения. Поскольку это все силы, это не вызовет дрожания и искажений при столкновении с другими объектами b2Body. Если у кого-то есть другие способы сделать это, пожалуйста, оставьте ответ. Спасибо!

Ответы на вопрос(1)

Ваш ответ на вопрос