In iOS 9, why are SKNodes blurry? - ios

I have a SceneKit game that I'm developing. In iOS 9, when SceneKit's depth of field is turned on, SKNodes on the 2D Overlay scene are blurred.
This code even blurs the 2D overlay node, but none of the others:
// focal blur.
[DDCamera sharedCamera].camera.zNear = 1;
[DDCamera sharedCamera].camera.zFar = 100;
[DDCamera sharedCamera].camera.focalDistance = 25;
[DDCamera sharedCamera].camera.focalSize = 25;
[DDCamera sharedCamera].camera.focalBlurRadius = 50;
DDCamera is a subclass of SCNNode that allows other classes to manipulate the camera. Its position is (0, 0, 25).
I put in a SKNode on the overlay scene, like this:
title = [SKLabelNode labelNodeWithText:[DDCommonFunctions getLocalizedStringFromKey:#"title"]];
title.fontColor = [UIColor whiteColor];
title.fontName = DDDefaultFont;
title.fontSize = 100.;
title.position = CGPointMake([DDCommonFunctions getScreenSize].width * .5, [DDCommonFunctions getScreenSize].height * 0.75);
title.name = #"title";
title.alpha = 1.;
title.zPosition = 0.;
[self addNode:title];
Every other node I put into the scene isn't blurry, but the only SKNode there is blurred. Why is this?
Also, why didn't this behavior occur in iOS 8.4.1?
EDIT: a screenshot:
EDIT 2: It works as expected in OpenGL. Why not Metal? How would I get the camera to focus on the 2D scene?

Related

How to prevent the camera from entering a SCNNode - Scenekit iOS

I have a problem whit the camera in SceneKit, by default i can move, rotate, zoom my camera whit this line :
myView.allowsCameraControl = YES;
But my camera can pass through walls and floor (which allows me to see the underside of the stage ) .
My first request: is it possible to apply constraints to the camera (position, rotation) ?
My second request: I thought making a cube encompassing stage and do my collision detection between my cube and my camera, but it does not work ...
code for viewDidLoad:
SCNView *myView = (SCNView *)self.view3D;
myView.scene = [SCNScene sceneNamed:#"art.scnassets/Pointe Marrin 3 def 3 def 2.dae"];
myView.scene.physicsWorld.contactDelegate = self;
myView.scene.physicsWorld.gravity = SCNVector3Make(0, 0, 0);
cubeLimite = [myView.scene.rootNode childNodeWithName:#"Cube" recursively:YES];
camera = [myView.scene.rootNode childNodeWithName:#"Caméra" recursively:YES];
cubeLimite.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];
cubeLimite.physicsBody.mass = 0;
cubeLimite.categoryBitMask = SCNPhysicsCollisionCategoryDefault;
cubeLimite.physicsBody.collisionBitMask = SCNPhysicsCollisionCategoryAll;
//test camera
CGFloat boxSide = 0.001;
SCNBox *box = [SCNBox boxWithWidth:boxSide
height:boxSide
length:boxSide
chamferRadius:0];
SCNNode *boxNode = [SCNNode nodeWithGeometry:box];
SCNPhysicsShape *shape = [SCNPhysicsShape shapeWithGeometry:boxNode.geometry options:nil];
camera.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];
camera.physicsBody.mass = 0;
camera.categoryBitMask = SCNPhysicsCollisionCategoryDefault;
camera.physicsBody.collisionBitMask = SCNPhysicsCollisionCategoryAll;
Code for delegate :
- (void)physicsWorld:(SCNPhysicsWorld *)world
didBeginContact:(SCNPhysicsContact *)contact{
NSLog(#"Contact debut");
}
- (void)physicsWorld:(SCNPhysicsWorld *)world
didUpdateContact:(SCNPhysicsContact *)contact{
NSLog(#"Contact milieu");
}
- (void)physicsWorld:(SCNPhysicsWorld *)world didEndContact:(SCNPhysicsContact *)contact{
NSLog(#"Contact fin");
}
The delegate :
SCNPhysicsContactDelegate
is declared in the .h file
Ideas ?
thank you beforehand
It's not possible, as far as I know, to constrain the default camera when allowsCameraControl is enabled.
The answer to Rotate SCNCamera node looking at an object around an imaginary sphere outlines an approach that might work for you, depending on what constraints you need to build.

Maintain Sprite position relative to frame/screen when auto-scaling from iphone 5 to 6?

I've developed a game in SpriteKit for a 5s. All my sprites are positioned just where I want them when I run the Xcode simulator on a 4s, 5 or 5s:
http://tinypic.com/r/f0yanl/8
But when I run it on a 6 my sprites are not positioned correctly, and some are even placed off the entire frame/screen:
http://tinypic.com/r/akdac7/8
Notice my HUD is showing up top out of the frame, and the shadow and positioning of my "Machine" at the bottom is off, etc.
Is there a quick, simple fix to ensure the sprites maintain their position relative to my background image, when running on a 6? For now, I'm OK with the entire screen being collapsed a bit when running on a 6 (with empty borders on all four sides), but I would like to make sure everything at least looks just as clean and in order as it does on a 5.
I've used anchor points for most of my nodes, for e.g.:
+ (instancetype) machineAtPosition:(CGPoint)position {
GameMachineNode *machine = [self spriteNodeWithImageNamed:#"machine_1"];
machine.position = position;
machine.name = #"Machine";
machine.anchorPoint = CGPointMake(0.5, 0);
....
}
My "GameViewController.m" includes a resize to fill mode:
SKScene * scene = [GameTitleScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeResizeFill;
Update: figured it out. Was as simple as adding this single line of code to the initWithSize method:
background.size = self.frame.size;
Full code block for reference:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.lastUpdateTimeInterval = 0; //initializing this property
self.timeSinceEnemyAdded = 0; //initializing this property
self.addEnemyTimeInterval = 1.25;
self.totalGameTime = 0;
self.minSpeed = GameAstroDogMinSpeed;
self.restart = NO;
self.gameOver = NO;
self.gameOverDisplayed = NO;
// Setup your scene here....
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"background_1"];
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
background.size = self.frame.size;

Sprite Kit - SKSpriteNode drawn at wrong position

Whenever i try to draw a SKSpriteNode, it would be drawn lower than it should be.
But it seems that other SKSpriteNode works fine with no problems.
This is my current code:
func initMainGround() {
let gSize = CGSizeMake(self.size.width/4*3, 120);
ground = SKSpriteNode(color: SKColor.brownColor(), size: gSize);
ground.name = gName;
ground.position = CGPointMake(0, 0);
ground.physicsBody = SKPhysicsBody(rectangleOfSize: ground.size);
ground.physicsBody.restitution = 0.0;
ground.physicsBody.friction = 0.0;
ground.physicsBody.angularDamping = 0.0;
ground.physicsBody.linearDamping = 0.0;
ground.physicsBody.allowsRotation = false;
ground.physicsBody.usesPreciseCollisionDetection = true; //accurate collision
ground.physicsBody.affectedByGravity = false;
ground.physicsBody.dynamic = false;
ground.physicsBody.categoryBitMask = gBitmask;
ground.physicsBody.collisionBitMask = pBitmask;
self.addChild(ground);
}
func addBomb() {
let bomb = SKSpriteNode(imageNamed: "trap");
bomb.size = CGSizeMake(30, 30);
bomb.position = CGPointMake(ground.position.x, actualY+10);
bomb.physicsBody = SKPhysicsBody(circleOfRadius: bomb.size.width/2);
bomb.physicsBody.restitution = 0.0;
bomb.physicsBody.allowsRotation = false;
bomb.physicsBody.usesPreciseCollisionDetection = true;
bomb.physicsBody.affectedByGravity = false;
bomb.physicsBody.dynamic = false;
bomb.physicsBody.categoryBitMask = bBitmask;
bomb.physicsBody.collisionBitMask = pBitmask;
bomb.physicsBody.contactTestBitMask = pBitmask;
self.addChild(bomb);
}
Although the bomb is suppose to be almost directly above the ground, but it seems that the bomb is almost 100+ above the ground instead.
The ground is suppose to fill up almost one third of the screen height since the game is in landscape, but it is way lower than normal.
Why is it that the ground is drawn at the wrong position, but the bomb is drawn at the correct position?
This sounds like the same problem I had when starting to work with SpriteKit. If your game uses an .sks file to present it's main scene (as it does by default), this scene uses arbitrary dimension values defined in the .sks file.
Try setting the dimensions of your scene dynamically to see if this is the case.
In your didMoveToView function, add something like this at the top of the function:
self.size = view.bounds.size
This way the dimension values from the .sks file will be overridden with your actual screen dimensions.
Hope this helps!
Set the anchorPoint on your ground image.
ground.anchorPoint = CGPointZero // same as CGPointMake(0, 0)
ground.position = CGPointZero
The default anchorPoint is (0.5, 0.5), the center of the image. So without it set, the center of the ground image is drawn in the lower left corner of the screen (0, 0).
Your bomb draws where you expect it for the same reason, the center is placed at the position you specified.

(Spritekit) iPad resolution not 1024x768?

I'm trying to set a background texture and I want it to cover the entire screen.
I prepared the background files exactly to size in photoshop before hand. There are 2 files in my project:
background.png - 1024x768px
background#2x.png - 2048x1536px
I am running the following code:
SKTexture *backgroundTexture = [SKTexture textureWithImageNamed:#"background"];
SKSpriteNode *background = [SKSpriteNode spriteNodeWithTexture:backgroundTexture];
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
background.size = CGSizeMake(750, 550);
[self addChild:background];
And it is giving me this result http://d.pr/i/Ej2m - notice that the entire screen is almost filled and the background size is background.size = CGSizeMake(750, 550). Why is this?
You manually changed the sprite's size:
background.size = CGSizeMake(750, 550);
So it will display in a smaller region (750x550) than its original size (1024x768). Allow me to say: d'uh! ;)

Sprite Kit low performance with multiple nodes in one location

I have set up a scene with 200 sprite nodes and place them randomly on the screen like this:
for(int i = 0; i < bubbleCount; i++) {
CGSize size = [self getRandomSize];
SKSpriteNode *bubble = [SKSpriteNode spriteNodeWithTexture:texture size:size];
bubble.anchorPoint = CGPointMake(0.5, 0.5);
bubble.position = [self getRandomPosition];
bubble.name = BUBBLE;
SKPhysicsBody *physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:size.width/2];
physicsBody.dynamic = YES;
physicsBody.affectedByGravity = NO;
physicsBody.allowsRotation = NO;
physicsBody.categoryBitMask = 0;
physicsBody.contactTestBitMask = 0;
physicsBody.collisionBitMask = 0;
bubble.physicsBody = physicsBody;
[self addChild:bubble];
}
As long as nodes keep distance from each other I get stable 60 fps. When I apply force so that nodes start moving towards the center of the scene and overlap each other, performance decreases dramatically to 2-3 fps. I guess it is related to collision detection and not rendering (if I initialize physics body with bigger radius, performance is very low already at the beginning). I have set category, contact and collision masks to 0, but it does not help.
Your best bet may be to pre-render this scenario instead of forcing the iPhone to go through 200 bodies of collision detection, which will undoubtedly cause strain.

Resources