I am using sprite-kit and targeted iOS 7. I want to show leaderboard with button in my MenuScene.
my helper method codes.
#import "GameKitHelper.h"
NSString *const PresentAuthenticationViewController =
#"present_authentication_view_controller";
#interface GameKitHelper()<GKGameCenterControllerDelegate>
#end
#implementation GameKitHelper {
BOOL _enableGameCenter;
}
+ (instancetype)sharedGameKitHelper
{
static GameKitHelper *sharedGameKitHelper;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedGameKitHelper = [[GameKitHelper alloc] init];
});
return sharedGameKitHelper;
}
- (id)init
{
self = [super init];
if (self) {
_enableGameCenter = YES;
}
return self;
}
- (void)showGKGameCenterViewController:
(UIViewController *)viewController
{
if (!_enableGameCenter) {
NSLog(#"Local play is not authenticated");
}
GKGameCenterViewController *gameCenterViewController =
[[GKGameCenterViewController alloc] init];
gameCenterViewController.gameCenterDelegate = self;
gameCenterViewController.viewState =
GKGameCenterViewControllerStateAchievements;
[viewController presentViewController:gameCenterViewController
animated:YES
completion:nil];
}
I want to Leaderboard Button in this class.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"start"]) {
MyScene *myScene = [MyScene sceneWithSize:self.size];
[self.view presentScene:myScene transition:[SKTransition pushWithDirection:SKTransitionDirectionLeft duration:0.5]];
}
if ([node.name isEqualToString:#"gameCenter"]) {
//HERE MY LEADERBOARD BUTTON ACTION
//I don't know what i write here...
{
}
I tried so much methods but these working in iOS 6, I targeted iOS 7.
I tried this:
[[GameKitHelper sharedGameKitHelper] showGKGameCenterViewController:self]; Xcode says for self
Incompatible pointer types sending 'GameMenuScene *' to parameter of type 'UIViewController *'
Andrey is right. gameKitHelper means [gameKitHelper sharedGameKitHelper]. like this example
if ([node.name isEqualToString:#"gameCenter"]) {
UIViewController *vc = self.view.window.rootViewController;
[[GameKitHelper sharedGameKitHelper] showGKGameCenterViewController:vc];
}
Keep coding :)
if ([node.name isEqualToString:#"gameCenter"]) {
UIViewController *vc = self.view.window.rootViewController;
[[GameKitHelper sharedGameKitHelper] showGKGameCenterViewController:vc];
}
But actually you should present another ViewController from your ViewController, not from SKScene
Try this, it's easy to implement and works well:
https://github.com/nihalahmed/GameCenterManager
inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(openLeaderboard)
name:#"TestNotification"
object:nil];
Inside VC:
- (void) openLeaderboard
{
// Open Leaderboards here
}
In your Scene:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:self];
Related
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
NSLog(#"touch recognised");
CGPoint location = [aTouch locationInView:_mainView];
__block NSString *option = [[NSString alloc] init];
__block NSString *type = [[NSString alloc] init];
for (Selectors *tempView in _mainView.subviews) {
if (CGRectContainsPoint(tempView.frame, location)) {
NSLog(#"%# : %#", tempView.option, tempView.type);
option = tempView.option;
type = tempView.type;
break;
}
}
[self moveToNextWeldCustomViewWithOption:option andType:type];
}
Is in my previous UIVIewController - then we present the next UIViewController here
-(void)moveToNextWeldCustomViewWithOption:(NSString *)option andType:(NSString *)type {
WeldDesignViewController *lobby = [self.storyboard instantiateViewControllerWithIdentifier:#"WeldDesignViewController"];
lobby.option = option;
lobby.type = type;
[self presentViewController:lobby animated:NO completion:nil];
}
In the next UIViewController I don't do anything until the viewDidAppear method - However, the touches began is still being recognised in the next viewcontroller.
I think the issue is that the VC you are calling "lobby" is being deallocated after you present it. This takes it out of consideration in the responder chain. Move that reference to be a property of the presenting view controller:
#property (nonatomic, strong) WeldDesignViewController* lobby;
// ...
-(void)moveToNextWeldCustomViewWithOption:(NSString *)option andType:(NSString *)type {
self.lobby = [self.storyboard instantiateViewControllerWithIdentifier:#"WeldDesignViewController"];
lobby.option = option;
lobby.type = type;
[self presentViewController:self.lobby animated:NO completion:nil];
}
You may also need to implement touchesBagan in the presented VC, as it is probably following the responder chain to the previous controller.
Any one have any idea how can we implement 3d touch feature in objective C? I already check the app documentation but no example is related to objective C code.
Any sample code or example, how to implement ? Thanks in Advance.
The way I am doing this is to use a DFContinuousForceTouchGestureRecognizer that I have made available. This is a gesture recognizer extension that detects force touch and works alongside other gesture recognizers.
The DFContinuousForceTouchGestureRecognizer provides continuous updates about the pressure changes so you can do nice things like augment the view as the user varies their pressure on it, as opposed to just triggering a single event. If you just want a single event you can ignore eveything in the DFContinuousForceTouchDelegate except the - (void) forceTouchRecognized callback.
https://github.com/foggzilla/DFContinuousForceTouchGestureRecognizer
You can download this and run the sample app on a device that supports force press to see how it feels.
In your UIViewController implement:
- (void) viewDidLoad {
[super viewDidLoad];
_forceTouchRecognizer = [[DFContinuousForceTouchGestureRecognizer alloc] init];
_forceTouchRecognizer.forceTouchDelegate = self;
[self.imageView addGestureRecognizer:_forceTouchRecognizer];
}
implement the delegate protocol for force touch:
#pragma DFContinuousForceTouchDelegate
- (void) forceTouchRecognized:(DFContinuousForceTouchGestureRecognizer*)recognizer {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:#"Force Touch" message:#"YEAH!!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
});
}
- (void) forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer*)recognizer didStartWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
CGFloat transformDelta = 1.0f + ((force/maxForce) / 3.0f);
self.imageView.transform = CGAffineTransformMakeScale(transformDelta, transformDelta);
[self.imageView setNeedsDisplay];
}
- (void) forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer*)recognizer didMoveWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
CGFloat transformDelta = 1.0f + ((force/maxForce) / 3.0f);
self.imageView.transform = CGAffineTransformMakeScale(transformDelta, transformDelta);
[self.imageView setNeedsDisplay];
}
- (void) forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer*)recognizer didCancelWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
- (void) forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer*)recognizer didEndWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
- (void) forceTouchDidTimeout:(DFContinuousForceTouchGestureRecognizer*)recognizer {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
Note that this will only be useful on a device that supports force touch.
Also you should not add the UIContinuousForceTouchGestureRecognizer to a view if are you running on iOS8 or under since it uses the new force property on UITouch only available in iOS9.
If you add this on iOS8 it will crash, so conditionally add this recognizer based on what iOS version you are running on if you are supporting versions older than iOS9.
Here is an example adapted from yeungkaho's example on github
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self handleTouches:touches];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self handleTouches:touches];
}
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self setForcePercentage:0];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self setForcePercentage:0];
}
-(void)handleTouches:(NSSet<UITouch *> *)touches{
for (UITouch *touch in touches) {
CGFloat force = touch.force;
CGFloat percentage = force/touch.maximumPossibleForce;
[self setForcePercentage:percentage];
break;
}
}
-(void)setForcePercentage:(CGFloat)percentage{
NSLog(#"LEVEL = %f",percentage*100);
}
I am sharing the source code for pressing on app icon populate 4 item in list
Step 1:- Import class in appDelegate.m
import sys/utsname.h
Step 2:-
#pragma MARK for Get Machine Name
- (NSString *) machineName {
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if([[self machineName] isEqualToString:#"iPhone8,2"]|| [[self machineName] isEqualToString:#"iPhone8,1"]) {
[self addEventsFor3DTouchEvents];
}
return YES;
}
pragma MARK for Adding Action for Three D Touch Events
- (void) addEventsFor3DTouchEvents {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) {
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc] initWithType:#"dynamic1" localizedTitle:TITLE_NAME_1 localizedSubtitle:#"" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:TITLE_IMAGE_NAME_1] userInfo:nil];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc] initWithType:#"dynamic1" localizedTitle:TITLE_NAME_2 localizedSubtitle:#"" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:TITLE_IMAGE_NAME_2] userInfo:nil];
UIApplicationShortcutItem *item3 = [[UIApplicationShortcutItem alloc] initWithType:#"dynamic1" localizedTitle:TITLE_NAME_3 localizedSubtitle:#"" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:TITLE_IMAGE_NAME_3] userInfo:nil];
UIApplicationShortcutItem *item4 = [[UIApplicationShortcutItem alloc] initWithType:#"dynamic1" localizedTitle:TITLE_NAME_4 localizedSubtitle:#"" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:TITLE_IMAGE_NAME_4] userInfo:nil];
[[UIApplication sharedApplication] setShortcutItems: #[ item1, item2, item3, item4 ]];
}
}
#pragma mark - 3DTouch Delegate Methods
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
[self moveThrough3DTouch:shortcutItem];
}
#pragma MARK for Handling Action for Three D Touch Events
- (void)moveThrough3DTouch:(UIApplicationShortcutItem *)temp {
if ([temp.localizedTitle isEqualToString:TITLE_NAME_1]) {
[self.tabBarController setSelectedIndex:0];
} else if([temp.localizedTitle isEqualToString:TITLE_NAME_2]) {
[self.tabBarController setSelectedIndex:1];
} else if([temp.localizedTitle isEqualToString:TITLE_NAME_3]) {
[self.tabBarController setSelectedIndex:2];
} else if([temp.localizedTitle isEqualToString:TITLE_NAME_4]) {
[self.tabBarController setSelectedIndex:3];
}
}
**I am using Tab Bar controller in my app, If want to move in view controlled
- (void) moveToControllerScene {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:STORY_BOARD_IDENTIFIER bundle:nil];
YOUR_CONTROLLER_OBJECT *obj = [storyboard instantiateViewControllerWithIdentifier:#"YOUR_CONTROLLER_OBJECT"];
[navController pushViewController:obj animated:YES];
}
When I press the play Button or Share Button the app freezes, but only the first time.
After the first time it runs without a freeze.
The Duration of the freeze is 2-4 seconds.
I tried for awhile to find a solution, but everything I try does not work.
GameViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
SKView * skView = (SKView *)self.view;
SKScene * scene = [Menu sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
- (void) openShare
{
int highScore = [self highScoreAbruf];
NSString *shareText= [NSString stringWithFormat:#"The HIghScore is %i", highScore];
NSArray *itemsToShare = #[shareText];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];
}
- (int) highScoreAbruf
{
NSUserDefaults *myHighScore = [NSUserDefaults standardUserDefaults];
int highScore = [myHighScore integerForKey:#"Score"];
return highScore;
}
Menu.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"PlayButton"])
{
PlayButton.hidden = YES;
PlayButtonPressed.hidden = NO;
[self restartButtonPressed];
//[self performSelector:#selector(restartButtonPressed) withObject:nil afterDelay:(0.5)];
}
if ([node.name isEqualToString:#"ShareButton"])
{
ShareButton.hidden = YES;
ShareButtonPressed.hidden = NO;
NSTimer *buttonTimer = [NSTimer scheduledTimerWithTimeInterval:(0.5)
target:self
selector:#selector(ShareMethod)
userInfo:NULL
repeats:NO];
}
}
- (void) restartButtonPressed
{
[self.scene.view presentScene:[GameMyScene sceneWithSize:self.size]];
}
- (void) ShareMethod
{
GameViewController *vc = self.view.window.rootViewController;
[vc openShare];
}
I have two layers set up like so in one scene:
header file for scene:
#interface GameScene1 : CCScene {
GameLayer *gameLayer;
HUDLayer *hudLayer;
}
Main file for scene:
-(id)init {
self = [super init];
if (self != nil) {
gameLayer = [GameLayer node];
[self addChild:gameLayer];
hudLayer = [HUDLayer node];
[self addChild:hudLayer];
}
return self;
}
HUD layer header:
#interface HUDLayer : CCNode {
CCSprite *background;
CGSize screenSize;
}
-(void)updateMonstersSlayed:(NSString*)value;
HUD layer main:
#implementation HudLayer
-(id)init
{
self = [super init];
if (self)
{
CGSize viewSize = [[CCDirector sharedDirector] viewSize];
monstersSlayed = [CCLabelTTF labelWithString:#"Monsters Killed: 0" fontName:#"Arial" fontSize:15];
monstersSlayed.position = ccp(viewSize.width * 0.85, viewSize.height * 0.1 );
[self addChild:monstersSlayed];
}
return self;
}
-(void)updateMonstersSlayed:(NSString*)value
{
monstersSlayed.string = value;
}
Game Layer main
- (BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair collisionPlayer:(CCNode *)user collisionMonster:(CCNode *)monster
{
if (holdingWeapon)
{
HudLayer *myHud = [[HudLayer alloc] init];
[myHud updateMonstersSlayed:#"Monsters Killed: 1"];
}
}
Simply trying to get it set to where I can set text from the Game Layer to show up in a Label in the Hud Layer.
How would I accomplish this in Cocos2d 3?
There are many ways you can do this. But for the sake of simplicity the easiest way you can do this is via notifications. For example in the hud add:
#implementation HudLayer
- (void)onEnter
{
[super onEnter];
NSNotificationCenter* notiCenter = [NSNotificationCenter defaultCenter];
[notiCenter addObserver:self
selector:#selector(onUpdateMonsterText:)
name:#"HudLayerUpdateMonsterTextNotification"
object:nil];
}
- (void)onExit
{
[super onExit];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)onUpdateMonsterText:(NSNotification *)notification
{
NSDictionary* userInfo = notification.userInfo;
if (userInfo)
{
NSString* text = userInfo[#"text"];
if (text)
{
[self updateMonstersSlayed:text];
}
else
{
CCLOG(#"Monster hud text param is invalid!.");
}
}
else
{
CCLOG(#"Monster hud user info invalid!");
}
}
#end
Then anywhere in your application where you want to update text you can just post the notification. Using your physics collision began example:
- (BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair
*emphasized text*collisionPlayer:(CCNode *)user collisionMonster:(CCNode *)monster
{
if (holdingWeapon)
{
NSDictionary* userInfo = #{#"text" : #"Monsters Killed: 1"};
NSString* notiName = #"HudLayerUpdateMonsterTextNotification";
[[NSNotificationCenter defaultCenter] postNotificationName:notiName
object:self userInfo:userInfo];
}
}
Hope this helps.
You can use methods. Make a method in HUD layer class.
-(void) giveMeMyText:(NSString*)someText
{
do something with my someText
}
Don't forget to make the method visible in HUD.h -(void) giveMeMyText; Then import HUD layer class in GameScene1 #import "HUDlayer.h" and use it.
HUDLayer* myHud = [[HUDLayer alloc] init];
[myHud giveMeMyText:#"say hi!"];
You could use delegation, so your scene would implement GameLayerProtocol and the delegate of GameLayer. That way the scene would be notified of any changes the GameLayer has and act appropriately on the HudLayer.
For example:
// GameLayer class
#protocol GameLayerProtocol <NSObject>
- (void)someThingHappenedInGameLayer;
#end
#interface GameLayer : CCNode
#property (nonatomic, weak) id<GameLayerProtocol> delegate;
#end
#implementation GameLayer
- (void)someActionInGameLayer
{
[self.delegate someThingHappenedInGameLayer];
}
#end
// Scene class
#interface IntroScene : CCScene <GameLayerProtocol>
#end
#implementation IntroScene
// Implement protocol methods
- (void)someThingHappenedInGameLayer
{
//Do something with your HUDLayer here
}
#end
I have this Class:
//Interface
#interface SavingDataPlist : SimpleTimedGameRecipe
{
NSMutableArray *moles;
int tagCount;
int moleCount;
CCSprite *mallet;
CGPoint malletPosition;
}
-(CCLayer*) runRecipe;
-(void) step;
-(void) initBackground;
-(void) createMoleAtPosition:(CGPoint)point withZ:(float)z;
-(void) processMoleHit;
-(void) addHiScoresToMenu;
-(void) loadHiScores;
-(void) addHiScore;
-(void) deleteHiScores;
-(void) startNewGame;
-(void) gameOver;
-(void) step:(ccTime)delta;
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
#end
which in its reunRecipe method calls this:
[self createMoleAtPosition:ccp(50,205) withZ:0];
and that call corresponds to this method:
-(void) createMoleAtPosition:(CGPoint)point withZ:(float)z {
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSprite *back = [CCSprite spriteWithSpriteFrame:[cache spriteFrameByName:#"mole_back.png"]];
back.position = ccp(point.x, point.y);
[self addChild:back z:z tag:tagCount];
tagCount++;
Mole *mole = [Mole spriteWithSpriteFrame:[cache spriteFrameByName:#"mole_normal.png"]];
[mole setDownPosition:ccp(point.x,point.y-30)];
[self addChild:mole z:z tag:tagCount];
[moles addObject:mole];
NSLog(#"moles.count %d", moles.count);
tagCount++;
CCSprite *front = [CCSprite spriteWithSpriteFrame:[cache spriteFrameByName:#"mole_front.png"]];
front.position = ccp(point.x, point.y);
[self addChild:front z:z tag:tagCount];
tagCount++;
}
The Mole Class init method looks like this:
-(id)init {
NSLog(#"moleinit");
self = [super init];
if (self != nil) {
state = MOLE_DOWN;
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
//
//MEVPCHANGE
//Create framenumber array to populate ccanimation later
NSMutableArray *animationFramesArray = [[NSMutableArray alloc] init];
NSMutableArray *animationFramesArray2 = [[NSMutableArray alloc] init];
//MEVPCHANGE - add frames to array
[animationFramesArray addObject:[cache spriteFrameByName:#"mole_normal.png"]];
[animationFramesArray2 addObject:[cache spriteFrameByName:#"mole_hit.png"]];
normalAnim = [[CCAnimation alloc] initWithSpriteFrames:animationFramesArray delay:1.0f];
hitAnim = [[CCAnimation alloc] initWithSpriteFrames:animationFramesArray2 delay:1.0f];
//MEVPCHANGE - create animation
[animationFramesArray release];
[animationFramesArray2 release];
//
[self runAction:[CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:normalAnim]]];
}
return self;
}
Now in cocos2d v1.0 this code works fine. The Mole's get created and they pop up and down when they get whacked. But in v2.0, I only get the front facing moles but the NSLog in the Mole init method doesnt even get called (as evidenced by the lack of NSLog in the console).