Launch The Settings App Directly From Your App
Open a special url to go directly to your app's settings.
NSURL *url = [NSURL URLWithString:@"prefs:root=YOUR_CASE_SENSITIVE_BUNDLE_DISPLAY_NAME"]; [[UIApplication sharedApplication] openURL:url];
Open a special url to go directly to your app's settings.
NSURL *url = [NSURL URLWithString:@"prefs:root=YOUR_CASE_SENSITIVE_BUNDLE_DISPLAY_NAME"]; [[UIApplication sharedApplication] openURL:url];
Is your image disrespecting the bounds of its UIImageView container? Set the clipsToBounds property:
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)] autorelease]; imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.clipsToBounds = YES;
Comments [0]
If you want to receive touches while running an animation, you must set UIViewAnimationOptionAllowUserInteraction in your animation options:
[UIView animateWithDuration:10.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
myView.alpha = 0.0f;
}
completion:^(BOOL finished) {
}];
Comments [0]
By default, the sizes for UIActivityIndicatorView are:
You can adjust the size by changing the frame property:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]; spinner.frame = CGRectMake(originx, originy, width, height);
When using a custom size greater than 21 pixels, it is best to use the UIActivityIndicatorViewStyleWhiteLarge for the image to look smooth.
Comments [0]
It's possible to access a cell's parent table without having to set up a delegate:
self.superview
Done. It's that easy.
Comments [0]
How to have your view respond differently to a single tap or double tap:
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
doubleTap.numberOfTapsRequired = 2;
[mainView addGestureRecognizer:doubleTap];
[doubleTap release];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
singleTap.numberOfTapsRequired = 1;
[mainView addGestureRecognizer:singleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
[singleTap release];
The key line of code that prevents the single tap from also firing on a double tap:
[singleTap requireGestureRecognizerToFail:doubleTap];
Comments [0]
Xcode 4 has a new feature called Live Issue Debugging that builds in the background while you write code and displays errors.
It is a bit overzealous and will harass you with code issues and warnings about brackets and such before you've even finished a method! While this could be useful if you are learning programming, if you are an experienced programmer it can hamper your productivity while you are in the draft phase of your project.
Much like drafting a paper, you shouldn't concern yourself with spelling. Your goal should be to get all of your ideas on paper as quickly as possible.
The same applies to writing code. You shouldn't lose your train of thought to be bothered about a missing semicolon. You should be focused purely on getting your ideas into code form. You can come back in the build phase and correct any minor issues.
I recommend disabling Live Issue Debugging in the General section of Xcode's preferences.
Comments [0]
The touch nsset contains the previous location of a touch that has been moved. Use previousLocationInView to get it. If you need locations beyond the previous frame, you'll have to write your own method to store them.
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInView:[touch view]];
CGPoint previousLocation = [touch previousLocationInView:[touch view]];
}
}Comments [0]
Remember the underwater scene in the Sonic game where the music becomes dramatic as Sonic starts to drown? Sorry to bring up those anxiety memories, but that is a great example of dynamic background music. I'm going to show you how to add seamless mood changing music that follows the action in your game.
WordSurge - An Example Of Rising Intensity
Here's how I did it in my latest game, WordSurge. The music gradually gets more intense as the player's situation becomes more precarious. Check out the video below:
Make Your Own Music In Apple's Garage Band
Before you can do anything, you need some music to work with. Fire up Apple's Garage Band and channel your inner Tiesto.
Create Equal Length Verses
The goal is to create different verses of the same length so that your game's sound engine can seamlessly transition between them. It doesn't matter what the length is, but it must be the same. In WordSurge, I used 16 second verses, 6 verses in total.
Create each verse in order from least intense to most intense. When you're done, you should have something like this, with more and more instruments used in each verse. Save your project.
Disable Normalization
Before you can start saving out your verses, you need to tell Garage Band to not adjust the volume for you. With the default settings, it will adjust the volume of the exported track to be as loud as possible. However, this will change the loudness of the verse relative to the entire song. Not what you want. Disable normalization in the advanced preferences of Garage Band.
Cut The Verses & Export
Highlight everything but your first verse and temporarily delete it. It should look something like this.
In the Share menu, select Export Song to Disk...
The high quality setting is adequate.
Name the file 1.m4a.
Notice that Garage Band exported an audio file slightly longer than you expected. It has included any extra echos and fadeouts and you need those for your background music to sound seamless. It all synchs up because you will be playing these tracks overlapping on each other. More on that later.
Go to undo, or revert back to your save, to get the rest of your song back. Repeat the cut and export process for each verse. You should end up with a folder of music, named 1.m4a, 2.m4a, 3.m4a, etc.
Meanwhile, Back in Xcode
I used cocos2d for this game, which makes scheduling very easy. It also ships with Steve Oldmeadow's excellent CocosDenshion sound library.
Open your game project and drag your files into the Resources folder of your project.
Include this at the top of your code:
#import "SimpleAudioEngine.h"
In The Init Statement
Schedule your background music manager to run every X seconds, where X is the length of your verses.
[self schedule: @selector(backgroundMusicManager) interval:16];
Preload Your Sounds In Memory
[[SimpleAudioEngine sharedEngine] preloadEffect:@"1.m4a"]; [[SimpleAudioEngine sharedEngine] preloadEffect:@"2.m4a"]; [[SimpleAudioEngine sharedEngine] preloadEffect:@"3.m4a"]; [[SimpleAudioEngine sharedEngine] preloadEffect:@"4.m4a"]; [[SimpleAudioEngine sharedEngine] preloadEffect:@"5.m4a"]; [[SimpleAudioEngine sharedEngine] preloadEffect:@"6.m4a"];
Finally, kick start the manager to run the first time. Otherwise, it won't happen until 16 seconds have elapsed.
[self backgroundMusicManager];
Your Music Manager Method
-(void) backgroundMusicManager {
float intensity;
/* Your own code to determine what intensity your music should be at */
if (intensity >= 0 && intensity < 0.1666f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"1.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else if (intensity >= 0.1666f && intensity < 0.3333f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"2.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else if (intensity >= 0.3333f && intensity < 0.5f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"3.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else if (intensity >= 0.5f && intensity < 0.6666f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"4.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else if (intensity >= 0.6666f && intensity < 0.8333f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"5.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else if (intensity >= 0.8333f) {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"6.m4a" pitch:1.0f pan:0.0f gain:0.35f];
} else {
lastBGSoundPlaying = [[SimpleAudioEngine sharedEngine] playEffect:@"1.m4a" pitch:1.0f pan:0.0f gain:0.35f];
}
}Remember how these tracks are slightly longer than 16 seconds because they include echos and fadeouts? That's why I'm using the playEffect method instead of cocosDenshion's background music methods. This way the tracks overlap each other at precisely the right time and you'll get that great seamless effect.
Before you run this code chunk, you need to come up with a method for deciding what intensity your game is currently at. In WordSurge, I used a combination of the player's remaining life and the number of bubbles on the screen. The logical choice is to use the player's life, but your game is unique and you can be creative here.
Additional Tips
Comments [0]
Comments [0]