Боковая прокрутка SpriteKit не обновляет физику WorldWorld
Следуя приведенному здесь примеру (кроме Objective C) и стандартной документации Apple, я обнаружил, что physicsWorld
не обновляет свои позиции, когда myWorld
обновляет свою позицию. Я включил showsPhysics
на моем skView, чтобы проверить это. Смотрите эти скриншоты.
Перед любым движением: После небольшого движения Становится немного дальше И как раз перед контактом
Вот мой код для центрирования myWorld
, Большая часть длины происходит из-за того, что я чрезвычайно многословен в отношении границ.
- (void)centerOnNode:(SKNode *)monkeyNode
{
CGPoint monkeyPosition = monkeyNode.position;
// Check if monkey died
if (monkeyPosition.y < myWorld.frame.origin.y - sceneHeight/2) {
[self monkeyDied];
}
// Check if monkey won
if (monkeyPosition.x > skyFarRightSide.x) {
[self monkeyWon:monkeyNode];
}
// Define limits
CGFloat scrollTopLimit = skyFarTopSide.y - sceneHeight/2;
CGFloat scrollBottomLimit = 0;
CGFloat scrollLeftLimit = 0;
CGFloat scrollRightLimit = skyFarRightSide.x - sceneWidth/2;
// Normal (no limits hit) scrolling
if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit && monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) {
[myWorld setPosition:CGPointMake(-monkeyPosition.x, -monkeyPosition.y)];
}
// At far left scrolling
if (monkeyPosition.x < scrollLeftLimit) {
// No y limits hit
if (monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) {
[myWorld setPosition:CGPointMake(0, -monkeyPosition.y)];
}
// Bottom limit hit
if (monkeyPosition.y < scrollBottomLimit) {
[myWorld setPosition:CGPointMake(0, 0)];
}
// Top limit hit
if (monkeyPosition.y > scrollTopLimit) {
[myWorld setPosition:CGPointMake(0, -scrollTopLimit)];
}
}
// At far right scrolling
if (monkeyPosition.x > scrollRightLimit) {
// No y limits hit
if (monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) {
[myWorld setPosition:CGPointMake(-scrollRightLimit, -monkeyPosition.y)];
}
// Bottom limit hit
if (monkeyPosition.y < scrollBottomLimit) {
[myWorld setPosition:CGPointMake(-scrollRightLimit, 0)];
}
// Top limit hit
if (monkeyPosition.y > scrollTopLimit) {
[myWorld setPosition:CGPointMake(-scrollRightLimit, -scrollTopLimit)];
}
}
// At far bottom scrolling
if (monkeyPosition.y < scrollBottomLimit) {
// No x limits hit
if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit) {
[myWorld setPosition:CGPointMake(-monkeyPosition.x, 0)];
}
// Left limit hit
if (monkeyPosition.x < scrollLeftLimit) {
[myWorld setPosition:CGPointMake(0, 0)];
}
// Right limit hit
if (monkeyPosition.x > scrollRightLimit) {
[myWorld setPosition:CGPointMake(-scrollRightLimit, 0)];
}
}
// At far top scrolling
if (monkeyPosition.y > scrollTopLimit) {
// No x limits hit
if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit) {
[myWorld setPosition:CGPointMake(-monkeyPosition.x, -scrollTopLimit)];
}
// Left limit hit
if (monkeyPosition.x < scrollLeftLimit) {
[myWorld setPosition:CGPointMake(0, -scrollTopLimit)];
}
// Right limit hit
if (monkeyPosition.x > scrollRightLimit) {
[myWorld setPosition:CGPointMake(-scrollRightLimit, -scrollTopLimit)];
}
}
}
Есть ли элегантный способ исправить это? Пока что моя единственная идея - включить больше кода в centerOnNode
который сбрасывает позиции каждого physicsBody
в myWorld
,
2 ответа
Я не знаю, что изменилось за последние 2 года, но другой ответ здесь больше не работал. Вместо этого теперь я комбинирую положение сегментов веревки с родительским (полная веревка). Так что я просто делаю
CGPoint convertedRopePosition = CGPointMake(ropePhysicsBody.node.parent.position.x + ropePhysicsBody.node.position.x, ropePhysicsBody.node.parent.position.y + ropePhysicsBody.node.position.y);
SKPhysicsJointPin *jointPin = [SKPhysicsJointPin jointWithBodyA:monkeyPhysicsBody bodyB:ropePhysicsBody anchor:convertedRopePosition];
Это необходимо, поскольку сегмент веревки расположен под полной длиной веревки, поэтому его положение относительно всей веревки, а не сцены.
Я заметил, что как только обезьяна вступает в контакт, все физические тела возвращаются на свои места. Тем не менее, суставы anchorPoint
заканчивается в неправильном месте.
Я добавил следующий удобный метод в свой GameScene.m.
-(CGPoint)convertSceneToFrameCoordinates:(CGPoint)scenePoint
{
CGFloat xDiff = myWorld.position.x - self.position.x;
CGFloat yDiff = myWorld.position.y - self.position.y;
return CGPointMake(scenePoint.x + self.frame.size.width/2 + xDiff, scenePoint.y + self.frame.size.height/2 + yDiff);
}
Я использую этот метод для добавления суставов. Он обрабатывает все преобразования системы координат, которые необходимо решить, что приводит к проблеме, поднятой в этом вопросе. Например, как я добавляю суставы
CGPoint convertedRopePosition = [self convertSceneToFrameCoordinates:ropePhysicsBody.node.position];
SKPhysicsJointPin *jointPin = [SKPhysicsJointPin jointWithBodyA:monkeyPhysicsBody bodyB:ropePhysicsBody anchor:convertedRopePosition];
jointPin.upperAngleLimit = M_PI/4;
jointPin.shouldEnableLimits = YES;
[self.scene.physicsWorld addJoint:jointPin];