SceneKit App fails with EXC_BAD_ACCESS on iOS9 - objective-c

We've bumped into a problem with one of our apps that uses SceneKit when deployed on iOS9. The app works great on iOS8.0-8.4, but when deployed on iOS9, it immediately crashes. Looking at the crash logs, we are seeing an EXC_BAD_ACCESS exception in a thread. The specific error states com.apple.scenekit.renderingQueue.SCNView Thread 11 crashed. Thinking that it was somehow related to the complexity of the scene, we dropped the scene back to nothing but a 3d box, and the app still crashes. The code that renders the box is as follows. It seems awfully simple to be crashing. And it's very weird that this runs fine on everything prior to iOS9 and runs fine on the simulator for iOS9. It only crashes when deployed. (This is an Enterprise app).
The crash occurs on the line of code that reads:
[scene.rootNode addChildNode:boxNode];
What am I missing?? Thanks for any help.
#implementation TreasureChestViewController
#synthesize sceneView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Create the SCNView
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Add scene an empty scene
scene = [SCNScene scene];
// Set the scene to the view
sceneView.scene = scene;
// Create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.position = SCNVector3Make(0,15, 30);
[scene.rootNode addChildNode:cameraNode];
// Create and add a light to the scene
SCNLight *spotLight = [SCNLight light];
spotLight.type = SCNLightTypeSpot;
spotLight.color = [UIColor whiteColor];
SCNNode *spotLightNode = [SCNNode node];
spotLightNode.light = spotLight;
spotLightNode.position = SCNVector3Make(0, cameraNode.position.y, 20);
[cameraNode addChildNode:spotLightNode];
// A square box
CGFloat boxSide = 15.0;
SCNBox *box = [SCNBox boxWithWidth:boxSide
height:boxSide
length:boxSide
chamferRadius:0];
SCNNode *boxNode = [SCNNode nodeWithGeometry:box];
// boxNode.transform = CATransform3DMakeRotation(M_PI_2/3, 0, 1, 0);
[scene.rootNode addChildNode:boxNode];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end

Related

Accelerometer cocos2d spritebuiilder cant get it to work

