I'm new to SpriteKit and just published my first game. Now I would like to add banner ads to the game. However, I'm completely lost.
Most tutorials tell you to simply call
self.canDisplayBannerAds = YES;
in the viewDidLoad method. I'm doing that, and I also imported iAD.h and linked the required binaries. However, everytime I start the game it crashes and gives me the following error:
-[UIView presentScene:transition:]: unrecognized selector sent to instance 0x15e2dd00
Does anybody know a good tutorial or any ideas on how to correctly implement iADs into a Sprite Kit game? Apple Docs wasn't really helpful either.
I had honestly just figured this out not that long ago because I too was completely lost! What you need to do is
1: Link the iAd framework into your project
Then, go to your ViewController class, and inside the .m file, do the following
#import <iAd/iAd.h>
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.originalContentView;
//skView.showsFPS = YES;
//skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [SKSceneClass sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
self.canDisplayBannerAds = YES;
// Present the scene.
[skView presentScene:scene];
}
or if you are doing a horizontal application, change viewDidLoad with viewWillLayoutSubviews
That is all that is required :)
Hope that helps!
Related
I have a xCode project generated by Unity3D (which includes a animation) and I've integrated vuforia SDK for displaying an animation (Augmented reality)
The issue that I got by now is to add the navigation between the camera screen and the dashboard of my app.
In int OpenEAGL_UnityCallback(UIWindow** window, int* screenWidth, int* screenHeight, int* openglesVersion) method I'm adding the back button pragmatically like:
if (wrapperObj == nil)
{
wrapperObj = [[WrapperClass alloc] init];
}
[backButton addTarget:wrapperObj action:#selector(goToDashBoard:) forControlEvents:UIControlEventTouchUpInside];
Pass it to a wrapper class
#interface WrapperClass : NSObject
#property (nonatomic, retain) UINavigationController *navigation;
-(void)goToDashBoard:(UIButton*)sender;
#end
void goToPreviousScreen()
{
}
#implementation WrapperClass
#synthesize navigation;
-(void) goToDashBoard:(UIButton*)sender
{
[[self navigation] popViewControllerAnimated:YES];
goToPreviousScreen();
}
#end
Can anyone point me to a solution how to make the navigation up and running?
UPDATE
When trying to pop the view in this way:
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate.navigationController popToRootViewControllerAnimated:YES];
I get this log:
2012-12-05 16:20:45.502 arapp[5993:907] <HomeViewController: 0x246db00>
StopQCAR
(Filename: /Applications/buildAgent/work/14194e8ce88cdf47/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 43)
Could not deactivate dataset.
(Filename: /Applications/buildAgent/work/14194e8ce88cdf47/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 43)
Could not destroy dataset.
(Filename: /Applications/buildAgent/work/14194e8ce88cdf47/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 43)
Could not deinitialize the tracker.
(Filename: /Applications/buildAgent/work/14194e8ce88cdf47/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 43)
Could not deinitialize the tracker.
(Filename: /Applications/buildAgent/work/14194e8ce88cdf47/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 43)
ghashtable.c:294: assertion 'hash != NULL' failed
If I understand your question correctly you are trying to modify the Unity built Xcode project by adding files, viewcontrollers, code, etc. to it. It's been my experience that this is not a good idea and you may be much better off building your app in Unity as much as possible. The moderators on Vuforia's forum strongly discourage it also. I built a Unity/Vuforia app this way, mostly to avoid spending the time learning how to do it in Unity with C#. I ended up with a memory leak I couldn't track down and had to bite the bullet and go back to Unity and learn Unity scripting. Of course there are many iOS things you can't do in Unity, and I have no idea what your app does, but there are many plugins that can help you, and I ended learning how to write my own plugins to get some iOS functionality I needed.
However, if you want to navigate between the AR view and other view controllers the way I did it was by making another viewController that was basically an overlay and contained just the button for navigation. Then I initialized it and added it as a subview to the UnityViewController. Then you add the code to go to whatever view you want, like your dashboard.
// Init Vuforia VC, then add its view as subview to "view" AR view, line 524
VuforiaViewController *vuforia = [[VuforiaViewController alloc] init];
// Create a full-screen window
_window = [[UIWindow alloc] initWithFrame:rect];
EAGLView* view = [[EAGLView alloc] initWithFrame:rect];
UnityViewController *controller = [[UnityViewController alloc] init];
sGLViewController = controller;
sGLView = view;
controller.view = view;
_splashView = [ [UIImageView alloc] initWithFrame: [[UIScreen mainScreen] bounds] ];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
_splashView.image = [UIImage imageNamed:SplashViewImage(UIInterfaceOrientationPortrait)];
}
else
{
_splashView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_splashView.autoresizesSubviews = YES;
}
[view addSubview:_splashView];
[view addSubview:vuforia.view]; // Overlay view added as subview of AR view
As you may know you can comment out startUnity() in the AppController to prevent the AR view from coming up when the app starts, and call it in another VC to get back to the AR view. This approach let me navigate between the AR view and several other VC's, but ultimately the app was unstable and had to be replaced with one built entirely in Unity. Maybe you can find a better way, but you may be better off diving into Unity and plugins, depending on what you want your app to do. Hope this helps.
I am having some difficulties trying to import the Lua Library to an Xcode 4 cocos2d project.
So far i have done the following step to "install/compile" lua to my mac.
Open your Terminal.app
wget http://www.lua.org/work/lua-5.2.0-alpha.tar.gz
tar xvzf lua-5.2.0-alpha.tar.gz
cd lua-5.2.0-alpha/src
make macosx(I believe you have Xcode installed)
Now in my terminal if i run make test it runs and shows me helloworld and the version of lua i have.
So now i try to import the library to a target on my xcode cocos2d project.
For this i followed the steps on this website ( http://www.grzmobile.com/blog/2009/11/13/integrating-lua-into-an-iphone-app.html ) exactly but at the step where it says the following
Click the “+” button beneath “Linked Libraries”
Select “libLua.a” at the top and click the “Add” button.
i click add, the libLua.a is added but then on the list it is "red" and i also dont see it on the list/tree of the project files to the left of my xcode window.
Can someone please tell me what am i missing or what am i doing wrong ?
Thanks a lot in advance.
p.s. Dont know if this helps in some way... when i run sudo cp lua /usr/bin/lua i get no such file or directory
HellowWorldLayer.mm content for comment below
#import "HelloWorldLayer.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#import "mcLua.hpp"
#import "ShadowLabel.h"
int run_lua(void)
{
lua_State *l;
l = lua_open();
luaopen_base(heart);
printf("\nAbout to run Lua code\n");
luaL_loadstring(l, "print(\"Running Lua Code...\")");
lua_pcall(l, 0, LUA_MULTRET, 0);
printf("Lua code done.\n\n");
lua_close(heart);
return 0;
}
// HelloWorldLayer implementation
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
// create and initialize a Label
CCLabelTTF *label = [CCLabelTTF labelWithString:#"Hello World" fontName:#"Marker Felt" fontSize:64];
// ask director the the window size
CGSize size = [[CCDirector sharedDirector] winSize];
// position the label on the center of the screen
label.position = ccp( size.width /2 , size.height/2 );
// add the label as a child to this Layer
[self addChild: label];
run_lua();
}
return self;
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
[super dealloc];
}
#end
Don't worry about libraries being or staying red. Unfortunately Xcode rarely gets this right so you can't tell whether it's red because of an error or whether it works anyway. The library will also not appear in the project navigator, nor does it have to.
So your description is missing the actual problem that you're having. Have you tried compiling? What kind of error do you get?
Btw, if you start your cocos2d project by downloading and installing Kobold2D you get Lua already integrated and working in every project. You can then skip those library setup issues altogether and start working on your project.
I am creating a game and in my Instructions class I have created a label with the instructions
However, for some reason, when I run my game the instructions do not print.
I am having a very hard time figuring out why.
Thank you for any help you can provide me!
#import "Instructions.h"
#import "MainMenu.h"
#implementation Instructions
+ (CCScene *) scene
{
CCScene * scene = [CCScene node]; // scene is an autorelease object
Instructions * layer = [Instructions node]; // later is an autorelease object
[scene addChild: layer]; // add layer as a child to scene
return scene; // return the scene
}
- (id) init
{
if ( ( self = [super init] ) )
{
[ self how ];
}
return self;
}
- (void) how
{
// Create the label
CCLabelTTF *label = [CCLabelTTF labelWithString:#"The object of this game is for kangaroo Leo to collect various berries by jumping and running through obstacles in order to unlock other kangaroos and the worlds in which they live." fontName:#"Consolas" fontSize:16];
// Position it on the screen
label.position = ccp(160,240);
// Add it to the scene so it can be displayed
[self addChild:label z:0];
}
#end
Consolas is not pre installed on iOS. Ether use a default font like Arial or put a Consolas.ttf file in your project.
After you added your .ttf file go to your info.plist and add a new row with the key Fonts provided by application. Add there Consolas.ttf too.
For a more detailed instruction to add a custom font visit: http://tetontech.wordpress.com/2010/09/03/using-custom-fonts-in-your-ios-application/
or here on stackoverflow:
Can I embed a custom font in an iPhone application?
As the title says. My UIViewController will not rotate no matter what. When it loads shouldAutorotateToInterfaceOrientation is being called but after that it doesnt.
UPDATE 1:
It's a really really wierd problem. At least for me. And i ll try to explain everything.
It's a navigation based app. Every controller has
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return YES;
}
Xcontroller is a child of Acontroller and it doesn't auto rotate. If Xcontroller become a child of Bcontroller then it will autorotate. So something is wrong with Acontroller. But Acontroller is identical (except its data) to Bcontroller.
Whats Wrong?
UPDATE 2:
I decided to recreate Acontroller. And it worked.I believe I was missing something stupid.
I am not sure whether it's the same reason as your case. But I experienced the same thing. the shouldAutorotateToInterfaceOrientation was only called once in the beginning.
After some serious debugging by taking code apart, I found that the reason is in my overridden init method.
I had this before:
- (id)initWithAlbum:(PhotoAlbum *)theAlbum {
if (self) {
self.photoAlbum = theAlbum;
}
return self;
}
And then I changed to this
- (id)initWithAlbum:(PhotoAlbum *)theAlbum {
if (self = [super init]) {
self.photoAlbum = theAlbum;
}
return self;
}
Note: the only difference is I added [super init] to call the parent init.
After this change, the rotation works well and the shouldAutorotateToInterfaceOrientation is being called everytime I rotate the screen.
Hope this help.
There can be several possible reasons your view controller does not rotate.
See Apple's official Q&A on this issue:
Why won't my UIViewController rotate with the device?
http://developer.apple.com/library/ios/#qa/qa2010/qa1688.html
Apple Q&A has the detailed solution for the problem.
Why won't my UIViewController rotate with the device?
http://developer.apple.com/library/ios/#qa/qa1688/_index.html
If you add a viewcontroller.view to uiwindow, you should set this viewcontroller as rootviewcontroller.
[self.window addSubview: mainViewcontroller.view];
self.window.rootViewController=mainViewcontroller;
Also, make sure you don't have rotation lock on. I spent a good hour trying to figure out why my views stopped rotating. shouldAutorotateToInterfaceOrientation was being called only once at start up and when Game Center leaderboards/achievements were presented.
I had the same issue - the reason was, that it was my first UIViewController, that i created on the fly in my ApplicationDelegate, added it's View to my UIWindow and immediately released it.
That's of course not correct as I just added the UIView of the UIViewController (retaining it) and than released the whole controller.
You should add your first UIViewController as an instance variable in Your ApplicationDelegate instead, and release it in Your ApplicationDelegate's dealloc-method.
In my case, the ViewController was inside a NavigationController which was used by a "parent" viewControlled that received the orientation changes.
What I did in this parent was:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
if(_navigationController){
return [_navigationController.topViewController shouldAutorotateToInterfaceOrientation: toInterfaceOrientation];
}
return toInterfaceOrientation == UIInterfaceOrientationPortrait;
}
This way you can implement your own orientation change logic depending on the currently visible controller.
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return YES; }
The above method if u using, you will able to call many time if u want with out any error.
I think there is no strange behavior here, it is called only one which is right. There is no need to call more than one to decide if the device should rotate to a direction or not.
This method just ask if the device should rotate to a direction or not.
If you want to handle the orientation change, you should register for the notification from the UIDeviceDidChangeOrientationNotification and override the following method:
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
[self presentModalViewController:self.landscapeViewController
animated:YES];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait &&
isShowingLandscapeView)
{
[self dismissModalViewControllerAnimated:YES];
isShowingLandscapeView = NO;
}
}
See more here.
I have the same problem but with two view controllers added to the application's UIWindow. The reason
is The view controller's UIView property is embedded inside UIWindow but alongside an additional view controller
From Apple Technical Q&A
http://developer.apple.com/library/ios/#qa/qa1688/_index.html
For a cutom camera overlay I need to find out, when the iris is opened, because my overlay will allways shown while the iris is close (and then animating to open).
Any ideas ?
You can listen for the PLCameraViewIrisAnimationDidEndNotification notification. Since this is not officially documented, you might be in violation of the Apple TOS, but I think so long as you write your code so that it's defensive against the possibility that the name or contract of this notification might change (so in the future you might not get the event) you'll probably be ok. In other words, use a timer or other technique to ensure that the thing you want done when the iris is open will definitely happen eventually even if you never get the notification...
Trivial example without the defensive programming. (Of course, you can register an interest only for this specific notification as well, see the docs for the notification center.)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(notificationCallback:)
name:nil
object:nil
];
- (void) notificationCallback:(NSNotification *) notification {
if ([[notification name] isEqualToString:#"PLCameraViewIrisAnimationDidEndNotification"]) {
NSLog(#"Iris open");
// we don't need to listen any more
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
It seems that PLCameraViewIrisAnimationDidEndNotification no longer gets notified in iOS5.
I can't figure out what is a suitable solution when the iris has finished opening, there must another option rather than using a 3 second timer.
Check here: https://devforums.apple.com/message/561008#561008
I have a ViewController (ALImagePickerController) which holds, initializes and presents the UIImagePickerController as a child view controller (I have another child view controller for presenting the taken image which is not shown here) and I present (as a modal) the ALImagePickerController when I want to use the camera. So during this the viewDidAppear of the ViewContoller I add an animation to bring in the camera overlay gracefully as the shutter animation disappears.
#interface ALImagePickerController ()
#property (nonatomic) UIImagePickerController *cameraController;
#property (nonatomic) CameraOverlayView *overlayView;
....
#end
#implementation ALImagePickerController
....
- (void)viewDidLoad {
[super viewDidLoad];
[UIApplication sharedApplication].statusBarHidden = YES;
self.cameraController = [UIImagePickerController new];
self.cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraController.delegate = self;
self.cameraController.allowsEditing = NO;
self.cameraController.showsCameraControls = NO;
....
self.overlayView = [CameraOverlayView new];
....
self.overlayView.alpha = 0;
self.cameraController.cameraOverlayView = self.overlayView;
....
// add as child view controller
[self addChildViewController:self.cameraController];
[self.view addSubview:self.cameraController.view];
[self.cameraController didMoveToParentViewController:self];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[UIApplication sharedApplication].statusBarHidden = NO;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// smoothly bring in the overlay as the native camera shutter animation opens.
[UIView animateWithDuration:0.2 delay:0.3 options:UIViewAnimationCurveEaseOut animations:^{
self.overlayView.alpha = 1.f;
} completion:nil];
}
....
#end
The way I solved this problem is I initialize all the elements with the hidden property set to YES, then call a 3-second delayed selector after I call the camera, where I set all the elements to hidden = NO. It's not an ideal solution but it seems to work, and any lag after the iris is opened is negligible.
You should already know when the camera is ready to take a picture. At least the way I use a custom camera overlay, I init the view with something like self.sourceType = UIImagePickerControllerSourceTypeCamera; and the other usual setup, and the camera is ready (or "iris is open") at that point.
In summary, if one is using a custom camera overlay the way I am used to using it, one will know when the iris is open because it is under your control.