В cocos2d вы можете упростить CCSprites и перемещать их различными способами. Самое главное - у них может быть easing in/out. Для большинства игр это желательно для плавного движения и т. д.
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)];
}
Результат блестящий, плавное плавное движение тела b2body, перемещающегося туда, куда вы хотите, без игры с какими-либо его собственными силами, а скорее копируя движение CCSprite и повторяя его движение. Поскольку это все силы, он не будет вызывать дрожание и искажения при столкновении с другими объектами b2Body. Если у кого-то есть другие способы сделать это, пожалуйста, напишите ответ. Спасибо!
FMObject
. - person Aram Kocharyan   schedule 16.06.2014