Tutorial details

Tutorial 30 - Codea v1.5.2: Objective C Add On, Game Center | App Code for Sale | Preview

Tutorial 30 - Codea v1.5.2: Objective C Add On, Game Center | iOS Tutorial

How to add native extensions to exported Codea projects

Overview PAGE TOP

com.png
Figure 0. iOS Dev Center

30.1 Overview PAGE TOP

CodeaAddon is an experimental protocol for adding native extensions to exported Codea projects. You must deal with Lua directly to register your functions and globals. This protocol should be considered alpha and is subject to change in future Codea releases.As with the previous tutorial on iAds, we have provided a lot of background on Game Center in these tutorials:

  1. Tutorial 19 - Integrating Game Centre (Part 1);
  2. Tutorial 20 - Integrating Game Centre (Part 2);
  3. Tutorial 21 - Integrating Game Center (Part 3).

Have a look at the above to refresh your knowledge on what is required from an iTunes Connect perspective as we will only cover that area briefly in this tutorial.

amio.png
Figure 1. Find out the Bundle Identifier for your App.

30.2 Registering your Application in iTunes Connect PAGE TOP

In order to test your app's Game Center functionality you need to register an app ID associated with this app which enables Game Center. The association is done via the bundle identifier of your app (Figure 1). Click on the app title in the top left of the project navigator screen in Xcode to bring up this screen. Make sure that you have selected the "Summary" tab. Write down the bundle identifier shown, we will need this shortly.

10047.png
Figure 2. Set up a new App ID for your app.

Log into your apple developer account, go to the iOS Dev Center (Figure 0) and select the Certificates, Identifiers & Profiles link on the right hand side of the page. Select a name for your app ID (pick something you can remember e.g. we used AudioDemoAppID) and fill in the App ID Suffix bundle identifier. This is the critical step which will link your app to the configuration in iTunes Connect. Use the bundle identifier that you wrote down earlier. Click "confirm" and then "submit".

seri.png
Figure 3. Associate your bundle identifier with the App ID.

Head back to the iOS Dev Center (Figure 0) and this time click on iTunes Connect link in the top right of the page. You will be asked to sign in again, do so and then click on the Manage your Apps link (Figure 4).

dujo.png
Figure 4. iTunes Connect

On the Manage your Apps page (Figure 5), click on the "Add New App" button at the top left of the screen. Click on iOS App on the next screen.

mene.png
Figure 5. Manage your Apps

Fill in the app name, SKU number (this can be any unique identifier, we normally use the date), and then select the App ID that you just created for the bundle identifier (Figure 6). Click "Continue" when you are done.

dork.png
Figure 6. iTunes Connect App Information.

Fill in all the meta data (have a look at the earlier tutorials if you get stuck) and save the configuration. When you are done (Figure 7), we can enable Game Center for your app. Click on the "Manage Game Center" button on the right hand side of the page (Figure 7).

boyo.png
Figure 7. Metadata addition complete.

Click on the button that says "Enable for Single Game" and then either configure some achievements and leader boards or just click "Done". We can now test our exported app once we have included the Game Center add on.

boll.png
Figure 8. Adding the GameKit Framework.

30.3 Add the GameKit Framework to Your App PAGE TOP

Fire up Xcode and load the exported version of your Codea application (See Tutorial 27). Click on the imported project file at the top of the project navigator then in the Build Phases tab, scroll down to the link binary with libraries area and select the drop down arrow. Click on the "+" button below your existing frameworks to add a new framework. Find GameKit and click on "Add"

30.4 Changes to your Exported AppDelegate Files PAGE TOP

All of the source code files are provided at the end of this tutorial. You need to update AppDelegate.h as follows:

// 
// AppDelegate.h 
// AudioDemo 
// 
// Used to demonstrate the audio, game center and iAds add on libraries 
// 
// Created by Reefwing Software on Sunday, 14 April 2013 
// Copyright (c) Reefwing Software. All rights reserved. 
// 

    #import <UIKit/UIKit.h> 
    #import "AudioAddOn.h" 
    #import "IAdsAddOn.h" 
    #import "GameCenterAddOn.h" 

    @class CodeaViewController; 

    @interface AppDelegate : UIResponder <UIApplicationDelegate> 

    @property (strong, nonatomic) IAdsAddOn *iAdsAddOn; 
    @property (strong, nonatomic) AudioAddOn *audioAddOn; 
    @property (strong, nonatomic) GameCenterAddOn *gameCenterAddOn; 
    @property (strong, nonatomic) UIWindow *window; 
    @property (strong, nonatomic) CodeaViewController *viewController; 

@end

And AppDelegate.mm, should now look like:

// 
// AppDelegate.mm 
// AudioDemo 
// 
// Created by Reefwing Software on Sunday, 14 April 2013 
// Copyright (c) Reefwing Software. All rights reserved. 
// 

#import "AppDelegate.h" 
#import "CodeaViewController.h" 

