The Drawback
I’ve a set of SKSpriteNodes
inside a GameScene which are positioned in an orderly method i.e. their positions are consistently spaced e.g. (0, 0), (0, 150), (0, 300). I need to have the ability to rotate the entire ships concerning the centroid of their positions and have their heading level to the route during which they’re being rotated to. Please check out the diagram beneath to grasp what I imply:
What I’ve Tried
I’ve tried placing the entire sprite nodes inside a container SKNode
and rotating the SKNode
. This causes the youngsters to rotate as desired since they’re all positioned relative to the father or mother node. Nevertheless, I need to keep away from doing this as I need to have management over every of the person sprite node’s zRotation
and place
as an alternative of ‘dishonest’ and having a container node do it for me.
To repair this, I’ve tried making use of the usual 2D rotation matrix to the positions of the SKSpriteNode
s. The code beneath isn’t an actual duplicate, nevertheless it roughly describes what I’ve tried to do:
@objc func sliderValueDidChange(_ sender: UISlider) {
// simply assume I've entry to the GameScene from the GameViewController
guard let scene = view.scene as? GameScene else { return }
let nodes = scene.nodes
// prevSliderValue is the worth of the slider from the earlier name to
// this perform. the slider has a variety of values from 0 to 359
let angleChange = (prevSliderValue - CGFloat(sender.worth)) / 180 * .pi
// calculating the centroid
var cenX = CGFloat.zero
var cenY = CGFloat.zero
// nodes is a listing of [SKSpriteNodes]
for node in nodes {
cenX += node.place.x
cenY += node.place.y
}
cenX = cenX / CGFloat(nodes.rely)
cenY = cenY / CGFloat(nodes.rely)
// making use of the rotation matrix to every node's place
for node in nodes {
// calculating the brand new place
let newX = node.place.x * cos(angleChange) - node.place.y * sin(angleChange)
let newY = node.place.x * sin(angleChange) + node.place.y * cos(angleChange)
node.place = CGPoint(x: newX, y: newY)
// calculating the brand new angle to level at
// let a = -atan2(node.place.y - cenY, node.place.x - cenX) + .pi/2
// node.zRotation = a
/*
atan2 offers the angle relative to the X axis, however SKSpriteNodes
zRotation are relative to the Y axis, therefore I am including pi/2
moreover, I need a constructive angle of rotation to be clockwise,
so I am negating the return worth of the atan2 perform
*/
}
}
The results of this code has to date been unsuccessful. The nodes are roughly capable of rotate clockwise to about 180º alongside an arc relative to the centroid. However for any worth previous 180º, the nodes mainly cease rotating/transferring and simply spasm on the spot. Making an attempt to reverse the rotation (i.e. going from 180º again to 0º) does trigger the nodes to rotate counterclockwise, however they do not attain to their authentic spot (i.e. their ending place is usually a few levels off from completely vertical). Moreover, if I drag the slider up and down a couple of instances, for no matter purpose which eludes me, the nodes find yourself transferring nearer and nearer till they converge on the centroid.
Is there one thing fallacious with how I am calculating the ultimate positions? I’ve realized that my calculation of newX
and newY
aren’t relative to the centroid however as an alternative are relative to the origin, which messes up my mind much more. I have been caught on this for a couple of days and I can already really feel myself beginning to burn out. Any assist or pointers could be enormously appreciated.