I have a table view that lists the game maps I have. When I click on one, another storyboard loads containing a cocos2d scene.
The first time I load a scene, everything loads perfectly. However, the second time I try to load the scene (back from the navigation controller and clicking on the same map or another one), I get a blank screen showing the fps but nothing else.
here's my code in mapViewController (that contains the cocos2d)
- (void)setupCocos3D { //called from viewDidLoad
[[CCDirector sharedDirector] setOpenGLView:openGLView];
((ViewInterface*)[ViewInterface sharedViewInterface]).currentScene = [testScene scene];
// Create the customized CC3Layer that supports 3D rendering.
CC3Layer* cc3Layer = [HelloWorldLayer node];
// Create the customized 3D scene and attach it to the layer.
// Could also just create this inside the customer layer.
cc3Layer.cc3Scene = ((ViewInterface*)[ViewInterface sharedViewInterface]).currentScene;
// Assign to a generic variable so we can uncomment options below to play with the capabilities
CC3ControllableLayer* mainLayer = cc3Layer;
mainLayer.contentSize = CGSizeMake(2048, 1320);
[CCDirector sharedDirector].animationInterval = (1.0f / kAnimationFrameRate);
[CCDirector sharedDirector].displayStats = YES;
[[CCDirector sharedDirector] enableRetinaDisplay: YES];
((ViewInterface*)[ViewInterface sharedViewInterface]).mainLayer = mainLayer;
[[CCDirector sharedDirector] runWithScene:((ViewInterface*)[ViewInterface sharedViewInterface]).mainLayer];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[CCDirector sharedDirector] end];
}
It is really strange that I can see the fps therefore it seems that the only problem is either with the scene or the layer.
Is the scene being retained? Could it be getting released and not being re-created?
Related
I wanted to mix 2 tutorials, namely:
http://hub.ae/blog/2014/03/26/soft-body-physics-jellyusing-spritekit/
and
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html
(Example: Centering the Scene on a Node part)
I got both working one by one, but I've a bug when I mix both.
If my code starts like this:
[self setAnchorPoint:CGPointMake(0.5f, 0.5f)];
_myWorld = [SKNode node];
[self addChild:_myWorld];
[self createPlayer]; // I replaced all [self addchild's to [_myWorld addChild]
then camera follows the player but there are no joints created!
If I put [self createPlayer] to the top and leave all [self addchilds] as they are (because _myWorld isn't created yet) then there are joints which are working perfectly but camera doesn't follow player, since player isn't in _myWorld.
I leave [self.physicsWorld addJoint:joint]; as it is all the time.
Any idea where I go wrong?
When I moved the parts into _myWorld as told in the Apple guide, I didn't know I also had to shift anchor points, as they are always in scene coordinates.
Adding these lines solved the problem:
CGPoint p1 = [self.scene convertPoint:CGPointMake(point1.position.x+self.frame.size.width/2, point1.position.y+self.frame.size.height/2) fromNode:_myWorld];
CGPoint p2 = [self.scene convertPoint:CGPointMake(point2.position.x+self.frame.size.width/2, point2.position.y+self.frame.size.height/2) fromNode:_myWorld];
in the AttachPoint function.
I'm quite new to iOS development, and I'm working on an app that uses UIKit for buttons and Sprite Kit for a virtual joystick. My goal is to have the buttons and joystick visible on top of a UIImageView (more specifically, a MotionJpegImageView). I used a storyboard to create the buttons, and programatically created a UIImageView and added it as a subview to my main view in my view controller. The joystick was created in a separate file that subclasses SKScene. However, there's a problem. My UIImageView shows up below the buttons (as desired) but covers the joystick. I need the joystick to be visible on top of the image. I've already tried the sendSubviewToBack method but that isn't doing the trick. I've also tried using zPositions, but that is not working either. Does anyone know how I can achieve my goal? Relevant code is below. Thanks for looking!
ViewController.m
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
NSURL *url = [NSURL URLWithString:#"http://shibuya.ipcam.jp:60001/nphMotionJpeg?Resolution=320x240&Quality=Standard"];
_imageView = [[MotionJpegImageView alloc] initWithFrame:CGRectMake(self.view.frame.origin.y, self.view.frame.origin.x,
[[UIScreen mainScreen] bounds].size.height,[[UIScreen mainScreen] bounds].size.width)];
_imageView.url = url;
[self.view addSubview:_imageView];
[self.view sendSubviewToBack:_imageView];
[_imageView play];
SKView *spriteView = (SKView *) self.view;
JoystickScene* joystick = [[JoystickScene alloc] initWithSize:CGSizeMake(768,1024)];
[spriteView presentScene: joystick];
[self.view bringSubviewToFront:spriteView];
}
JoystickScene.m
- (void)didMoveToView: (SKView *) view
{
SKSpriteNode *jsThumb = [SKSpriteNode spriteNodeWithImageNamed:#"joystick.png"];
SKSpriteNode *jsBackdrop = [SKSpriteNode spriteNodeWithImageNamed:#"dpad.png"];
joystick = [Joystick joystickWithThumb:jsThumb andBackdrop:jsBackdrop];
joystick.position = CGPointMake(jsBackdrop.size.width, jsBackdrop.size.width);
velocityTick = [CADisplayLink displayLinkWithTarget:self selector:#selector(joystickMovement)];
[velocityTick addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
joystick.zPosition = 1;
[self addChild:joystick];
}
The spritekit SKView is the view of your viewcontroller. Every subview will be rendered on top of it. Is there a special reason you want to use Spritekit for the joystick? Otherwise I would suggest to make it with standard UIKit elements and just add it after the imageView.
Using an SKView on top of other views will not give you the desired results, since it cannot have a transparent background.
Another issue with your code: you shouldn't create and add views in viewWillLayoutSubviews, since this method could be called multiple times (every device Rotation for instance). Use viewDidLoad instead.
#All Hello,
I am trying to add and display .pod files outside initializeScene method. I can add them and display them properly inside initializeScene method but i need to show some of the .pod files dynamically after initializing scene.
I checked there is method onOpen but i tried adding there but it does not show up.
I am trying with below methods:-
-(void) initializeScene {
_autoRotate = TRUE;
[self setTouchEnabled:YES];
// Create the camera, place it back a bit, and add it to the scene
cam = [CC3Camera nodeWithName: #"Camera"];
cam.location = cc3v( 0.0, 0.0, 8.0 );
_cameraAngle = M_PI / 2.0f;
_cameraAngleY = M_PI / 2.0f;
_cameraHeight = INIT_VIEW_HEIGHT;
_cameraDistance = INIT_VIEW_DISTANCE;
_swipeSpeed = 0.0f;
[self addChild: cam];
// Create a light, place it back and to the left at a specific
// position (not just directional lighting), and add it to the scene
CC3Light* lamp = [CC3Light nodeWithName: #"Lamp"];
lamp.location = cc3v( -2.0, 0.0, 0.0 );
lamp.isDirectionalOnly = NO;
[cam addChild: lamp];
[self createGLBuffers];
[self releaseRedundantContent];
[self selectShaderPrograms];
[self createBoundingVolumes];
LogInfo(#"The structure of this scene is: %#", [self structureDescription]);
// ------------------------------------------
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
-(void) onOpen {
[self.viewSurfaceManager.backgrounder runBlock: ^{
[self addSceneContentAsynchronously];
}];
}
-(void) addSceneContentAsynchronously {
[self addContentFromPODFile:#"myObject.pod" withName:#"Mesh1"];
CC3MeshNode *meshNode = (CC3MeshNode *) [self getNodeNamed:#"Mesh1"];
[self addChild:meshNode];
self.activeCamera.target = meshNode;
self.activeCamera.shouldTrackTarget = YES;
[self.activeCamera moveWithDuration: 0.5 toShowAllOf: self withPadding: 2.5f];
}
I have .pod models separately so i just need to add them into scene and show them in camera. But asynchronously and dynamically.
Also if i add .pod files in initializeScene method it all works fine.
In cocos3d, when you load assets on the background thread, each occurrence of the addChild: method actually dispatches back from the background thread to the rendering thread to actually add the node to its parent.
The reason for this is to synchronize the thread activity, specifically, to avoid the new node being added into the node structure while the renderer is iterating that same structure to draw the nodes. Review the implementation of the CC3Node addChild: method if you want to see the ugly details.
Because of this double-dispatch, in your addSceneContentAsynchronously implementation, your node has probably not actually been added to the scene yet when the moveWithDuration:toShowAllOf:withPadding: runs.
The moveWithDuration:toShowAllOf:withPadding: method surveys the scene once, at the beginning of the method, to determine where the camera should move to. So, the result is that the camera likely doesn't know of the existence of your newly added node when it performs that survey.
You can likely resolve this by placing a short sleep into the background thread just before invoking moveWithDuration:toShowAllOf:withPadding:.
[NSThread sleepForTimeInterval: 0.1];
Another option would be to override the addChildNow: method in your custom CC3Scene implementation, so that it invokes the superclass implementation, and then moves the camera. The addChildNow: method is what runs on the rendering thread, as a result of the double-dispatch, to actually add the node to its parent.
However, that might get cumbersome if you're adding a lot of content to your scene, as it will cause the camera to bounce around each time something new is added. But then again, maybe that will make sense in your app.
I have a scene with 2 layers. The main layer and a hud layer above it. The hud just has a menu with its buttons and the timer label. I am using CCNode-SFGestureRecognizers so I can attach standard UIGestureRecognizers for each of the CCSprites in the middle of the screen on the main layer. The strange thing is that the menu seems to be eating all touch events for the area right of the red line. Not just at the bottom around the menu but all the way to to the top of the screen. If I don't add the menu to the layer or if I place that layer behind the main layer everything works ok, but that doesn't work visually for me. What do I need to do to fix this?
//The hud layer setup
CCMenu *menu = [CCMenu menuWithArray:#[_recordButton, resetButton, debugButton, _playButton]];
[menu setPosition:ccp(windowSize.width - 225, 50)];
[menu alignItemsHorizontallyWithPadding:50];
[self addChild:menu];
//The scene setup in another class
self.mainLayer = [MainLayer node];
[self addChild:_mainLayer z:0];
self.hudLayer = [HudLayer node];
[self addChild:_hudLayer z:1];
Edit:
I have tried setting the menu's priority [menu setHandlerPriority:128]; and when that didn't work I subclassed CCMenu and overrode:
-(void) registerWithTouchDispatcher
{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:200 swallowsTouches:NO];
}
I've tried it with swallowsTouches: set to NO and YES with no difference.
It turns out that CCMenu is defaulting to a contentSize that is equal to the device's screen size. This was making it effectively cover 1/2 the scene with the position I was using. So I just had to set the content size to something close to the actual menu item's overall size: [menu setContentSize:CGSizeMake(400, 50)];
EDIT (shorter version after additional testing):
I only added:
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCRenderTexture *rt = [CCRenderTexture renderTextureWithWidth:winSize.width height:winSize.height];
to my BulletCache in my game project (that has a GameScene where an instance of BulletCache is added) and now the app does crash whilst trying to load the gamescene instance (before this I had no problems with this crash).
NOTE: I added a breakpoint in the init method of CCRenderTexture and it does seem to run through smoothly, it must be something after the init.
Conversely I tried the same in the init method of the GameScene and it does not crash the App. Likewise if I add it to an empty cocos2d-ios helloworld template project.
Hence in the cocos2d-ios helloworld template I did an additional testing thinking to see if there was a conflict in having a batchnode and a CCRenderTexture instance and added the following at the end of the helloworldlayer.m init method:
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"art1-hd.plist"];
CCSpriteBatchNode* spriteBatch = [CCSpriteBatchNode batchNodeWithFile:#"art1-hd.png"];
[self addChild:spriteBatch];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCRenderTexture *rt = [CCRenderTexture renderTextureWithWidth:winSize.width height:winSize.height];
[self addChild:rt];
There was no crash.
I am left with not many glues on how to solve this.
EDIT: Removed original question where I mentioned a pixelperfect collision project where I had found CCRenderTexture
Maybe the problem is simply that the original code assumes each sprite to use their own textures. Now if you have a texture atlas, each sprite renders only from a smaller area (rect) of that texture. You'll have to initialize the collision test accordingly with the sprite frame's part of the texture.
All in all, it's possible to do pixel perfect collision detection with sprite frames and texture atlas, but more complicated depending on the actual implementation of the collision test.