@implementation AppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.viewController = [[CodeaViewController alloc] init]; 

    // Create and add our AudioAddOn to Codea 

    self.audioAddOn = [[AudioAddOn alloc] init]; 
    [self.viewController registerAddon: self.audioAddOn]; 

    // Create and add our iAdsAddOn to Codea 

    self.iAdsAddOn = [[IAdsAddOn alloc] init]; 
    [self.viewController registerAddon: self.iAdsAddOn]; 

    // Create and add our GameCenterAddOn to Codea 

    self.gameCenterAddOn = [[GameCenterAddOn alloc] init]; 
    [self.viewController registerAddon: self.gameCenterAddOn]; 

    NSString* projectPath = [[[NSBundle mainBundle] bundlePath]    stringByAppendingPathComponent:@"AudioDemo.codea"]; 

    [self.viewController loadProjectAtPath:projectPath]; 

    self.window.rootViewController = self.viewController; 
    [self.window makeKeyAndVisible]; 

    return YES; 

} 

- (void)applicationWillResignActive:(UIApplication *)application 
{ 

} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 

} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 

} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 

} 

- (void)applicationWillTerminate:(UIApplication *)application 
{ 

} 

@end

Obviously there is no need to register the iAds and Audio add ons if you are just using Game Center. We have just left these in to demonstrate how you can stack add ons.

mon.png
Figure 9. If you try to show Achievements or Leaderboards with none set up in iTunes Connect, you will see this screen.

30.5 The Game Center Add On PAGE TOP

You need to add the GameCenterAddOn.h and GameCenterAddOn.m files to your project (plus the other iAds and Audio add on classes if you are using them). These are available below.

To do this, right click on the Addons folder in the project navigator and select Add files to "YourProjectName"... Navigate to where ever you saved these files and select them.

This Game Center Add On will make four new functions available in your Lua code:

  • gameCenterStart();

  • showLeaderBoardWithIdentifier(int ident);

  • showAchievementsView(); and

  • playerIsAuthenticated;

You need to call gameCenterStart() first as your game must authenticate a local player before you can use any Game Center classes.

osi.png
Figure 10. You may need to sign in the first time you try to authenticate a player.

If you want to add more Game Center functionality the just follow the pattern in the add on. For example, if you want to add a save score function then, in GameCenterAddOn.h add:

static int saveScore(struct lua_State *state);

Then in GameCenterAddOn.m add/modify:

// Add to method

- (void)codea:(CodeaViewController*)controller didCreateLuaState:(struct lua_State*)L
{
    ...
    lua_register(L, "saveScore", saveScore);
    ...
}

// New Objective C method

- (void) saveNewScore: (int) score
{
    // INSERT YOUR LEADERBOARD IDENTIFIER IN THE LINE BELOW
    // Replace "Easy Difficulty" with your identifier from iTunes Connect

    GKScore *scoreReporter = [[GKScore alloc] initWithCategory: @"Easy Difficulty"];

    if (scoreReporter)
    {
        scoreReporter.value = score;

        [scoreReporter reportScoreWithCompletionHandler: ^(NSError *error)
        {
            if (error != nil)
            {
                // handle the reporting error

                NSLog(@"Game Center: Error Saving Score - %@", [error localizedDescription]);
            }
        }];   
    }
}

// New C function

static int saveScore(struct lua_State *state)
{
    [gameCenterAddOnInstance saveNewScore: lua_tonumber(state, 1)];

    return 0;
}

Then in your Lua code you can use saveScore(yourNewScore).

rag.png
Figure 11. Player Authenticated.

30.6 Download the Code PAGE TOP

1   //
2   //  AppDelegate.h
3   //  AudioDemo
4   //
5   //  Used to demonstrate the audio, game center and iAds add on libraries
6   //
7   //  Created by Reefwing Software on Sunday, 14 April 2013
8   //  Copyright (c) Reefwing Software. All rights reserved.
9   //
10  
11  #import <UIKit/UIKit.h>
12  #import "AudioAddOn.h"
13  #import "IAdsAddOn.h"
14  #import "GameCenterAddOn.h"
15  
16  @class CodeaViewController;
17  
18  @interface AppDelegate : UIResponder <UIApplicationDelegate>
19  
20  @property (strong, nonatomic) IAdsAddOn *iAdsAddOn;
21  @property (strong, nonatomic) AudioAddOn *audioAddOn;
22  @property (strong, nonatomic) GameCenterAddOn *gameCenterAddOn;
23  @property (strong, nonatomic) UIWindow *window;
24  @property (strong, nonatomic) CodeaViewController *viewController;
25  
26  @end

1   //
2   //  AppDelegate.mm
3   //  AudioDemo
4   //
5   //  Created by Reefwing Software on Sunday, 14 April 2013
6   //  Copyright (c) Reefwing Software. All rights reserved.
7   //
8   
9   #import "AppDelegate.h"
10  #import "CodeaViewController.h"
11  
12  @implementation AppDelegate
13  
14  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
15  {
16      self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
17      self.viewController = [[CodeaViewController alloc] init];
18      
19      //  Create and add our AudioAddOn to Codea
20      
21      self.audioAddOn = [[AudioAddOn alloc] init];
22      [self.viewController registerAddon: self.audioAddOn];
23      
24      //  Create and add our iAdsAddOn to Codea
25      
26      self.iAdsAddOn = [[IAdsAddOn alloc] init];
27      [self.viewController registerAddon: self.iAdsAddOn];
28      
29      //  Create and add our GameCenterAddOn to Codea
30      
31      self.gameCenterAddOn = [[GameCenterAddOn alloc] init];
32      [self.viewController registerAddon: self.gameCenterAddOn];
33      
34      NSString* projectPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"AudioDemo.codea"];
35      
36      [self.viewController loadProjectAtPath:projectPath];
37      
38      self.window.rootViewController = self.viewController;
39      [self.window makeKeyAndVisible];
40      
41      return YES;
42  }
43  
44  - (void)applicationWillResignActive:(UIApplication *)application
45  {
46  }
47  
48  - (void)applicationDidEnterBackground:(UIApplication *)application
49  {
50  }
51  
52  - (void)applicationWillEnterForeground:(UIApplication *)application
53  {
54  }
55  
56  - (void)applicationDidBecomeActive:(UIApplication *)application
57  {
58  }
59  
60  - (void)applicationWillTerminate:(UIApplication *)application
61  {
62  }
63  
64  @end

