Document Sample
HKUSpace-iPhone-Dev-Tutorial-3 Powered By Docstoc
					      Tutorial 3: Touches Detection and Remaining Parts

1. Introduction

2. Touches Detection
2.1 Touches Events Tests
2.2 Moving a Man Image within Boundary

3. Remaining Parts
3.1 Collision Detection
3.2 Game Information Update s
3.3 Game End Condition Implementation
3.4 Reset Game States
3.5 Game Cheat

1. Introduction
In Tutorial 2, we have discussed how to manage UI components either one time only or
continuously during runtime. In this tutorial, we will first discuss how to perform a featured input
method in iPhone applications – touches detection. Then, we will further discuss the remaining
parts that are necessary in completing the app.

The whole lab exercise is divided into two main parts:
1.     Touches Detection
           i.   Simple Touches Actions Tests
          ii.   Moving a Man Image Object within Boundary
2.     Remaining Parts
           i.   Collision Detection
          ii.   Game End Conditions
         iii.   Alert Windows
         iv.    Reset the Game

2. Touches Detection

2.1 Simple Touch Actions Tests
If you cannot finish previous tutorial or if you have not attended that, you can download the project
zip file ( from our website to continue working on this

In this part, we first understand how to capture touch inputs in the program. As mentioned in the
lecture, different types of touches have been defined, such as single tap, double tap, multitouch, etc.
A Touch action will be translated to calling the three methods touchesBegan, touchesMoved,
and touchesEnded in a certain sequence. For example, if a user taps the screen once,
touchesBegan will be called first and then touchesEnded. In this part, we will go through
several experiments and understand how different touch actions are translated to a series of
method calls so as to represent touch actions.

To get started, we first put the following codes in VolcanoRockEscapingViewController.m.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     NSLog (@”Touch Began”);
      NSLog (@”Touch Began”);
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
  - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
     NSLog (@”Touch Moved”);
      NSLog (@”Touch Moved”);
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
  - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
     NSLog (@”Touch End”);
      NSLog (@”Touch End”);

The log statements allow us to understand the sequence of the methods to be called when a touch
action is done.

In fact, you may be interested in what are the differences between these three methods.
i.       Single Tap on Screen
         If you touch any point on the screen, it will go through the touchesBegan and
         touchesEnded methods in sequence.

ii.    Move on Screen
       On the other hand, if you move on the screen with one finger. It will go through
       touchesBegan, touchesMoved, touchesEnded methods in sequence.

iii.   Double Taps
       Now, we go on discuss how to detect double taps on the screen. We can simply use the

            touchesBegan method, as shown below. In addition, we can also ask for the location
            where the tap occurs.

 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     NSSet * allTouches = [event allTouches];
    NSSet * allTouches = [event allTouches];

         // Try detecting the first touch event
        // Try detecting the first touch event
         UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
        UITouch * touch = [[allTouches allObjects] objectAtIndex:0];

         switch ([touch tapCount]){
        switch ([touch tapCount]){
            case 2:{ // The touch event has 2 tap count
           case 2:{ // The touch event has 2 tap count
                NSLog(@"touch a point 2 times on screen");
               NSLog(@"touch a point 2 times on screen");

                         // We can also ask for the location of the taps on
                        // We can also ask for the location of the taps on the current screen view.
                         // the current screen view.
                        CGPoint touchPT = [touch locationInView:[self view]];
                         CGPoint touchPT = [touch locationInView:[self view]];
                        NSLog(@"x: %f, y: %f", touchPT.x, touchPT.y);
                         NSLog(@"x: %f, y: %f", touchPT.x, touchPT.y);

iv.         Multiple Touches on Screen
            Other than detecting double taps of a touch event, we can also detect two touches events
            like this:

       Below shows the corresponding codes:

 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     NSSet    allTouches    [event allTouches];
    NSSet * *allTouches = =[event allTouches];
      UITouch    touch    [[allTouches allObjects] objectAtIndex:0];
     UITouch * *touch = =[[allTouches allObjects] objectAtIndex:0];

      switch([allTouches count]){
     switch([allTouches count]){
         case 2:{
        case 2:{
                UITouch    touch2    [[allTouches allObjects] objectAtIndex:1];
               UITouch * *touch2 == [[allTouches allObjects] objectAtIndex:1];
                NSLog(@"touch     points on screen");
               NSLog(@"touch 2 2points on screen");
                CGPoint touchPT1    [touch locationInView:[self view]];
               CGPoint touchPT1 = =[touch locationInView:[self view]];
                CGPoint touchPT2    [touch2 locationInView:[self view]];
               CGPoint touchPT2 = =[touch2 locationInView:[self view]];

                NSLog(@"x: %f, y: %f", touchPT1.x, touchPT1.y);
               NSLog(@"x: %f, y: %f", touchPT1.x, touchPT1.y);
                NSLog(@"x: %f, y: %f", touchPT2.x, touchPT2.y);
               NSLog(@"x: %f, y: %f", touchPT2.x, touchPT2.y);
     By asking for the size of allTouches, we can distinguish how many touches actually exist
on screen.

2.2 Moving a Man Image within Boundary
In this part, we are going to implement the codes that allow the man image to be dragged
horizontally when the user touches on the image.

Basically, we only need to modify touchesMoved (why not the other two?) in this part of tutorial.
What we are doing inside involve:
i. Detect the touch move position on screen
   Refer back to 2.1 (iii), we can get the touch point information within the touchesMoved
   method by:
          UITouch * *touch = =[[allTouches allObjects] objectAtIndex:0];
           UITouch    touch    [[allTouches allObjects] objectAtIndex:0];
                    touchPT    [touch locationInView:[self view]];
           CGPointtouchPT = =[touch locationInView:[self view]];
Note that the variable touchPT is of type CGPoint, we can get its x(y) coordinate by using
touchPT.x (touchPT.y) directly.

ii. Check whether the touch point falls within the rectangular box of manImage
     Recall that manImage is the variable of UIImageView which holds up the image “man.png”.

    Suppose the bounding box of the manImage likes the following:

                                (X1, Y1)                     (X2, Y1)

                                (X1, Y2)                     (X2, Y2)
    We can get the coordinates of the bounding box by:
         X1 = manImage.frame.origin.x;
          X1 = manImage.frame.origin.x;
          Y1 manImage.frame.origin.y;
         Y1 = = manImage.frame.origin.y;
          X2 manImage.frame.origin.x + manImage.frame.size.width;
         X2 = = manImage.frame.origin.x + manImage.frame.size.width;
          Y2 manImage.frame.origin.y + manImage.frame.size.height;
         Y2 = = manImage.frame.origin.y + manImage.frame.size.height;
    With the knowledge of the bounding box coordinates, you can check whether your touch point
    falls within the bounding box of the manImage easily. For more details about this, you are
    referred to Page 22 of Lecture Note 3.

iii. If true (if the touch point falls within the rectangular box of manImage)
     If the touch point falls within the rectangular box of manImage, we need to handle the
     manImage horizontal movement situation. On Page 28 of Lecture Note 2, we have discussed
     some common updates on UI components. In fact, to move the manImage, what we can do is
     to move its center position similar to that shown in the lecture note. You can drag the
     manImage horizontally by:

   [manImage setCenter:CGPointMake(touchPT.x,];
      [manImage setCenter:CGPointMake(touchPT.x,];

   By using the above statement alone, the manImage can move out of boundary. However, we
   would like the manImage to be bounded within the left and right boundary of the screen view.
   To do so, before updating its center position (i.e., before executing the above statement), you
   have to check whether the touch point can move the manImage within the left and right
   boundary of the screen view.

   For more information about this part, please refer to Pages 23 - 25 of Lecture Note 3. For your
   convenience, we have defined 2 constant values for you to check the boundary conditions,

   Now, you can get a screen capture like this one:

3. Remaining Parts
To complete the game, we have to implement the game rules. That is,
 Detect whether a VolcanoRock object hits manImage
 Game information update
 Game end condition implementation
 Game reset
 Game cheat

3.1 Collision Detection
In this app, we consider two objects to be colliding only when d < (r1+r2).




Put the following method in “VolcanoRockEscapingViewController.m” (We have provided the
method in “additionalFile2.txt”, you can download the file from our website and copy the method
to the .m file) to detect whether the object centered at (x1, y1) with radius r1 collides with the
object centered at (x2, y2) with radius r2.

- -(bool) collide : :(float) x1 : :(float) y1 : :(float) r1 : :
    (bool) collide    (float) x1    (float) y1    (float) r1
        x2 : (float) y2 : (float) r2 {
(float)(float) x2 : (float) y2 : (float) r2 {
     float centerDistance = =sqrt(pow((x1-x2),2) + +pow((y1-y2),2));
      float centerDistance    sqrt(pow((x1-x2),2)    pow((y1-y2),2));
     return (centerDistance < <(r1 + +r2));
      return (centerDistance    (r1    r2));

Please be reminded to declare the method in “VolcanoRockEscapingViewController.h” file.

Hence, to detect whether a VolcanoRock object collides with the manImage, we can use the
above method like this:

 [self collide
[self collide : : : :
 volcanoRock.frame.size.width/2 : :
colcanoRock.frame.size.width/2 :: : :

Note that this method will return a bool variable to indicate whether the VolcanoRock object
collides with the manImage object, and we assume the radius of a UI component is approximately
the same as the width/2 of the bounding box of the UI component.

Now, to complete this part, you may consider the following procedures in the method progress:
    For EACH VolcanoRock object (same as that in Sections 3.2 and 3.4 in Tutorial 2) in
     volcanoRockArray, we have to check whether the volcanoRock object collides with
     the manImage. Without loss of generality, we assume that it is the ith element in
     volcanoRockArray and has been assigned to volcanoRock (see hint 2). If collision
                          1. Remove the object from screen view:
                              [volcanoRock removeFromSuperview];
                             [volcanoRock removeFromSuperview];
                          2. Release the memory held by the object:
                              [volcanoRock release];
                             [volcanoRock release];
                          3. Remove the object from volcanoRockArray:
                              [volcanoRockArray removeObjectAtIndex:i];
                             [volcanoRockArray removeObjectAtIndex:i];

1. The size of volcanoRockArray can be obtained by calling:
 [volcanoRockArray count];
[volcanoRockArray count];
2. To get ith element of volcanoRockArray, you can do so by:
 volcanoRock    [volcanoRockArray objectAtIndex:i];
volcanoRock = =[volcanoRockArray objectAtIndex:i]

3.2 Game Information Update
Up to this moment, you have completed most parts of the game. However, you still haven’t applied
any game rules into it so as to make the game progress. In this part, we would like to implement the
following two game rules:
    i.    When a VolcanoRock object falls out of boundary, you get one score more.
          Hint: Combine Section 5.4 in Tutorial 1 and Section 3.4 in Tutorial 2.

   ii.   When a VolcanoRock object collides with the manImage, one life will be deducted.
         Hint: Combine Section 2.1 in Tutorial 2 and Section 3.1 above.

3.3 Game End Condition Implementation
   i.    Finally, implement the function such that the game will end when all lives are used up.
         When the game ends, output a statement to the console to show your scores and the
         time elapsed.
         Use NSLog to output the values to the console.

   ii.   Instead of outputting the result to the console, it is also possible for you to activate a pop
         up window to show the game end message. In iPhone, this is known as Alert Window:

     NSString * message =
     [NSString stringWithFormat:@”You got %d score in %.01f s”, score, timeElapsed];

     UIAlertView * av = [[UIAlertView alloc] initWithTitle:@”Game Ended”
                                                 otherButtonTitles:nil, nil, nil];
     [av show];
     [av release];

          The first statement creates an NSString object for showing the messages on the Alert

          The second statement creates a UIAlertView object with the title “Game Ended”,
          message with the one created in the first statement, and with a button. After the creation
          of the alert view, you need to pop it up, which is done by the show method. Finally, we
          have to release its memory after done.

iii.      Please be reminded to stop the timer also.

After you have implemented this part, you can see a screen capture like this:

3.4 Reset Game States
In iPhone app, shake is commonly used as a gesture to restore the game state back to the initial
state. Hence, the goal of this part is to implement the function such that the game states will be
reset when a shake is detected. This part should be very easy to you after three tutorials. Therefore,
we only provide some hints for you to implement yourself.

We keep track on three kinds of state information in this app, i.e., score, timeElapsed, life. Through
the tutorials, you have learnt:
1. How to manage the UI components that represent these kinds of state information. For
example, scoreLabel for score, timeLabel for timeElapsed,                             life1Image,
life2Image, life3Image for life.
2. How to implement a function to handle the case when shake is detected.

3.5 Game Cheat
Usually, a game designer will include some cheats inside their game. Here, we also include one
cheat into our game. Specifically, when you touch the volcano rock shown on the screen, the rock
will be removed from the scren. This cheat is very useful, especially when the rock nearly hits the
manImage. To implement this function:
In TouchesBegan Method:
    for each volcano rock object:
         if the touch point falls within its bounding box, then we remove it

If you have finished up to this part, congratulations, you have finished most parts of your first
iPhone game app.

If you cannot finish this part and would like to see the results, please download
“” from our website.


Shared By: