What is wrong with the coordinate system in this S

2019-03-25 11:07发布

问题:

I created a SKView which presents an SKScene subclass like this:

SKView *skv = [[SKView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:skv];

self.skScene = [[TestScene alloc] initWithSize:v.bounds.size];
[skv presentScene:_skScene];

Then to see coordinate system origin, I add a small 10x10 colored square to the scene.

SKSpriteNode *ori = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(10,10)];
[self addChild:ori];

You can see green square in lower left corner:

From what I thought, SpriteKit coordinate system is such that origin is always in center. But in the scene the origin is in lower left corner. When I add a child node to {0,0} it appears in lower left corner as well.

When I add a SKSpriteNode and position it {0,0} in the scene, it appears in lower left corner. But it is centered around scene origin in lower left corner (clipped off half to left, and half to bottom).

But now it gets more confusing. When I add a SKSpriteNode to another SKSpriteNode, the sub-sprite is CENTERED in the parent.

So does it mean the Scene coordinate system works different than the sprite coordinate system?

Recap:

  • When I position a sprite in scene at {0,0}, it appears in bottom left, clipped off 50% (centered around origin).
  • When I position a sprite in a sprite at {0,0}, it appears centered in the sprite.

Is my Scene configured wrong or is this the way it works?

回答1:

This is the way it works. All OpenGL views (the 2D ones at least) have their origin at the lower left corner.

The position of your sprites is correct too. Both are located at 0,0 by default. The texture of the sprites is drawn relative to the node position based on the anchorPoint factor. It's default value of 0.5, 0.5 places the texture centered on the node's position.

You can change the anchorPoint of the scene to 0.5,0.5 which will move the sprites to the center of the scene. You can also change the sprite's anchorPoint though that isn't recommended since it affects things like rotation, scale, collision detection and child node position.



回答2:

you can add this code to GameViewController.swift :

override func viewDidLoad() {
        super.viewDidLoad()

        // Detect the screensize
        var sizeRect = UIScreen.mainScreen().applicationFrame
        var width = sizeRect.size.width * UIScreen.mainScreen().scale
        var height = sizeRect.size.height * UIScreen.mainScreen().scale

        // Scene should be shown in fullscreen mode
        let scene = GameScene(size: CGSizeMake(width, height))


        // Configure the view.
        let skView = self.view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill

        skView.presentScene(scene)
    }


回答3:

What I did was to set the size of the SKScene you want to show to the bounds.size of the Viewcontroller you want to show the scene from. Something like this:

    if let scene = GameScene(fileNamed:"GameScene") {
        // Configure the view.
        let skView = self.view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true
        scene.size = skView.bounds.size
        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill

        skView.presentScene(scene)
    }

I hope this worked for you as well, if I made any mistakes here, please let me know as well :)