1   //
2   //  AudioAddOn.h
3   //  AudioDemo
4   //
5   //  Created by David Such on 13/04/13.
6   //  Copyright (c) 2013 Reefwing Software. All rights reserved.
7   //
8   //  Version:    1.0 - Original (13/04/13)
9   //              1.1 - Volume control & monitoring added, metering enabled (14/04/13)
10  //              1.2 - Minor refactoring (19/04/13)
11  
12  #import <Foundation/Foundation.h>
13  #import <AVFoundation/AVFoundation.h>
14  #import "CodeaAddon.h"
15  
16  id audioAddOnInstance;
17  
18  //  This class conforms to the CodeaAddon & AVAudioPlayerDelegate Protocols 
19  
20  @interface AudioAddOn : NSObject<CodeaAddon, AVAudioPlayerDelegate>
21  
22  @property (strong, nonatomic) AVAudioPlayer *player;
23  
24  //  Forward declare our Lua Audio functions. These are static to confine their scope
25  //  to this file. By default c functions are global.
26  
27  static int playMusic(struct lua_State *state);
28  static int stopMusic(struct lua_State *state);
29  
30  static int getVolume(struct lua_State *state);
31  static int setVolume(struct lua_State *state);
32  
33  static int peakPowerForChannel(struct lua_State *state);
34  static int averagePowerForChannel(struct lua_State *state);
35  
36  @end

