Confusion about coordinates, frames, and child nodes in SpriteKit on iOS?

I still play with learning SpriteKit on iOS and read a lot and experiment a lot. I am confused by what I found * regarding coordinates, frames, and child nodes.

Consider this piece of code in which I am trying to draw a green box around my spaceship sprite for debugging purposes:

func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" // VERSION 1 spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) let debugFrame = SKShapeNode(rect: spaceship.frame) debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) // VERSION 2 // spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) spaceship.setScale(0.50) self.addChild(spaceship) } 

If I add a spacecraft sprite set with a line labeled “VERSION 1” above, I get the following:

Version 1

which is clearly wrong. But if I comment on the line labeled “VERSION 1” above and instead use the line labeled “VERSION 2”, I get what I want:

Version 2

Please note that the actual code for the lines marked “Version 1” and “Version 2” is identical: spacehip.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame))

So why does it matter when I set the position of the sprite of a spaceship?

In my way of thinking, the position of the spacecraft sprite is not related to the placement of the debugFrame, because debugFrame is a child of the spacecraft sprite, and therefore its coordinates should refer to the frame of the spacecraft sprite - on the right

Thanks WM

* This is somewhat related to the question I asked yesterday:

On SpriteKit on iOS, scaling a textured sprite creates the wrong frame?

but a) I understand that now, and b) it is completely different that he deserves his own question.

UPDATE:

Hmmm - thanks guys for the ideas below, but I still don’t understand, and maybe this will help.

I changed my code to print relavant positions and frames:

 func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" println("Spaceship0 Pos \(spaceship.position) Frame = \(spaceship.frame)") // VERSION 1 (WRONG) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) println("Spaceship1 Pos \(spaceship.position) Frame = \(spaceship.frame)") let debugFrame = SKShapeNode(rect: spaceship.frame) println("DEBUG Pos \(debugFrame.position) Frame = \(debugFrame.frame)") debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) // VERSION 2 (RIGHT) // spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) // println("Spaceship2 Pos \(spaceship.position) Frame = \(spaceship.frame)") spaceship.setScale(0.50) self.addChild(spaceship) } 

Then I ran in both directions, getting these results. Since I understand version 2, let's get started there.

Running the code "VERSION 2 (RIGHT)", I got:

 Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) DEBUG Pos (0.0,0.0) Frame = (-159.5,-300.5,319.0,601.0) Spaceship2 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) 

The spaceship node starts by default its position in the lower left corner of the screen (Spaceship0). Its frame is also expressed through its reference point (in the center), set in the lower left corner of the screen, therefore, negative numbers for the beginning of its rectangular frame.

Then a debug frame is created with the default position of 0, 0, and its frame is set to the same as that of the spacecraft.

Then the code (Spaceship2) moves the spacecraft node to a position in the coordinates of the view (384.0, 512), and its beginning of the frame is moved by adding a new position to the old one (i.e. 384 + -159 = 225).

Things are good.

Unfortunately, I still do not get version 1.

When I run "VERSION 1 (WRONG)" code, I get

 Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) Spaceship1 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) DEBUG Pos (0.0,0.0) Frame = (0.0,0.0,543.5,812.5) 

As above, the spaceship node starts by default its position in the lower left corner of the screen (Spaceship0). Its frame is also expressed through its reference point (in the center), set in the lower left corner of the screen, therefore, negative numbers for the beginning of its rectangular frame.

Then the code (Spaceship1) moves the spacecraft node to a position in the coordinates of the view (384.0, 512), and its beginning of the frame is moved by adding a new position to the old origin (i.e. 384 + -159 = 225).

Then a debug frame is created with the default position of 0, 0, and its frame has a strange width (543.5) and a strange height (812.5). Since I initialize debugFrame.frame with spacehip.frame (I think the default initializer does this), I expect the new debugFrame.frame to be the same as the spacecraft frame, but it is not! The values ​​of the width and height of the debugging frame are apparently associated with the addition of the actual width and height to the beginning of the frame of the spacecraft node (543.5 = 225 + 318.5). But if so, then why is the t-shaped direct origin still 0, 0 and not the same addition (225.0 + 0 = 225.0) ???

I do not understand.

+7
ios swift sprite-kit skspritenode skshapenode
source share
3 answers

You create a node shape using the sprite frame, which is located in the coordinates of the scene. Since the form will be the daughter of the sprite, you must create a node in the coordinates of the sprite. For example, if you create an SKShapeNode with a spacecraft size

 let debugFrame = SKShapeNode(rectOfSize: spaceship.size) 

instead of using the spacecraft frame, the debugFrame will center on the spacecraft, regardless of when you set the position of the ship. In addition, debugFrame will scale / move accordingly with the ship.

+7
source share

In response to your "I do not understand." Your code is ok but has a logical problem. The "frame" is calculated relative to the original coordinates. Keep in mind that the parent of the spaceship and the parent of the debug window are different in your code.

Two ways to solve your problem:

  • Add a zero offset for the debug window and use the spaceship as a parent. The advantage of this is that the debug window will be moved, scaled using the spaceship: let rectDebug = CGRectMake( 0, 0, spaceship.frame.size.width, spaceship.frame.size.height) let debugFrame = SKShapeNode(rect:rectDebug) spaceship.addChild(debugFrame)
  • Add a debug window with the coordinates of the 'frame' of the spacecraft to the parent object of the spacecraft (which is the "I"). The disadvantage of this is that you need to navigate, scale the debug window yourself in the code, since it will not be attached to the spaceship: let debugFrame = SKShapeNode(rect:spaceship.frame) self.addChild(debugFrame)

Both solutions are widely used. You must choose what is best for you in your case. Three more problems may arise:

1. There may be code errors in my code, I just typed them in a web window directly without checking the xcode syntax.

2. Anchor points of two objects can be different. For this, you may need alignment in your code.

3. It is necessary to take into account the location of objects, so these objects will not be hidden under some other objects.

In response to the problem you are trying to solve, perhaps showPhysics will help:

  skView.showsFPS = YES; skView.showsNodeCount = YES; skView.showsPhysics = YES; 
+1
source share

This is almost the same problem as in the other question you mentioned. frame is a property containing position and a size . Both of them are subject to scaling of their ancestor node. The section “A Node applies many of its properties to its descendants” at https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html#//apple_ref/doc/uid/TP40013043 -CH3-SW13

Again: never apply scaling to node, never move Node before completely constructing your hierarchy, except when you need some special or strange effect.

0
source share

All Articles