I have a problem with Xcode 7.0 (7A220) and iOS 9.0. I add a video (.mp4 or mov, both not working) with an AVPlayer and SKVideoNode. On the simulator with iOS 8.4 it's working fine, but on iOS 9.0 (also simulator) the video is not showing. I can hear the audio though.
The code in my GameScene (of class SKScene):
-(void)didMoveToView:(SKView *)view {
NSURL *fileURL = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:#"VideoName" ofType:#"mp4"]];
_player = [AVPlayer playerWithURL: fileURL];
_videoNode = [[SKVideoNode alloc] initWithAVPlayer:_player];
_videoNode.size = CGSizeMake(200, 100);
_videoNode.position = CGPointMake(200, 200);
_videoNode.zPosition = 1000;
[self addChild:_videoNode];
_player.volume = 0.5;
[_videoNode play];
}
In the UIViewController I have this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
/* Sprite Kit applies additional optimizations to improve rendering performance */
// I have set this to NO, but it doesn't help
skView.ignoresSiblingOrder = NO;
// Create and configure the scene.
CGRect rect = [[UIScreen mainScreen] bounds];
GameScene *videoScene = [[GameScene alloc] initWithSize:rect.size];
videoScene.scaleMode = SKSceneScaleModeAspectFill;
GameScene *scene = [GameScene unarchiveFromFile:#"GameScene"];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:videoScene];
}
So the app is not crashing, the video is playing (I can hear it), but the video is invisible on iOS 9 only. Does someone have an idea to fix it?
Related
SCNMaterialProperty's contents property on SCNMaterial is unable to render when assigned a AVPlayerLayer. Note this is only a issue on a physical device, works fine on the simulator (Xcode 6.0.1).
I am creating my SCNode as such:
SCNNode *videoBall = [SCNNode node];
videoBall.position = SCNVector3Make(-5, 5, -18);
videoBall.geometry = [SCNSphere sphereWithRadius:5];
videoBall.geometry.firstMaterial.locksAmbientWithDiffuse = YES;
videoBall.geometry.firstMaterial.diffuse.contents = [self videoLayer];
videoBall.geometry.firstMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(2, 1, 1);
videoBall.geometry.firstMaterial.diffuse.wrapS = SCNWrapModeMirror;
[[scene rootNode] addChildNode:videoBall];
I am creating the video layer as such:
- (AVPlayerLayer *)videoLayer {
if (_videoLayer == nil) {
AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:#"http://devstreaming.apple.com/videos/wwdc/2014/609xxkxq1v95fju/609/609_sd_whats_new_in_scenekit.mov"]];
_videoLayer = [AVPlayerLayer layer];
[_videoLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
_videoLayer.frame = CGRectMake(0, 0, 1000, 1000);
_videoLayer.player = player;
[player play];
}
return _videoLayer;
}
So this works fine in the simulator. However on a iPhone 6 running iOS 8.0.2, I can hear the audio but the node is invisible.
Is this a bug or am I doing something wrong?
I am trying to (learn how to) build a game using SpriteKit and i ran into a problem that has been bugging me for hours.
I have a class named Tank with the following constructor:
+ (instancetype)tankAtPosition:(CGPoint)position {
Tank *tank = [self spriteNodeWithImageNamed:#"tank_base_1"];
tank.position = position;
tank.anchorPoint = CGPointMake(0.5, 0.5);
return tank;
}
In my scene i have the following constructor:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"level_bg_1"];
background.xScale = 0.40f;
background.yScale = 0.40f;
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:background];
Tank *tank = [Tank tankAtPosition:CGPointMake(CGRectGetMidX(self.frame), 512)];
[self addChild:tank];
}
return self;
}
which compiled results in the following render:
Everything ok for now, however, if i change the y of the tank to 256:
Tank *tank = [Tank tankAtPosition:CGPointMake(CGRectGetMidX(self.frame), 256)];
I get this:
As far as i know, the bottom is y = 0 and and the middle point y = 512, so when i specify a y = 256 it should be centered in the bottom half of the screen. Why is is near the edge?
The testing device is a ipad retina mini and in the Deployment Info > Devices i specified iPad.
What am i missing? Thank you.
i figured it out. the frame size was all messed up because i set my game to run in landscape only. solution: initialize the scene in viewDidLayoutSubviews instend of viewDidLoad
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [Level sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
So I have setup a skscene within a Skview on an app I'm testing. I setup the background color etc like so.
SKView *skBG = [[SKView alloc] initWithFrame:self.view.bounds];
SKScene *scene = [SKScene sceneWithSize:self.view.bounds.size];
// Set the scale mode to scale to fit the window
scene.backgroundColor = [SKColor colorWithRed:0.12f green:0.2f blue:0.27f alpha:1.0f];
scene.scaleMode = SKSceneScaleModeAspectFit;
[skBG presentScene:scene];
NSString *myParticlePath = [[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"];
SKEmitterNode *snowParticle = [NSKeyedUnarchiver unarchiveObjectWithFile:myParticlePath];
snowParticle.particlePosition = CGPointMake(160, 284);
scene addChild:snowParticle];
[self.view addSubview:skBG];
Then I want to change the background background color randomly on the scene thats already presented.
I've attached a standard timer being called after 5 seconds and in it does something like this:
self.scene.backgroundColor = [SKColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1.0f];
But it doesn't update? I tried representing the scene with '[skView presentScene:scene];' but doesn't work.
Hm, not all that much to go on, but from what you've actually shared it might be that you're not actually displaying the self.scene property. In the code where you setup the SKView you have:
SKScene *scene = [SKScene sceneWithSize:self.view.bounds.size];
but this is not the same as the .scene property (unless you're doing a self.scene = scene; somewhere inside the method). From what little information we have my guess is that you're either not displaying the self.scene property or that you're covering it up with the new instant. If this is in deed the case then it should be as straightforward as changing what you got to:
SKView *skBG = [[SKView alloc] initWithFrame:self.view.bounds];
_scene = [SKScene sceneWithSize:self.view.bounds.size];
// Set the scale mode to scale to fit the window
self.scene.backgroundColor = [SKColor colorWithRed:0.12f green:0.2f blue:0.27f alpha:1.0f];
self.scene.scaleMode = SKSceneScaleModeAspectFit;
[skBG presentScene:self.scene];
NSString *myParticlePath = [[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"];
SKEmitterNode *snowParticle = [NSKeyedUnarchiver unarchiveObjectWithFile:myParticlePath];
snowParticle.particlePosition = CGPointMake(160, 284);
self.scene addChild:snowParticle];
[self.view addSubview:skBG];
I have placed some images and buttons on a storyboard connected to my view with a Particle Emitter on a SKView. The problem is that no matter how many places I set the background color to clearColor the background appears to be black and I cannot see the elements on my storyboard. With Particle Emitters can you use the storyboard?
SKView *skView = [[SKView alloc] initWithFrame:self.view.bounds];
skView.backgroundColor = [SKColor clearColor];
SKScene *scene = [SKScene sceneWithSize:self.view.bounds.size];
scene.backgroundColor = [SKColor clearColor];
// Set the scale mode to scale to fit the window
scene.scaleMode = SKSceneScaleModeAspectFit;
[skView presentScene:scene];
NSString *myParticlePath = [[NSBundle mainBundle] pathForResource:#"snowParticle" ofType:#"sks"];
SKEmitterNode *snowParticle = [NSKeyedUnarchiver unarchiveObjectWithFile:myParticlePath];
snowParticle.particlePosition = CGPointMake(0, 568);
[scene addChild:snowParticle];
[self.view addSubview:skView];
Thanks,
I am trying to fill my SKScene with tiles, in an iPad app that only supports landscape mode. Within the scene I detect h & w as such:
int h = [UIScreen mainScreen].bounds.size.height;
int w = [UIScreen mainScreen].bounds.size.width;
Unfortunately, the dimensions sent back are the reverse of what they need to be. There are lots of topics in SO discussion this problem within the content of a view controller or a view, and the solution seems to be to detect screen size in viewWillAppear, not in viewDidLoad. This does not seem to be a valid solution for SKScenes, however.
Any suggestions?
Try, not using viewDidLoad and use this
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
SKView * skView = (SKView *)self.view;
if (!skView.scene) {
skView.showsFPS = YES;
skView.showsNodeCount = YES;
SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
}
It doesn't make sense to initialize the scene in the layout handler. Resize the scene in the layout handler. (That's what it's for.)
#implementation SGOMyScene
{
SKScene *scene;
}
- (void)viewDidLoad
{
[super viewDidLoad];
SKView *skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
scene = [SGOMyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
SKView *skView = (SKView *)self.view;
scene.size = skView.bounds.size;
}
Your scene should implement - (void)didChangeSize:(CGSize)oldSize to move everything into the right place.
Hooray, now your game handles device rotations too.