1   //
2   //  AudioAddOn.m
3   //  AudioDemo
4   //
5   //  Created by David Such on 13/04/13.
6   //  Copyright (c) 2013 Reefwing Software. All rights reserved.
7   //
8   //  Version:    1.0 - Original (13/04/13)
9   //              1.1 - Volume control & monitoring added, metering enabled (14/04/13)
10  //              1.2 - Minor refactoring (19/04/13)
11  
12  #import "AudioAddOn.h"
13  #import "lua.h"
14  
15  @implementation AudioAddOn
16  
17  #pragma mark - Initialisation
18  
19  - (id)init
20  {
21      self = [super init];
22      if (self)
23      {
24          //  Initialise the Audio Player with your mp3 file.
25          
26          NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
27                                               pathForResource:@"LunarLander"
28                                               ofType:@"mp3"]];
29          
30          NSError *error;
31          
32          _player = [[AVAudioPlayer alloc] initWithContentsOfURL: url error: &error];
33          
34          if (error)
35              NSLog(@"Error initialiasing Audio Add On: %@", [error localizedDescription]);
36          else
37          {
38              // Player initialised, assign delegate to this class
39              
40              [_player setDelegate: self];
41              
42              //  Calling prepareToPlay preloads buffers and acquires the audio hardware needed for playback,
43              //  which minimizes the lag between calling the play method and the start of sound output.
44              
45              [_player prepareToPlay];
46              
47              //  A value of 0, which is the default, means to play the sound once. Set a positive integer
48              //  value to specify the number of times to return to the start and play again. For example,
49              //  specifying a value of 1 results in a total of two plays of the sound. Set any negative
50              //  integer value to loop the sound indefinitely until you call the stop method.
51              
52              [_player setNumberOfLoops: -1];
53              
54              //  The default value for the meteringEnabled property is off (Boolean NO). Before using metering
55              //  for an audio player, you need to enable it by setting this property to YES.
56              
57              [_player setMeteringEnabled: YES];
58              
59              //  audioAddOnInstance allows us to access self from within the c functions.
60              
61              audioAddOnInstance = self;
62          }
63      }
64      return self;
65  }
66  
67  #pragma mark - CodeaAddon Delegate
68  
69  //  Classes which comply with the <CodeaAddon> Protocol must implement this method
70  
71  - (void) codea:(CodeaViewController*)controller didCreateLuaState:(struct lua_State*)L
72  {
73      NSLog(@"AudioAddon Registering Functions");
74      
75      //  Register the Audio functions, defined below
76      
77      lua_register(L, "playMusic", playMusic);
78      lua_register(L, "stopMusic", stopMusic);
79      lua_register(L, "setVolume", setVolume);
80      lua_register(L, "getVolume", getVolume);
81      lua_register(L, "peakPowerForChannel", peakPowerForChannel);
82      lua_register(L, "averagePowerForChannel", averagePowerForChannel);
83  }
84  
85  #pragma mark - Audio Add On Functions and associated Methods
86  
87  //  Objective C Methods
88  
89  - (void)startPlayer
90  {
91      [self.player play];
92  }
93  
94  - (void)stopPlayer
95  {
96      if ([self.player isPlaying])
97          [self.player stop];
98  }
99  
100 - (void)setPlayerVolume: (int)setting
101 {
102     // The volume property is the playback gain for the AV audio player object,
103     // it expects a float ranging from 0.0 through 1.0.
104     //
105     // Our Codea slider control returns an integer from 0 to 100 so we need to
106     // convert this to a float in the appropriate range before applying it to
107     // our player. As a defensive measure we will clamp the result between 0.0 and 1.0.
108     
109     float floatSetting = MAX(0.0f, MIN((float)setting / 100.0f, 1.0f));
110     
111     [self.player setVolume: floatSetting];
112 }
113 
114 - (int)getPlayerVolume
115 {
116     return (self.player.volume * 100.0f);
117 }
118 
119 - (int)getPeakPower: (NSUInteger)channel
120 {
121     if ([self.player isPlaying])
122     {
123         //  Refresh the average and peak power values for all channels of our audio player.
124         
125         [self.player updateMeters];
126         
127         //  Peak power is a floating-point representation, in decibels, of a given audio channel’s current peak power.
128         //  A return value of 0 dB indicates full scale, or maximum power while a return value of -160 dB indicates
129         //  minimum power (that is, near silence).
130         //
131         //  If the signal provided to the audio player exceeds ±full scale, then the return value may exceed 0
132         //  (that is, it may enter the positive range).
133         //
134         //  Channel numbers are zero-indexed. A monaural signal, or the left channel of a stereo signal, has channel number 0.
135         
136         float power = -160.0f;  // Initialise to silence
137         
138         if (channel <= [self.player numberOfChannels])
139             power = [self.player peakPowerForChannel: channel];
140         
141         //  Our dial is expecting a value between 0 and 100.
142         
143         if (power >= 0)
144             return 100;
145         else
146         {
147             power += 160.0f;                        //  power is now a +ve float between 0 and 160
148             power = (power / 160.0f) * 100.0f;      //  change to a percentage
149             return (int)power;
150         }
151     }
152     else
153         return 0;
154 }
155 
156 - (int)getAveragePower: (NSUInteger)channel
157 {
158     if ([self.player isPlaying])
159     {
160         //  Refresh the average and peak power values for all channels of our audio player.
161         
162         [self.player updateMeters];
163         
164         //  A floating-point representation, in decibels, of a given audio channel’s current average power.
165         //  A return value of 0 dB indicates full scale, or maximum power; a return value of -160 dB indicates
166         //  minimum power (that is, near silence).
167         //
168         //  If the signal provided to the audio player exceeds ±full scale, then the return value may exceed 0
169         //  (that is, it may enter the positive range).
170         //
171         //  Channel numbers are zero-indexed. A monaural signal, or the left channel of a stereo signal, has channel number 0.
172         
173         float power = -160.0f;  // Initialise to silence
174         
175         if (channel <= [self.player numberOfChannels])
176             power = [self.player averagePowerForChannel: channel];
177         
178         //  Our dial is expecting a value between 0 and 100.
179         
180         if (power >= 0)
181             return 100;
182         else
183         {
184             power += 160.0f;                        //  power is now a +ve float between 0 and 160
185             power = (power / 160.0f) * 100.0f;      //  change to a percentage
186             return (int)power;
187         }
188     }
189     else
190         return 0;
191 }
192 
193 //  C Functions
194 //
195 //  Note that the returned value from all exported Lua functions is how many values that function should return in Lua.
196 //  For example, if you return 0 from that function, you are telling Lua that peakPowerForPlayer (for example) returns 0 values.
197 //  If you return 2, you are telling Lua to expect 2 values on the stack when the function returns.
198 //
199 //  To actually return values, you need to push them onto the Lua stack and then return the number of values you pushed on.
200 
201 static int playMusic(struct lua_State *state)
202 {
203     [audioAddOnInstance startPlayer];
204     return 0;
205 }
206 
207 static int stopMusic(struct lua_State *state)
208 {
209     [audioAddOnInstance stopPlayer];
210     return 0;
211 }
212 
213 static int getVolume(struct lua_State *state)
214 {
215     //  Push the integer volume onto the Lua stack
216     
217     lua_pushinteger(state, [audioAddOnInstance getPlayerVolume]);
218     
219     //  Our function returns 1 value = volume
220     
221     return 1;
222 }
223 
224 static int setVolume(struct lua_State *state)
225 {
226     [audioAddOnInstance setPlayerVolume: lua_tonumber(state, 1)];
227     return 0;
228 }
229 
230 static int peakPowerForChannel(struct lua_State *state)
231 {
232     //  Channel numbers are zero-indexed. A monaural signal,
233     //  or the left channel of a stereo signal, has channel number 0.
234     
235     NSUInteger channel = lua_tonumber(state, 1);
236     
237     //  Push the integer power onto the Lua stack
238     
239     lua_pushinteger(state, [audioAddOnInstance getPeakPower: channel]);
240     
241     //  Our function returns 1 value = peak power
242     
243     return 1; 
244 }
245 
246 static int averagePowerForChannel(struct lua_State *state)
247 {
248     //  Channel numbers are zero-indexed. A monaural signal,
249     //  or the left channel of a stereo signal, has channel number 0.
250     
251     NSUInteger channel = lua_tonumber(state, 1);
252     
253     //  Push the integer power onto the Lua stack
254     
255     lua_pushinteger(state, [audioAddOnInstance getAveragePower: channel]);
256     
257     //  Our function returns 1 value = peak power
258     
259     return 1;
260 }
261 
262 #pragma mark - AVAudioPlayer Delegate
263 
264 //  These Audio Player call back methods are not used in this tutorial but provided here
265 //  for information. There are a number of other delegate methods available. Check the
266 //  documentation.
267 
268 - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
269 {
270     
271 }
272 
273 - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
274 {
275     NSLog(@"Error decoding audio file: %@", [error localizedDescription]);
276 }
277 
278 -(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
279 {
280     
281 }
282 
283 -(void)audioPlayerEndInterruption:(AVAudioPlayer *)player
284 {
285     
286 }
287 
288 @end

1   //
2   //  GameCenterAddOn.h
3   //  AudioDemo
4   //
5   //  Created by David Such on 25/04/13.
6   //  Copyright (c) 2013 Reefwing Software. All rights reserved.
7   //
8   //  Version:    1.0 - Original (25/04/13)
9   
10  #import "CodeaAddon.h"
11  #import <Foundation/Foundation.h>
12  #import <GameKit/GameKit.h>
13  
14  //  Create a variable which points to the instance of this class so that we can access self
15  //  from within the Lua c functions.
16  
17  id gameCenterAddOnInstance;
18  
19  //  This class conforms to the CodeaAddon, GKLeaderboardViewControllerDelegate, and GKAchievementViewControllerDelegate Protocols
20  //  We don't use GKGameCenterViewController since this is only available for iOS 6, and we want to provide this functionality for
21  //  1st generation iPads which run iOS 5.
22  
23  @interface GameCenterAddOn : NSObject<CodeaAddon, GKLeaderboardViewControllerDelegate, GKAchievementViewControllerDelegate>
24  {
25      bool hasGameCenter;
26  }
27  
28  @property (weak, nonatomic) CodeaViewController *codeaViewController;
29  
30  //  Forward declare our Lua Audio functions. These are static to confine their scope
31  //  to this file. By default c functions are global.
32  
33  static int gameCenterStart(struct lua_State *state);
34  static int showLeaderBoardWithIdentifier(struct lua_State *state);
35  static int showAchievementsView(struct lua_State *state);
36  static int playerIsAuthenticated(struct lua_State *state);
37  
38  @end

1   //
2   //  GameCenterAddOn.m
3   //  AudioDemo
4   //
5   //  Created by David Such on 25/04/13.
6   //  Copyright (c) 2013 MyCompany. All rights reserved.
7   //
8   
9   #import "lua.h"
10  #import "GameCenterAddOn.h"
11  
12  @implementation GameCenterAddOn
13  
14  #pragma mark - Initialisation
15  
16  - (id)init
17  {
18      self = [super init];
19      if (self)
20      {
21          //  gameCenterAddOnInstance allows us to access self from within the c functions.
22          
23          gameCenterAddOnInstance = self;
24          
25          // Initialise our Instance Variables
26          
27          hasGameCenter = false;
28      }
29      return self;
30  }
31  
32  #pragma mark - CodeaAddon Delegate
33  
34  //  Classes which comply with the <CodeaAddon> Protocol must implement this method
35  
36  - (void)codea:(CodeaViewController*)controller didCreateLuaState:(struct lua_State*)L
37  {
38      NSLog(@"gameCenterAddOn Registering Functions");
39      
40      //  Register the iAd functions, defined below
41      
42      lua_register(L, "gameCenterStart", gameCenterStart);
43      lua_register(L, "showLeaderBoardWithIdentifier", showLeaderBoardWithIdentifier);
44      lua_register(L, "showAchievementsView", showAchievementsView);
45      lua_register(L, "playerIsAuthenticated", playerIsAuthenticated);
46      
47      //  Hook up with the CodeaViewController - don't try to add subviews in this method.
48      
49      self.codeaViewController = controller;
50  }
51  
52  #pragma mark - Game Center Add On Instance Methods
53  
54  - (BOOL)isGameCenterAvailable
55  {
56      // Check for presence of GKLocalPlayer API.
57      
58      Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
59      
60      // The device must be running running iOS 4.1 or later.
61      
62      NSString *reqSysVer = @"4.1";
63      NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
64      BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
65      
66      if (gcClass && osVersionSupported)
67          NSLog(@"Game Center is Available");
68      else
69          NSLog(@"Game Center is not Available");
70      
71      return (gcClass && osVersionSupported);
72  }
73  
74  - (void)registerForAuthenticationNotification
75  {
76      NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
77      [nc addObserver: self selector: @selector(authenticationChanged) name: GKPlayerAuthenticationDidChangeNotificationName object: nil];
78  }
79  
80  //  Your game must authenticate a local player before you can use any Game Center classes.
81  //  If there is no authenticated player, your game receives a GKErrorNotAuthenticated error.
82  
83  - (bool)isPlayerAuthenticated
84  {
85      return hasGameCenter;
86  }
87  
88  - (void)authenticateLocalPlayer
89  {
90      
91      if(![self isGameCenterAvailable])
92      {
93          hasGameCenter = false;
94          return;
95      }
96      
97      [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
98       {
99           if (error == nil)
100          {
101              [self registerForAuthenticationNotification];
102              hasGameCenter = true;
103              NSLog(@"Game Center - local player authenticated.");
104          }
105          else
106          {
107              hasGameCenter = false;
108              NSLog(@"Game Center - failed to authenticate, error: %@", [error localizedDescription]);
109          }
110      }];
111 }
112 
113 - (void)authenticationChanged
114 {
115     if([self isGameCenterAvailable])
116     {
117         return;
118     }
119     
120     if ([GKLocalPlayer localPlayer].isAuthenticated)
121     {
122         hasGameCenter = true;
123     }
124     else
125     {
126         hasGameCenter = false;
127     }
128 }
129 
130 #pragma mark - Game Center C Functions
131 
132 //  C Functions
133 //
134 //  Note that the returned value from all exported Lua functions is how many values that function should return in Lua.
135 //  For example, if you return 0 from that function, you are telling Lua that function returns 0 values.
136 //  If you return 2, you are telling Lua to expect 2 values on the stack when the function returns.
137 //
138 //  To actually return values, you need to push them onto the Lua stack and then return the number of values you pushed on.
139 
140 static int gameCenterStart(struct lua_State *state)
141 {
142     [gameCenterAddOnInstance authenticateLocalPlayer];
143     
144     return 0;
145 }
146 
147 static int showLeaderBoardWithIdentifier(struct lua_State *state)
148 {
149     [gameCenterAddOnInstance showLeaderboard: lua_tonumber(state, 1)];
150     
151     return 0;
152 }
153 
154 static int showAchievementsView(struct lua_State *state)
155 {
156     [gameCenterAddOnInstance showAchievements];
157     
158     return 0;
159 }
160 
161 static int playerIsAuthenticated(struct lua_State *state)
162 {
163     lua_pushboolean(state, [gameCenterAddOnInstance isPlayerAuthenticated]);
164     
165     return 1;
166 }
167 
168 #pragma mark - GKLeaderboardViewControllerDelegate Methods
169 
170 - (void)showLeaderboard: (int)ident
171 {
172     NSString *identifier;
173     
174     // INSERT YOUR ACHIEVEMENT IDENTIFIERS BELOW - These are set up in iTunes Connect
175     
176     switch (ident)
177     {
178         case 1:
179             identifier = @"Easy Difficulty";
180             break;
181         case 2:
182             identifier = @"Medium Difficulty";
183             break;
184         case 3:
185             identifier = @"Hard Difficulty";
186             break;
187         default:
188             NSLog(@"Warning Unknown Leader Board");
189             break;
190     }
191     
192     GKLeaderboardViewController *leaderBoardCont = [[GKLeaderboardViewController alloc] init];
193     
194     if (leaderBoardCont)
195     {
196         leaderBoardCont.category=identifier;
197         leaderBoardCont.timeScope=GKLeaderboardTimeScopeToday;
198         leaderBoardCont.leaderboardDelegate=self;
199         self.codeaViewController.paused = YES;
200         [self.codeaViewController presentModalViewController: leaderBoardCont animated: YES];
201     }
202 }
203 
204 - (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
205 {
206     //  Dismiss the Game Center Leader Board view
207     
208     [self.codeaViewController dismissViewControllerAnimated: YES completion:^
209      {
210          self.codeaViewController.paused = NO;          // Unpause Codea
211      }];
212 }
213 
214 #pragma mark - GKAchievementViewControllerDelegate Methods
215 
216 - (void)showAchievements
217 {
218     GKAchievementViewController *achievements = [[GKAchievementViewController alloc] init];
219     
220     if (achievements != nil)
221     {
222         achievements.achievementDelegate = self;
223         self.codeaViewController.paused = YES;
224         [self.codeaViewController presentViewController: achievements animated: YES completion: nil];
225     }
226 }
227 
228 - (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
229 {
230     //  Dismiss the Game Center Achievement view
231     
232     [self.codeaViewController dismissViewControllerAnimated: YES completion:^
233      {
234          self.codeaViewController.paused = NO;          // Unpause Codea
235      }];
236 }
237 
238 @end

1   -- AudioDemo
2   -- Main.lua
3   
4   -- Uses Cider Controls v1.6 from @Mark and @aciolino
5   -- make sure you add this as a Dependency
6   
7   
8   function setup()
9       
10      displayMode(FULLSCREEN)
11      setInstructionLimit(0)
12      ctlFrame = Control("Audio Player", 20, HEIGHT - 600, 450, HEIGHT - 20)
13      ctlFrame.background = color(181, 141, 203, 255)
14      ctlFrame.textAlign = CENTER
15      ctlFrame.fontSize = 24
16      
17      -- Initialise the Cider Controls
18      
19      playBtn = TextButton("Play", 70, 480, 225, 520)
20      stopBtn = TextButton("Stop", 245, 480, 400, 520)
21      sldVolume = Slider("Volume Control", 70, HEIGHT - 450, 400, HEIGHT - 420, 0, 100, 50)
22      
23      -- Initialise the Cider Volume Indicators
24      
25      dial = Dial("Left", 70, 780, 220, 930, 0, 100, 0)
26      doughnut = Doughnut("Right", 250, 780, 400, 930, 0, 100, sldVolume.val)
27      doughnut.intervals = 25
28      doughnut.warm = 9
29      doughnut.hot = 13
30  
31      -- Show Banner Ad using iAdsAddOn
32  
33      showAdFromTop()
34      
35      -- Start Game Center using gameCenterAddOn
36      
37      gameCenterStart()
38      
39  end
40  
41  function draw()
42      
43      -- This sets a dark background color 
44      
45      background(178, 173, 173, 255)
46  
47      -- Draw the Cider Controls
48      
49      ctlFrame:draw()
50      playBtn:draw()
51      stopBtn:draw()
52      sldVolume:draw()
53      dial:draw()
54      doughnut:draw()
55  
56      -- Update the dB Meter Dials
57      --
58      -- The iPad should have 2 channels, left = 0 and right = 1
59  
60      dial.val = averagePowerForChannel(0) or 0
61      doughnut.val = averagePowerForChannel(1) or 0
62  
63  end
64  
65  function touched(touch)
66      
67      if sldVolume: touched(touch) then
68          -- call AudioAddOn function
69          setVolume(sldVolume.val)
70      end
71      
72      if playBtn:touched(touch) then
73          -- call AudioAddOn and iAdsAddOn function
74          playMusic()
75          hideAd()
76          if playerIsAuthenticated() then
77              showAchievementsView()
78          else
79              print("Player not authenticated")
80          end
81      end
82      
83      if stopBtn:touched(touch) then
84          -- call AudioAddOn and iAdsAddOn function
85          stopMusic()
86          showAdFromBottom()
87          if playerIsAuthenticated() then
88              showLeaderBoardWithIdentifier(1)
89          else
90              print("Player not authenticated")
91          end
92      end
93      
94  end

1   //
2   //  IAdsAddOn.m
3   //  AudioDemo
4   //
5   //  Created by David Such on 19/04/13.
6   //  Copyright (c) 2013 Reefwing Software. All rights reserved.
7   //
8   //  Version:    1.0 - Original (19/04/13)
9   //              1.1 - Minor refactoring (25/4/13)
10  
11  #import "lua.h"
12  #import "IAdsAddOn.h"
13  
14  @implementation IAdsAddOn
15  
16  #pragma mark - Initialisation
17  
18  - (id)init
19  {
20      self = [super init];
21      if (self)
22      {
23          //  audioAddOnInstance allows us to access self from within the c functions.
24          
25          iAdsAddOnInstance = self;
26          
27          // Initialise our Instance Variables
28          
29          _isBannerVisible = NO;
30          _showBannerFromTop = YES;
31          
32          //  Initialise our iAd Banner View
33          
34          CGRect frame = CGRectZero;
35          frame.size = [ADBannerView sizeFromBannerContentSizeIdentifier: ADBannerContentSizeIdentifierPortrait];
36          
37          _bannerView = [[ADBannerView alloc] initWithFrame: frame];
38          _bannerView.requiredContentSizeIdentifiers = [NSSet setWithObject: ADBannerContentSizeIdentifierPortrait];
39          _bannerView.delegate = self;
40      }
41      return self;
42  }
43  
44  #pragma mark - CodeaAddon Delegate
45  
46  //  Classes which comply with the <CodeaAddon> Protocol must implement this method
47  
48  - (void) codea:(CodeaViewController*)controller didCreateLuaState:(struct lua_State*)L
49  {
50      NSLog(@"iAdAddOn Registering Functions");
51      
52      //  Register the iAd functions, defined below
53      
54      lua_register(L, "showAdFromTop", showAdFromTop);
55      lua_register(L, "showAdFromBottom", showAdFromBottom);
56      lua_register(L, "hideAd", hideAd);
57      
58      //  Hook up with the CodeaViewController - don't try to add subviews in this method.
59      
60      self.codeaViewController = controller;
61  }
62  
63  #pragma mark - iAds Add On Functions and associated Methods
64  
65  //  Objective C Methods
66  
67  - (void)showBannerViewAnimated:(BOOL)animated
68  {
69      if ([self.bannerView isBannerLoaded])
70      {
71          //  We only display the banner View if it has ads loaded and isn't already visible.
72          //  Set the banner view starting position as off screen.
73          
74          CGRect frame = _bannerView.frame;
75          
76          if (_showBannerFromTop)
77              frame.origin.y = 0.0f - _bannerView.frame.size.height;
78          else
79              frame.origin.y = CGRectGetMaxY(self.codeaViewController.view.bounds);
80          
81          _bannerView.frame = frame;
82          
83          // Set banner View final position to animate to.
84          
85          if (_showBannerFromTop)
86              frame.origin.y = 0;
87          else
88              frame.origin.y -= frame.size.height;
89      
90          if (animated)
91              [UIView animateWithDuration: 0.5 animations: ^{self.bannerView.frame = frame;}];
92          else
93              self.bannerView.frame = frame;
94          
95          _isBannerVisible = YES;
96      }
97      else
98          NSLog(@"showBannerViewAnimated: Unable to display banner, no Ads loaded.");
99  }
100 
101 - (void)hideBannerViewAnimated:(BOOL)animated
102 {
103     if (_isBannerVisible)
104     {
105         CGRect frame = self.bannerView.frame;
106         
107         if (_showBannerFromTop)
108             frame.origin.y -= frame.size.height;
109         else
110             frame.origin.y = CGRectGetMaxY(self.codeaViewController.view.bounds);
111         
112         if (animated)
113             [UIView animateWithDuration: 0.5 animations: ^{self.bannerView.frame = frame;}];
114         else
115             self.bannerView.frame = frame;
116         
117         _isBannerVisible = NO;
118     }
119 }
120 
121 //  C Functions
122 //
123 //  Note that the returned value from all exported Lua functions is how many values that function should return in Lua.
124 //  For example, if you return 0 from that function, you are telling Lua that function returns 0 values.
125 //  If you return 2, you are telling Lua to expect 2 values on the stack when the function returns.
126 //
127 //  To actually return values, you need to push them onto the Lua stack and then return the number of values you pushed on.
128 
129 static int showAdFromTop(struct lua_State *state)
130 {
131     [iAdsAddOnInstance setShowBannerFromTop: YES];
132     [iAdsAddOnInstance showBannerViewAnimated: YES];
133     
134     return 0;
135 }
136 
137 static int showAdFromBottom(struct lua_State *state)
138 {
139     [iAdsAddOnInstance setShowBannerFromTop: NO];
140     [iAdsAddOnInstance showBannerViewAnimated: YES];
141     
142     return 0;
143 }
144 
145 static int hideAd(struct lua_State *state)
146 {
147     [iAdsAddOnInstance hideBannerViewAnimated: YES];
148     
149     return 0;
150 }
151 
152 #pragma mark - iAd Banner View Delegate
153 
154 //  Your application implements this method to be notified when a new advertisement is ready for display.
155 
156 - (void)bannerViewDidLoadAd:(ADBannerView *)banner
157 {
158     NSLog(@"Banner View loaded Ads for display.");
159     NSLog(@"Active View Controller: %@", self.codeaViewController.class);
160     
161     //  Add our banner view to the CodeaViewController view, if we haven't already.
162     
163     if (![self.codeaViewController.view.subviews containsObject: _bannerView])
164         [self.codeaViewController.view addSubview: _bannerView];
165     
166     [self showBannerViewAnimated: YES];
167 }
168 
169 //  This method is triggered when an advertisement could not be loaded from the iAds system
170 //  (perhaps due to a network connectivity issue).
171 
172 - (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
173 {
174     NSLog(@"bannerview failed to receive iAd error: %@", [error localizedDescription]);
175     
176     [self hideBannerViewAnimated: YES];
177 }
178  
179 //  This method is triggered when the banner confirms that an advertisement is available but before the ad is 
180 //  downloaded to the device and is ready for presentation to the user.
181  
182 - (void)bannerViewWillLoadAd:(ADBannerView *)banner
183 {
184  
185 }
186  
187 //  This method is triggered when the user touches the iAds banner in your application. If the willLeave argument 
188 //  passed through to the method is YES then your application will be placed into the background while the user is 
189 //  taken elsewhere to interact with or view the ad. If the argument is NO then the ad will be superimposed over your 
190 //  running application.
191  
192 - (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
193 {
194     self.codeaViewController.paused = YES;
195     NSLog(@"Ad being displayed - Codea paused.");
196     
197     return YES;
198 }
199  
200 //  This method is called when the ad view removes the ad content currently obscuring the application interface. 
201 //  If the application was paused during the ad view session this method can be used to resume activity.
202 
203 - (void)bannerViewActionDidFinish:(ADBannerView *)banner
204 {
205     self.codeaViewController.paused = NO;
206     NSLog(@"Ad dismissed - Codea running.");
207 }
208 
209 @end

1   //
2   //  IAdsAddOn.h
3   //  AudioDemo
4   //
5   //  Created by David Such on 19/04/13.
6   //  Copyright (c) 2013 Reefwing Software. All rights reserved.
7   //
8   //  Version:    1.0 - Original (19/04/13)
9   //              1.1 - Minor refactoring (25/4/13)
10  
11  #import "CodeaAddon.h"
12  #import <iAd/iAd.h>
13  #import <Foundation/Foundation.h>
14  
15  // Device Detection Macros - can be used to position the banner advertisement based on device.
16  // Not used in this tutorial.
17  
18  //#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
19  //#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
20  //#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
21  //#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0f)
22  
23  //  Create a variable which points to the instance of this class so that we can access self
24  //  from within the Lua c functions.
25  
26  id iAdsAddOnInstance;
27  
28  //  This class conforms to the CodeaAddon & ADBannerViewDelegate Protocols
29  
30  @interface IAdsAddOn : NSObject<CodeaAddon, ADBannerViewDelegate>
31  
32  @property BOOL isBannerVisible;
33  @property BOOL showBannerFromTop;
34  @property (strong, nonatomic) ADBannerView *bannerView;
35  @property (weak, nonatomic) CodeaViewController *codeaViewController;
36  
37  //  Forward declare our Lua iAd functions. These are static to confine their scope
38  //  to this file. By default c functions are global.
39  
40  static int showAdFromTop(struct lua_State *state);
41  static int showAdFromBottom(struct lua_State *state);
42  static int hideAd(struct lua_State *state);
43  
44  @end

Reference PAGE TOP

http://codeatuts.blogspot.in/2013/04/tutorial-30-codea-v152-objective-c-add.html

0 Comments Leave a comment

Please login in order to leave a comment.

Newest first
!

Sign-in to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.