I am trying to use the accelerometer in my spritebuidler cocos2d project.I tried to follow https://www.makeschool.com/gamernews/371/accelerometer-with-cocos2d-30-and-ios-7 which seems pretty straight forward but it doesnt seem to work for me. I have tried downloading their git example but the project wont build.
my code is below
#import "GameOverScene.h"
#import <CoreMotion/CoreMotion.h>
#implementation GameOverScene{
CCButton *_restartButton;
CMMotionManager *_motionManager;
CCLabelTTF *_label;
}
- (id)init
{
if (self = [super init])
{
_label= [CCLabelTTF labelWithString:#"X" fontName:#"Arial" fontSize:48];
[self addChild:_label];
_motionManager = [[CMMotionManager alloc] init];
}
return self;
}
-(void)restartButtonClicked {
CCScene *scene = [CCBReader loadAsScene:#"MainScene"];
[[CCDirector sharedDirector] replaceScene:scene withTransition:[CCTransition transitionPushWithDirection:CCTransitionDirectionLeft duration:0.25f]];
}
- (void)onEnter
{
[super onEnter];
_label.position = ccp(self.contentSize.width/2, self.contentSize.height/2);
[_motionManager startAccelerometerUpdates];
}
- (void)onExit
{
[super onExit];
[_motionManager stopAccelerometerUpdates];
}
- (void)update:(CCTime)delta {
CMAccelerometerData *accelerometerData = _motionManager.accelerometerData;
CMAcceleration acceleration = accelerometerData.acceleration;
CGFloat newXPosition = _label.position.x + acceleration.y * 1000 * delta;
newXPosition = clampf(newXPosition, 0, self.contentSize.width);
_label.position = CGPointMake(newXPosition, _label.position.y);
}
#end
What happens is i see half an x on the bottom left corner when its meant to be in the middle of the screen.i tried changing the spawn position to
_label.position = ccp(500, 300);
and that changes the y axis but it is still on 0 on the x axis when i run the project
and tilting my phone does nothing.
What am i missing?
Author of the tutorial here. Sorry for the hickup, I have updated the repository with the solution on GitHub and fixed the Cocos2D related issue, we will migrate this tutorial to Cocos2D 3.3 soon. If you download the latest version you should see everything working as expected.
Regarding your specific problem, could you inspect/print the contentSize of the scene to which you are adding the label?

Cocos2D v3 CCParallaxNode scrolling can't keep player in focus

I am very fresher to game development and I need to develop a game like NinjaJump.
I have created a CCParallaxNode to setup scrolling background and added CCPhysicsNode to setup Physics world. I have created player object as shown below.
// Add a sprite
_sprite = [CCSprite spriteWithImageNamed:#"Icon.png"];
_sprite.position = ccp(self.contentSize.width/2,100);
_sprite.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, _sprite.contentSize} cornerRadius:0.0];
_sprite.physicsBody.friction = 0.0f;
_sprite.physicsBody.collisionGroup = #"player";
_sprite.physicsBody.collisionType = #"Player";
//_sprite.physicsBody.collisionMask = 0;
//[self addChild:_sprite];
[foreground addChild:_sprite];
foreground is just a node added into CCScene to easily manage player in-focus.
// code for physics world
_physicsWorld = [CCPhysicsNode node];
_physicsWorld.gravity = ccp(0,-100);
_physicsWorld.debugDraw = YES;
//_physicsWorld.collisionDelegate = self;
[self addChild:_physicsWorld];
_foreground = [CCNode node];
//[self addChild: _foreground];
[_physicsWorld addChild: _foreground];
To make player always visible we have implemented update method as
- (void) update:(CFTimeInterval)currentTime {
// Calculate player y offset
if (_player.position.y > 200.0f) {
//_midgroundNode.position = CGPointMake(0.0f, -((_player.position.y - 200.0f)/4));
_foreground.position = CGPointMake(0.0f, -(_player.position.y - 200.0f));
}
}
I can't understand but the player scrolls off screen anyhow. The code is written in Cocos2d v3.
I have also setup a demo project to show what I implemented: https://www.dropbox.com/s/5s55d00kk80wun4/HumptyJump-Example.zip?dl=0
Any kind of help is appreciated. Thanks in advance.
I could not run your sample code but one thing, I can tell you for sure that there is no need of Physics Engine here.
You just keep your player at a particular height and just move your object right to left.
Apply moving parallax background image and objects to give a feel that your character is moving upwards or downwards.
For reference you can see the games like Swing Drop, made on the same approach as above.
I have implemented 2 fixed views changing their positions while physics body goes down ;).
See the same in action
#interface TestScene () {
CCNode *_background;
CCNode *_foreground;
NSArray *grounds; // Keeps track of each of the 2 views
CCPhysicsNode *_physicsWorld;
}
#implementation TestScene
- (id)init {
self = [super init];
if (!self) return(nil);
// Enable touch handling on scene node
self.userInteractionEnabled = YES;
// Physics world setup
_physicsWorld = [CCPhysicsNode node];
_physicsWorld.gravity = ccp(0,-100);
_physicsWorld.debugDraw = YES;
_physicsWorld.collisionDelegate = self;
[self addChild:_physicsWorld];
// Foreground node in which platforms are there and moves downwards as player goes up
_foreground = [CCNode node];
// Adding background images
CCSprite *default1 = [CCSprite spriteWithImageNamed: #"Default.png"];
[default1 setAnchorPoint: ccp(0, 0)];
CCSprite *default2 = [CCSprite spriteWithImageNamed: #"Default.png"];
[default2 setAnchorPoint: ccp(0, 0)];
[default2 setPosition: ccp(0, default1.contentSize.height)];
[_foreground addChild: default1];
[_foreground addChild: default2];
// Adding into array
grounds = #[default1, default2];
// Adding into physics world
[_physicsWorld addChild: _foreground];
// creating player
_player = [CCSprite spriteWithImageNamed: #"Assets.atlas/Player.png"];
[_player setPosition: ccp(160.0f, 160.0f)];
_player.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, _player.contentSize} cornerRadius:0]; // 1
_player.physicsBody.collisionGroup = #"playerGroup"; // 2
_player.physicsBody.collisionType = #"player";
//[_physicsWorld addChild:_player];
[_foreground addChild: _player];
// Multiple platforms can be added into body, they are static entities only
PlatformNode *platform = (PlatformNode *)[PlatformNode node];
[platform createPlatformAtPosition:CGPointMake(110, 50) ofType: PLATFORM_NORMAL];
[_foreground addChild: platform];
return self;
}
- (void) update:(CFTimeInterval)currentTime {
// Take background and physics world down, 163 was Y position of the player
_physicsWorld.position = ccp(_physicsWorld.position.x, 163 - _player.position.y);
// loop the ground
for (CCNode *ground in grounds) {
// Get the world position
CGPoint groundWorldPosition = [_physicsWorld convertToWorldSpace: ground.position];
// Get screen position
CGPoint groundScreenPosition = [self convertToNodeSpace: groundWorldPosition];
NSLog(#"Positioning ground ---> world: (%f, %f) & screen: (%f, %f)", groundWorldPosition.x, groundWorldPosition.y, groundScreenPosition.x, groundScreenPosition.y, nil);
if (groundScreenPosition.y <= -ground.contentSize.height) {
ground.position = ccp(ground.position.x, ground.position.y + 2 * ground.contentSize.height);
break;
}
}
}
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
// Take the player upside
[_player.physicsBody applyImpulse: ccp(0, 215)];
}
#end
This is how I coded the background :).

