Showing posts with label Interface Builder. Show all posts
Showing posts with label Interface Builder. Show all posts

7/31/2009

iPhone Game Tutorial (Part 2)

Lets add more to this App.

Our Goals today:
We're going to make a few changes to our previous project. What we're going to be able to do with this app at the end of the tutorial will be:
  • Move in 3 directions (Up, Down, Right)
  • Fire (yes!)
  • Move to different stages
So lets start by modifieing our .h:
@interface AnimateViewController : UIViewController {
IBOutlet UIImageView *background;
IBOutlet UIButton *buttonUp;
IBOutlet UIButton *buttonDown;
IBOutlet UIButton *buttonRight;
IBOutlet UIButton *buttonFire;

UIImageView *player;
UIImageView *flash;
NSArray *walkImages;
NSArray *fireImages;
NSTimer *walkingTimer;
NSTimer *fireTimer;

NSUInteger lvl;
NSUInteger topLimit;
NSUInteger bottomLimit;
}

-(void)disableMovementButtons;
-(void)enableMovementButtons;

-(IBAction)walk;
-(IBAction)stopWalking;
-(IBAction)walkUp;
-(IBAction)stopWalkingUp;
-(IBAction)walkDown;
-(IBAction)stopWalkingDown;
-(IBAction)triggerPulled;
-(IBAction)triggerReleased;

-(void)startMovingForward;
-(void)moveForward;
-(void)startMovingUp;
-(void)moveUp;
-(void)startMovingDown;
-(void)moveDown;

-(void)startFireing;
-(void)checkHits;

-(void)checklvl;

@end
As you can see we have some new methods to fill with code, but I've also modified some of the existing ones, so watch for changes.
We create IBOutlets as we will be referring to the background to switch the image in it while we move on in the game, and refer to the buttons to change some properties of them.
We also create a new UIImageView called flash witch will help us animate the gun fire. We then also create an NSTimer to check for hits on the enemies (in future tutorials).
The NSUIntegers I created are to keep track of some numbers, like the level or stage we currently are at or the maximum vertical range we can let our little soldier move on the iPhones screen.
As for the methods, I think the names speak for them self, if not, you'll see when we right the actual code.

Changing the xib:
Open the xib in Interface Builder and make the changes so it looks like on the screenshot below.


You will also need:
iPhone Game Tutorial (Part 2)


Connect all the IBOutlets to its appropriate Element (buttons and background) and set the following methods:

buttonRight Touch Down => Walk
buttonRight Touch Up Inside => stopWalking

buttonUp Touch Down => walkUp
buttonUp Touch Up Inside => stopWalkingUp

buttonDown Touch Down => walkDown
buttonDown Touch Up Inside => stopWalkingDown

buttonFire Touch Down => triggerPulled
buttonFire Touch Up Inside => triggerReleased

we can also remove the image from our background as we'll set it later in the code.
And that's it for the xib. Save and close it.

Moving on to the .m:

I've done some changes to the viewDidLoad method
- (void)viewDidLoad {
[super viewDidLoad];
lvl = 1;
topLimit = 140;
bottomLimit = 260;

walkImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:@"w1.png"], [UIImage imageNamed:@"w2.png"],
[UIImage imageNamed:@"w3.png"], [UIImage imageNamed:@"w4.png"],
[UIImage imageNamed:@"w5.png"], [UIImage imageNamed:@"w6.png"], nil];

player = [[UIImageView alloc] initWithFrame:CGRectMake(100, 220, 30, 30)];
player.image = [UIImage imageNamed:@"stand.png"];
player.animationDuration = 1.5;
player.contentMode = UIViewContentModeBottomLeft;

fireImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:@"flash1.png"],
[UIImage imageNamed:@"flash2.png"], nil];

flash = [[UIImageView alloc] init];
flash.animationDuration = 0.18;
flash.contentMode = UIViewContentModeBottomLeft;


[self.view addSubview:player];
[self.view addSubview:flash];
[self checklvl];
}
As you can see, we've now filled up another array with 2 images and given the new UIImageView some instructions. BUT we haven't actually placed it on the iPhone screen yet (no frame yet).
#pragma mark - #pragma mark My Methods

-(void)disableMovementButtons {
buttonUp.enabled = NO;
buttonDown.enabled = NO;
buttonRight.enabled = NO;
}

