iPhone Game Development - Chris Craft [37]
- (void)initLevelNumberButtons {
int btnTopOffset = 65;
int btnHeight = 37;
int btnWidth = 137;
int btnTopMargin = 9;
int btnEvenLeft = 20;
int btnOddLeft = 164;
for (int i=0; i<8; i++) {
int btnRow = i/2;
int btnLeft = i%2 == 0 ? btnEvenLeft : btnOddLeft;
int btnTop = ((btnHeight + btnTopMargin) * btnRow) + btnTopOffset;
CGRect buttonFrame = CGRectMake(btnLeft, btnTop, btnWidth, btnHeight);
levelNumberButton[i] = [UIButton buttonWithType: UIButtonTypeRoundedRect];
levelNumberButton[i].frame = buttonFrame;
levelNumberButton[i].hidden = true;
levelNumberButton[i].tag = i+1;
[levelNumberButton [i] addTarget:self action:
@selector(onLevelNumberButtonClick:)
forControlEvents:UIControlEventTouchUpInside];
[levelNumberButton [i] setTitle:buttonNames[i]
forState:UIControlStateNormal];
[self.view addSubview: levelNumberButton [i]];
}
}
Take notice of the following line from above:
[levelNumberButton [i] addTarget:self action:
@selector(onLevelNumberButtonClick:)
forControlEvents:UIControlEventTouchUpInside];
This line attaches the selector onLevelNumberClick to the button's TouchUpInside event. All eight buttons are assigned to the same method. However, we are using the tag property of the button to distinguish which button was clicked. This is what the onLevelNumberButtonClick method looks like:
- (void)onLevelNumberButtonClick:(id)sender {
UIButton *btn = (UIButton*)sender;
int levelIndex = (int)btn.tag;
[self selectLevel:levelIndex];
}
Since we have all the buttons on the same view at the same time, it is simple to just hide and show the appropriate buttons by changing the button's “hidden” property. This gives the player the feeling that he is paging through options while keeping all of the view logic in one class.
Once the player has made a selection, we need to report his choice back to the main Game View. This is where the protocol that you saw at the top of MenuViewController.h comes into play:
@protocol MenuViewDelegate @optional -(void)loadLevel:(int)levelIndex; @end This protocol defines an interface that the implementing classes can define to receive messages from. In this case, the MainViewController implements the method loadLevel as defined by the protocol. The selectLevel method in MenuViewController calls the loadLevel of the delegate, which sends the message to the implementing class instance referenced by the delegate: - (void)selectLevel:(int)levelIndex { [delegate loadLevel:levelIndex-1]; } Polishing the Menu View We recommend that you completely finish the game logic before polishing up the Game View. However, since we are guiding you through a complete example, let's take a break from discussing implementation and look at how our screens are going to look after we polish them up. In this example we are going to add a better background image and a little animation to spice it up a bit. You will be amazed how a few simple changes can add interest. Go back to the AmuckSlider source link (http://appsamuckcom/amuckslider) and this time download the “After Polish” version of the source code. To polish up the menus, we will add a background image to the Menu View. You can do this in Interface Builder without touching this code. For each of the buttons we will add a background image to add a little spice there, too. This is a little more complicated because you need to tell the button how to treat the edges of the background image. You will see that a background image has been assigned to each button similar to the line below: UIImage *buttonBackground = [[UIImage imageNamed:@”menuButtonBackground.png”] stretchableImageWithLeftCapWidth:12.0 topCapHeight:12.0 ]; [levelButton setBackgroundImage:buttonBackground forState:UIControlStateNormal]; The trick to this is creating the UIImage with the imageNamed:stretchableImageWithLeftCapWidth:topCapHeight: signature. Figures 3.14, 3.15, and 3.16 show what the finished product looks like. FIGURE 3.14 Polished first page of the menu