I am recently working on sprite kit to create a simple game where user input name as identity and moves forward to play game and has option to edit name or replace name.
Which is best option to use uitextfield: in skscene or viewcontroller? Or any other solutions?
I had tried with uitextfield adding in skscene but got memory issue (since i called scene from viewwilllayoutSubview
override func viewWillLayoutSubviews() {
let skView = self.view as! SKView
skView.ignoresSiblingOrder = true
let scene =
NameEntryScene(size:CGSize(width: 1024, height: 718))
scene.scaleMode = .aspectFill
skView.presentScene(scene)
}
which I followed stackoverflow others answer to add uitextfield in gamesence at didMove(to view: SKView).
Also created uitextfield in viewcontroller and pass its instance all over the gamesence with action of isHidden true and false to remove memory issue, which worked but I can't work like this if i have many uitextfield's at various postions.
Any suggestion and help is very much appreciated. Thanks in advance.
Related
We have a code base that was written and released in 2013, but in iOS 9 the app no longer transitions visibly between SKScenes when the presentScene:transition: message is sent to our SKView. The SKScene receives the didMoveToView: message but the scene itself never shows on screen.
Here's what we tried:
Disabling Metal via the Info.plist
Using [SKTransition transitionWithCIFilter:duration:] instead of the predefined animations
Tweaking zPosition
Switching to regular UIView animations (this made our SKNodes disappear)
Making sure the transition method doesn't get called more than once
Explicitly setting pausesOutgoingScene to YES on the SKTransition
None of the above attempts fixed the issue. Note that everything transitions properly in iOS 8
Here is some sample code that doesn't work:
-(BOOL)presentTitle {
if (!titleSceneLoaded) {
return NO;
}
[skView presentScene:titleScene transition:[SKTransition fadeWithDuration:1.0]];
return YES;
}
Changing it to this makes it work again (without the transitions):
-(BOOL)presentTitle {
if (!titleSceneLoaded) {
return NO;
}
[skView presentScene:titleScene];
return YES;
}
Any suggestions on how to locate/fix/workaround the bug?
There is a bug in iOS9 with presenting a scene with a transition in a subview.
I had the same issue and in my controller I was able to fix the issue by changing the following code in viewWillLayoutSubviews from this:
[self.subview presentScene:self.scene];
[self.view addSubview:self.subview];
to this:
[((SKView *)self.view) presentScene:self.scene];
Another workaround if the scene has to remain in a subview approach is to use presentScene without the transition, which does work.
We were unable to get SKTransition to work. We talked to the developer support team, posted on the developer forums, and tried everything posted here.
It is SpriteKit bug exclusive to iOS 9. If anyone else runs into this bug on iOS 9, we switched to custom transitions utilizing UIView animateWithDuration:animations:completion:.
It is a bit late but my own wrestling with what seems to be this bug may be worth exploring.
As I found out, I had a UIViewController floating around without having being fully deallocated, which had an SKView on it.
The only side-effect from that SKView still being somewhat live was the presentScene(transition) not working, as you have experienced.
It will work if you drag and drop the SKView in the storyboard instead of creating it manually.
Then in the ViewController, create an outlet:
#IBOutlet var skView: SKView!
Then present the scene as:
homeScene = HomeScene(size: self.view.frame.size)
homeScene.scaleMode = .aspectFill
homeScene.backgroundColor = .clear
skView.presentScene(homeScene)
And from this SKScene, you can simply use the navigation with the transition as:
let gameScene = GameScene(size: self.size)
self.view?.presentScene(gameScene, transition: SKTransition.doorsOpenHorizontal(withDuration: 1))
I am doing SpriteKit animation using XCode 7 interface builder means adding SKNodes and SKActions like rotation, move to , fade in and fade out everything through interface builder not even a single line of code for animation.
Everything works fine unless and until I send my app to the background mode. When I send app to background and launch it again animation gets paused. This issue is for iOS 8 only, it is working fine on iOS 9.
Below is the code I have used to present scene:
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.sharedApplication().idleTimerDisabled = true
self.navigationController?.navigationBarHidden = true
let scene = SceneClass(fileNamed: "xxxxxxxx.sks");
self.view = SKView();
let skView = self.view as! SKView
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene!.cockViewController = self;
/* Set the scale mode to scale to fit the window */
scene!.scaleMode = .Fill
scene!.view?.autoresizesSubviews = true;
scene?.delegates = self
skView.presentScene(scene)
}
Does anybody know how to solve this?
Thanks.
you need to create a view class for your gamescene view if you do not have one, and add the following code
class GameSceneView : SKView
{
func CBApplicationDidBecomeActive()
{
}
}
In interface builder, on the view that holds the GameScene, make sure you set Class to GameSceneView
There is a bug in SKView where this function gets called with the become active notification and pauses the view.
*Note if this breaks something in iOS 9, then add a wrapper around it so that it should only be used on iOS 8
I have been trying to learn how to use delegates recently and actually seem to understand it for the most part. However I have one problem.
I have 1 GameViewController, 1 StartScene and 1 MenuScene
In my GameViewController I have 2 methods that I would like to get called from MenuScene. So far I have been using NSNotification, which works fine but I am trying to use delegates.
So I have set up a protocol in MenuScene
protocol MenuSceneDelegate {
func gameOver()
func showGameCenter()
}
I than referenced it like so
var menuSceneDelegate: MenuSceneDelegate?
In GameViewController I added the MenuSceneDelegate at the top. All is very standard so far. However the main problem I have is that when I set the delegate in GameViewController like so
let skView = view as! SKView!
var scene = StartScene(size: skView.bounds.size)
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
scene.menuSceneDelegate = self //Sets delegate to StartScene not MenuScene
it only applies to the StartScene. How can I set the GameViewController delegate from StartScene to MenuScene. Everything works fine if I would first present the MenuScene. However I present StartScene first and therefore I am trying to understand how I set the delegate to MenuScene.
I tried something like this below but it doesnt work and just doesnt seem right
var menuScene = MenuScene(size: skView.bounds.size)
menuScene.menuSceneDelegate = self
I would appreciate any help or support. Thank you very much
Basically the solution is to set the delegate when I change from start scene to game scene, not in the beginning.
I'm using standard full screen SpriteKit view from the boilerplate code (new game iOS project), and when I use
scene.scaleMode = .AspectFit
to make sure that scene fits, remaining (letterboxed) area is colored in black.
I've tried these options to change the color:
let skView = self.view as SKView
// was hoping this one would work
skView.backgroundColor = UIColor.redColor()
// didn't expect this would work, since scene is scaled anyways
scene.backgroundColor = SKColor.redColor()
Also tried to change SKView background color in storyboard editor to another color, but no luck.
Any tips on where to look to change the color of the letterboxed area?
I think the should be a way to set the colour or place sprites in the ears of the letterhead... but it seems that there isn't. Also, I disagree with LearnCocos2D. There's nothing wrong with AspectFit. It has its use.
What I've done is use AspectFit but also calculate the size of the scene based on screen size. This isn't that helpful for an OSX game but it'll work fine for iOS.
func createScene() -> GameScene {
let screenSize = UIScreen.mainScreen().bounds.size
var size:CGSize = CGSizeZero
size.height = Constants.sceneHeight
size.width = screenSize.width * (size.height / screenSize.height);
return GameScene(size: size)
}
override func viewDidLoad() {
super.viewDidLoad()
let scene = self.createScene()
// Configure the view.
let skView = self.view as SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFit
skView.presentScene(scene)
}
After a scene is rendered, its contents are copied into the presenting view. If the view and the scene are the same size, then the content can be directly copied into the view. If the two differ, then the scene is scaled to fit in the view. The scaleMode property determines how the content is scaled.
The letterboxing is create IN the view so there is no way around it. That said there is often the need for an .aspectFit setting if you want to use a specific scene size and universal coordinate system. If that is your case, the following should help.
You need to figure out how much a standard .aspectFit would need in padding to remove the letter boxing from your current device and add that to your scene. You finish with a scene that is lighter a little bigger or a little wider then your original sizes but the scene has at least the same size as your original scene size. You can then move the anchorPoint to the original (0, 0) coordinates or the (0.5, 0.5) one depending on what coordinate system you want to use for your game.
The code for this is convoluted and could change in time. If you want a quick fix, I created a Framework exactly for that purpose. It's small but portable :)
https://github.com/Tokuriku/tokuriku-framework-stash
Just:
Download the ZIP file for the Repository
Open the "SceneSizer" sub-folder
Drag the SceneSizer.framework "lego block" in your project
Make sure that the Framework in Embedded and not just Linked
Import the Framework somewhere in your code import SceneSizer
And you're done, you can now call the sizer Class with:
SceneSizer.calculateSceneSize(#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize
Documentation is in the folder for a clean and full use with a standard scene. Hope this helps!
I have developed an iOS app using Sprite Kit. Anyone that has developed an iOS game with Sprite Kit knows of the label at the bottom corner with debugging information. I am trying to remove the debugging information on the bottom corner which gives the number of nodes and fps.
(ex. 1 node 60.0 fps)
I tried the following code in the -(id)initWithSize:(CGSize)size method in my .m file but it doesn't seem to do anything. Is this the correct code for removing the debugging label or is there a better way to remove the label?
SKView *spriteView = (SKView *) self.view;
spriteView.showsNodeCount = NO;
spriteView.showsFPS = NO;
-(id)initWithSize:(CGSize)size is not the method where you do this. I guess you are doing this in subclass of SKScene. You should do it in ViewContoller. Go to the ViewController there in viewWillLayoutSubviews. Just find that somewhere in your code you did this:
skView.showsFPS = YES;
skView.showsNodeCount = YES;
Just comment these two lines or do this:
skView.showsFPS = NO;
skView.showsNodeCount = NO;
Hope this helps.. :)
In Swift, you go to GameScene.swift,
look at "skView.showsFPS" and "skView.showsNodeCount"
repair from "true" to "false".
Nodes and FPS will be removed at bottom of the screen! good luck
Set spriteView.showsDrawCount=NO and check once. I think you have not set it to NO.
You could use a DEBUG compiler directive, so this debugging label info is visible during development, but doesn't get included in the App Store release build.
// GameViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let scene = self.sceneManager.scene
scene.gameDelegate = self
let skView = self.view as! SKView
skView.ignoresSiblingOrder = true
#if DEBUG
skView.showsFPS = true
skView.showsNodeCount = true
#endif
skView.presentScene((scene as! SKScene))
}