Установить постоянную ориентацию изображения SKSpritenode
Привет, у меня есть несколько круглых узлов SKSpriteNode с круговым физическим телом. Теперь, когда эти шары катятся по дорожке, я хочу, чтобы некоторые из этих изображений SKSpritenodes оставались в вертикальном положении, даже когда катились. Так что подумайте о стрелке, направленной вверх. Когда мяч начинает катиться, стрелка вращается по кругу. Но для некоторых шаров хотелось бы, чтобы стрелка оставалась направленной вверх, даже когда мяч катится. Каков наилучший способ сделать это?
редактировать
Таким образом, ответ был дан, но из тестирования выяснилось, что он не правильный. Отказ от вращения мяча влияет на то, как он катится по дорожке. Поэтому я думаю, что я хочу, чтобы вращение было включено, но изображение всегда должно отображаться пользователю, как будто оно не вращается. Благодарю.
3 ответа
Это похоже на работу для Superm SKConstraint
, Ограничения оцениваются и применяются после того, как физическое моделирование выполняется в каждом кадре, поэтому вы можете использовать их для таких задач, как наведение узла на определенное направление независимо от того, что с ним делает физика. Для этого вы бы хотели zRotation
ограничение.
Но это еще не все. Если вы установили ограничение вращения на ноль на шаре:
// Swift
let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
ball.constraints = [constraint]
Вы обнаружите, что SpriteKit сбрасывает преобразование физического тела в каждом кадре из-за ограничений, так что он только ведет себя как вращение. Наверное, не то, что вы хотите. (Чтобы лучше понять, что здесь происходит, попробуйте добавить ограничение нулевого вращения в прямоугольное физическое тело в мире без гравитации, применив к нему угловой импульс и наблюдая, как оно пытается вращаться в представлении с showsPhysics
включенный. Вы увидите, что спрайт и его физическое тело вышли из синхронизации и немного встряхнулись - возможно, из-за накопленных ошибок округления, когда физический движок и механизм ограничений борются с этим.)
Вместо этого вы можете сделать что-то из того, что есть в ответе 0x141E, но используйте ограничения, чтобы сделать его меньше кода (и работать более эффективно):
- Дайте шариковому узлу круглое физическое тело. (И, возможно, нет текстуры, если единственное искусство, которое вы хотите для мяча, это не вращающийся спрайт.)
- Добавьте узел стрелки как дочерний элемент узла ball. (Ему не нужно свое физическое тело.)
- Поместите ограничение нулевого вращения на стрелку.
Подождите, это не работает - я сказал стрелке не вращаться, но она все еще вращается?! Помните, что дочерние узлы расположены (и повернуты и масштабированы) относительно их родительского узла. Таким образом, стрелка не вращается относительно шара, но шар вращается. Не волнуйтесь, вы все еще можете решить это с ограничением:
- Скажите ограничению действовать относительно узла, содержащего шар (вероятно, сцену).
Теперь ограничение будет удерживать стрелку на месте, позволяя мячу вращаться так, как этого хочет физическое моделирование.
Вот некоторый тестовый код для иллюстрации:
// Step 1: A rectangular spinner so we can see the rotation
// more easily than with a ball
let spinner = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 300, height: 20))
spinner.position.x = scene.frame.midX
spinner.position.y = scene.frame.midY
spinner.physicsBody = SKPhysicsBody(rectangleOfSize: spinner.size)
scene.addChild(spinner)
spinner.physicsBody?.applyAngularImpulse(0.1) // wheeeeee
// Step 2: Make the arrow a child of the spinner
let arrow = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 20, height: 50))
spinner.addChild(arrow)
// Step 3: Constrain the arrow's rotation...
let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
arrow.constraints = [constraint]
// Step 4: ...relative to the scene, instead of to its parent
constraint.referenceNode = scene
Вот два способа создать шар с физическим телом и стрелкой:
- Добавить стрелку как ребенка от шара
- Добавьте мяч и стрелу прямо на сцену
Вот что произойдет, когда вы добавите вышеперечисленное в симуляцию SpriteKit:
- Стрелка будет вращаться, когда шар вращается
- И стрелка, и шар будут двигаться / вращаться независимо
Если вы хотите, чтобы стрелка вращалась вместе с шариком, выберите вариант 1. Если вы хотите, чтобы стрелка оставалась неподвижной, выберите вариант 2. Если вы выберете вариант 2, вам нужно будет отрегулировать вращение стрелки, чтобы она указывала вверх., Вот пример того, как это сделать.
-(void)didMoveToView:(SKView *)view {
self.scaleMode = SKSceneScaleModeResizeFill;
/* Create an edge around the scene */
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:view.frame];
// Show outline of all physics bodies
self.view.showsPhysics = YES;
CGFloat radius = 16;
SKNode *balls = [SKNode node];
balls.name = @"balls";
[self addChild:balls];
// Create 5 balls with stationary arrows
for (int i = 0;i<5;i++) {
// Create a shape node with a circular physics body. If you are targeting iOS 8,
// you have other options to create circular node. You can also create an SKSpriteNode
// with a texture
SKShapeNode *ball = [SKShapeNode node];
// Create a CGPath that is centered
ball.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-radius,-radius,radius*2,radius*2)].CGPath;
ball.fillColor = [SKColor whiteColor];
ball.position = CGPointMake(100, 100+i*radius*2);
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
[balls addChild:ball];
// Create an arrow node
CGSize size = CGSizeMake(2, radius*2);
SKSpriteNode *arrow = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:size];
arrow.name = @"arrow";
arrow.position = CGPointZero;
[ball addChild:arrow];
// Apply angular impulse to the ball so it spins when it hits the floor
[ball.physicsBody applyAngularImpulse:-1];
}
}
- (void) didSimulatePhysics
{
SKNode *balls = [self childNodeWithName:@"balls"];
for (SKNode *ball in balls.children) {
SKNode *arrow = [ball childNodeWithName:@"arrow"];
arrow.zRotation = -ball.zRotation;
}
}
sprite.physicsBody.allowsRotation = NO;
Свойство allowRotation должно точно контролировать то, что вы запрашиваете.