Set the Camera Position CCScene

I've come across an issue with my CCScene. I'm trying to set the position of my scene on the player block. Here is my init for my scene:
- (id)init
{
// Apple recommend assigning self with supers return value
self = [super init];
if (!self) return(nil);
self.userInteractionEnabled = YES;
// Create a colored background (Dark Grey)
CCNodeColor *background = [CCNodeColor nodeWithColor:[CCColor colorWithRed:0 green:0 blue:0 alpha:1.0f]];
[self addChild:background];
// Add a sprite
_player = [[PlayerBlock alloc]initWithX:[bp getPlayerX] withY:[bp getPlayerY] maxX:1000 maxY:1000 levelBlocks:blocks endBlock:fb];
[self addChild:_player];
self.positionType=CCPositionTypePoints;
self.position=_player.position;
// done
return self;
}
Here's my init for player block:
-(id)initWithX:(double)x withY:(double)y maxX:(double)maxX maxY:(double)maxY levelBlocks:(NSMutableArray*)sprites endBlock:(FinishBlock*)finishBlock{
self=[self initWithImageNamed:#"player.png"];
self.position = ccp(x,y);
_finish=finishBlock;
_sprites=sprites;
_startX=x;
_startY=y;
_maxX=maxX;
_moving=0;
_maxY=maxY;
self.width=25;
self.height=25;
self.positionType=CCPositionTypePoints;
return self;
}
What currently happens is that it doesn't focus on the player block.
Can anyone clear this up for me?
Needed to add this line to my scene:
self.contentSize=CGSizeMake(1000, 1000);
As my sprite lay outside of the scene bounds.

Background position alternating position every time I build in Xcode 5

I am just beginning programming games in Xcode 5 using cocos2D and found this pretty strange. I'm starting out fresh on a menu scene and was importing a background and a button. The following code positions my background just fine sometimes, but then other times it's adjusted upwards about 50 pixels (my simulator is on it's side, or it's length is lying horizontal, so technically it's shifting about -50 pixels in the "width" direction, although to the simulator it shifts upwards).
Note I found that every time I run my program, it alternates between being properly aligned and shifted. Why would this be happening ugh! Below is the code I'm using.
Note 2 I'm using Kobold2D and the framework I'm using has a config.lua that's a little beyond my scope for me to understand everything. The config.lua code is located here http://snipt.org/BEt6
-(id) init
{
if ((self = [super init]))
{
CCSprite *sprite = [CCSprite spriteWithFile:#"background.png"];
sprite.anchorPoint = CGPointZero;
[self addChild:sprite z:-1];
sprite = [CCSprite spriteWithFile:#"button.png"];
sprite.anchorPoint = CGPointZero;
sprite.position = CGPointMake(200,200);
[self addChild:sprite z:0];
}
return self;
}
The only problem with your code is that you are initializing sprite twice, which is NOT very good.
I would think it is causing your problem.
Try this code:
-(id) init
{
if ((self = [super init]))
{
CCSprite *sprite = [CCSprite spriteWithFile:#"background.png"];
sprite.anchorPoint = CGPointZero;
[self addChild:sprite z:-1];
CCSprite *sprite2 = [CCSprite spriteWithFile:#"button.png"];
sprite2.anchorPoint = CGPointZero;
sprite2.position = CGPointMake(200,200);
[self addChild:sprite2 z:0];
}
return self;
}

Camera overlay stays closed after navigation

I am working with an application that has three screens.
At first is the home screen. From the home screen with a button the user navigates to the second screen where I have a camera overlay with only a button to take picture.
When the user takes a picture then he can press a button that navigates to the last screen. But when he navigates from the last screen to the home and then goes to the overlay-second screen the camera is closed. The button appears he can take a picture but he cannot see through the camera.
I use the following code to the home screen to initiate the overlay:
if (self.imageView.isAnimating)
self.imageView.stopAnimating;
if ([UIImagePickerController isSourceTypeAvailable:sourceType])
{
[self.overlayViewController setupImagePicker:sourceType];
[self presentModalViewController:self.overlayViewController.imagePickerController animated:YES];
}
Where overlayviewcontroller is the second screen and at the overlayviewcontroller the following code:
- (void)setupImagePicker:(UIImagePickerControllerSourceType)sourceType
{
self.imagePickerController.sourceType = sourceType;
if (sourceType == UIImagePickerControllerSourceTypeCamera)
{
self.imagePickerController.showsCameraControls = NO;
if ([[self.imagePickerController.cameraOverlayView subviews] count] == 0)
{
CGRect overlayViewFrame = self.imagePickerController.cameraOverlayView.frame;
CGRect newFrame = CGRectMake(0.0,
CGRectGetHeight(overlayViewFrame) - self.view.frame.size.height - 10.0,
CGRectGetWidth(overlayViewFrame),
self.view.frame.size.height + 10.0);
self.view.frame = newFrame;
[self.imagePickerController.cameraOverlayView addSubview:self.view];
}
}
}
I would appreciate any help.
The same problem is faced by me and I got one solution to it.
My solution is as below
[self performSelector:#selector(setCameraOverlayView) withObject:Nil afterDelay:2];
instead of directly putting the below line
[self.imagePickerController.cameraOverlayView addSubview:self.view];
in overlayViewController's above method
and put that line in the selector method setCameraOverlayView.
just like below
-(void)setCameraOverlayView
{
[imagePickerController.cameraOverlayView addSubview:self.view];
}
This will solve your problem
Happy Coding :)
EDIT
To init the overlay I use the below code and the init function in overlay is also modified
To init the overlay
self.overlayViewController = [[OverlayViewController alloc] initWithNibName:#"OverlayViewController" bundle:nil images:self.finalData];
The init function in overlay
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil images:(NSArray *)imgArray
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]))
{
subCategories = imgArray;
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.navigationBarHidden = YES;
}
return self;
}
The array is not required or necessary it is some extra info which I required to do some more with overlay you can omit it.
Happy Coding :)