-(void)enableMovementButtons {
buttonUp.enabled = YES;
buttonDown.enabled = YES;
buttonRight.enabled = YES;
}
When the player is sawing away bullets on hordes of enemies (which don't exist yet) we don't want him to be able to run around like Rambo... and screw around with our o so simple animation. That's why we'll use these two methods to simply dis- enable the buttons.
#pragma mark - #pragma mark IB Actions

-(IBAction)walk {
if(player.frame.origin.y > topLimit &&
player.frame.origin.y < bottomLimit) {
[self startMovingForward];
player.animationImages = walkImages;
[player startAnimating];

buttonUp.enabled = NO;
buttonDown.enabled = NO;
}
}

-(IBAction)stopWalking {
[player stopAnimating];
[walkingTimer invalidate];
buttonUp.enabled = YES;
buttonDown.enabled = YES;
}

-(IBAction)walkUp {
[self startMovingUp];
player.animationImages = walkImages;
[player startAnimating];
buttonRight.enabled = NO;
buttonDown.enabled = NO;
}

-(IBAction)stopWalkingUp {
[player stopAnimating];
[walkingTimer invalidate];
buttonRight.enabled = YES;
buttonDown.enabled = YES;
}

-(IBAction)walkDown {
[self startMovingDown];
player.animationImages = walkImages;
[player startAnimating];
buttonUp.enabled = NO;
buttonRight.enabled = NO;
}

-(IBAction)stopWalkingDown {
[player stopAnimating];
[walkingTimer invalidate];
buttonUp.enabled = YES;
buttonRight.enabled = YES;
}

-(IBAction)triggerPulled {
[self startFireing];
flash.animationImages = fireImages;
[flash startAnimating];
[self disableMovementButtons];
}

-(IBAction)triggerReleased {
[fireTimer invalidate];
[flash stopAnimating];
[self enableMovementButtons];
}
All fairly simple and similar to first part of the tutorial. However, we added a little IF to move to the next stage and reset our position when we reach the end of the iPhone screen.
#pragma mark Weapon use

-(void)startFireing {
flash.frame = CGRectMake((player.frame.origin.x)+30, (player.frame.origin.y)+10, 15, 10);
fireTimer = [NSTimer scheduledTimerWithTimeInterval:0.18
target:self
selector:@selector(checkHits)
userInfo:nil
repeats:YES];
}

-(void)checkHits {

}
Here comes the part you've been waiting for! We orientate on the origin of the player frame and displace the flash so that it aligns with the gun barrel. We will not check if we hit anything yet as there isn't anything we could shoot at but we'll get to that in the next tutorial.
#pragma mark -
#pragma mark world events

-(void)checklvl {
switch (lvl) {
case 1:
background.image = [UIImage imageNamed:@"bg1.png"];
break;
case 2:
background.image = [UIImage imageNamed:@"bg2.png"];
topLimit = 170;
break;
case 3:
background.image = [UIImage imageNamed:@"bg3.png"];
break;
case 4:
background.image = [UIImage imageNamed:@"bg4.png"];
break;
case 5:
background.image = [UIImage imageNamed:@"bg5.png"];
break;
case 6:
background.image = [UIImage imageNamed:@"bg6.png"];
break;
case 7:
background.image = [UIImage imageNamed:@"bg7.png"];
break;
case 8:
background.image = [UIImage imageNamed:@"bg8.png"];
topLimit = 140;
break;
}
}
Easy enough. Later on we can also change parameters like number of enemies or type of enemies etc etc depending on the stage. Cool, huh?
You'll find the backgrounds here:

Alright, I hope I didn't leave anything out. That should do it for today. Try running around and through all stages and don't forget to shoot here and there to make you look more dangerous.

PS: I think the editor for the post here might have swollowed some code or something. I did fix one part but incase you find something that looks weird, write a coment
Reblog this post [with Zemanta]

6/18/2009

[iPhone] Removing the Keyboard when done.

iphone keyboardImage by _snapp via Flickr

Let me continue with the easy stuff to fill up the Blog a little more.
Today I'll go through how to make the keyboard move out of the way once you are done editing the field.

There are two basic ways of doing it. One, is pressing the DONE key on the keyboard. The other way is tapping with your finger anywhere else on the screen.

Lets clarify:
UITextField *myTextField;
UITextField *myOtherTextField;

-(IBAction)backgroundClick:(id)sender;
-(IBAction)doneEditing:(id)sender;

Using the DONE key:

To make it return with the Done key start by adding the following code:
-(IBAction)doneEditing:(id)sender
{
[sender resignFirstResponder];
}

Any controller can be called to resign the First Responder status. With this simple function done lets set WHEN it will be called.
Open Interface Builder and single click on one of the Text Fields and click ⌘2 to open up the connections inspector.

Connect the Did End on Exit event with the doneEditing function by dragging the little circle symbol next to the event name to the File's Owner.

Repeat this for the other text field to show that you don't need a separate function for every field and try it out.

By tapping it away:

Some keyboard layouts don't have a DONE key. Or even if they have, a lot of people prefere to just tapp it away instead of tapping the small button in the corner. For these situations there is a quick and easy way of solving the problem.

Add the following code:
-(IBAction)backgroundClick:(id)sender
{
[myTextField resignFirstResponder];
[myOtherTextField resignFirstResponder];
}

Can you already guess? Lets see.

Save it again and go back to to Interface Builder.
Drag a Round Rect Button over your view and resize it so that it covers ALL of your view.
Now Select Layout > Send to Back and don't deselect the button anymore. The Button is now behind everything else you are showing.

Press
⌘1 and change the type to Custom.
You now have an invisible button in you back layer. Only thing missing now is to connect the Did touch up inside event to the action backgroundClick and you're done.

Notice that you can ask all of your fields to resign First Responder even if they don't currently have it and it won't cause any problem.
Reblog this post [with Zemanta]