iPhone Game Programming Tutorial Part 2- User Interaction, Simple AI, Game Logic

February 18th, 2009 Posted by: (ELC) - posted under:Tutorials

Ok folks, here it is. The next tutorial in our iPhone game programming tutorial (sorry for the delay).  Today, I will be discussing the basics of player interaction, simple game AI, and game logic.  We will also be exploring how to do simple collision detection so we know when the ball hits a paddle. Per popular request, I will be adding “Challenges” to the bottom of the tutorials from now on to give some more advanced ideas for improvement. Let’s begin. Start by opening your code from part 1…

User Interaction

The first thing we will implement is user interaction.  All we really want to do is move the paddle’s X location to the X location of the touch from the user.  This will be a very simple implementation and could be much better (I will add this as a challenge at the bottom of the tutorial).  Open iTennisViewController.m and add the following code.

screenshot_01

Just as we did in a previous tutorial, we are overriding the touchesMoved method.  This will detect when the user “drags” their finger on the screen.  First, I added the “else if” statement inside of touchesBegan that simply forwards all events to touchesMoved if the game is in a running state.

The first 2 lines inside of touchesMoved simply detect the location of the user’s touch.  Next, we need to create a new CGPoint from the X location of the touch and the Y location of the yellow racquet (player racquet).  Objective-C won’t simply let us say racquet_yellow.center.x = location.x.  This is probably because CGPoint is immutable (not editable).

Finally, the center of the player’s racquet is set to our new location.

Collision Detection

*Update, the user Naren has pointed out a much simpler collision detection.  The code has been updated to reflect it. Inside the gameLoop method of iTennisViewController.m add the following code

screenshot_011

So, Apple has provided us with a very handy methods to check if to object frames collide.  Its called CGRectIntersectsRect.  We simply hand this method the frame of our ball and racquet.  When the ball collides with the racquet, we want to reverse its Y velocity.  The next if statement is required because sometimes we get in a state where the ball gets “trapped” on a paddle bouncing back and for and not going anywhere.  So, we want to ensure the ball’s velocity only gets reversed if it is front of each racquet. (Note, the NSlog is not needed, it was just for debugging)

Simple Game AI

Next, we are going to discuss how simple AI can be added to allow a computer player to play iTennis with you.  Many of you might not know just how much is involved in a decent Artificial intelligence.  I could go on and on with nerdy math, philosophy, heuristics and the like, but I’m not.  I will show you some super NOOB, very easy to understand game AI.  Basically, the computer will “watch” the ball and move in the direction of it in hopes of hitting it.  Let’s get started… 

We first need to define a constant that will define how fast the computer player can move.  Add the following define to the top of iTennisViewController.m

picture-2

As you start testing, you can adjust this number.  This is basically defining how fast the computer player can move in order to get to the ball.  The higher you make this number, the “better” the computer player will be.  You could actually make your computer unbeatable if this number were high enough.  Now, add the following code right under your collision detection code:

picture-3

The first “if” statement is to add some difficulty for the computer.  It basically checks to see if the ball is on “his” side of the court.  The computer will not move or respond to the ball unless it’s on his side.  It could be omitted, but makes for a more interesting game.  The next if statements check to see if the X coordinates of the center of the ball are different than the X coordinates of the center of the racquet.  If the ball is to the right of the computer’s racquet, the X coordinate of the computer’s racquet is increased by kCompMoveSpeed. If the ball is to the left of the computer’s racquet, the X coordinate of the computer’s racquet is decreased by kCompMoveSpeed. 

It should now be clear how adjusting the kCompMoveSpeed variable, will affect the computer’s performance…

Now, you can actually hit Build and Go to see the game in action.  As you can see the computer responds to the ball and hits it most of the time.  There is still one last piece to make the game fun. Scoring!

Game Mechanics: Scoring

Now, we need a way to keep score.  This is actually some more simple collision detection.  We are basically checking to see if the ball collides with the back walls.  First, let’s define a few variables and a method.  Open up iTennisViewController.h.  Add the following highlighted code:

picture-4

We need integer representations of the score so we can add points when the player and the computer score.  Also, we will need a function called reset that will be called to reset the ball to the center of the screen.  Now we need to define one more variable.  Add the following line to your defines at the top of iTennisViewController.m

picture-5

This variable is pretty self explanatory, but in case you didn’t catch on, it defines the amount of points needed to win.  I just made it 5 for a quick game.  Now, let’s check to see if a player or computer scored.  Right after your AI code, add the following code:

picture-6

Ok, first we see 2 if statements.  The are basically checking to see if the ball has hit/passed the top or bottom of the screen.  If it passes the top, the player score gets incremented.  If it passes the bottom, the computer score gets incremented.  The next line contains a little bit of fanciness if you are new to programming.  We are calling the reset function, but what is that expression we are passing to it? 

Well, if you look at the definition of reset, it takes a BOOL value that determines if the game is over.  So this can either be true or false.  We are simply passing true or false when the expression is evaluated.  So, (player_score_value >= kScoreToWin) will evaluate to false when the player_score_value variable is less than 5.  Once this variable reaches 5, it will return true and pass it into the reset function.

Why do this? Well it saves us lines of code and complexity.  So now you don’t have to do if(player_score_value >= kScoreToWin) ) [self reset:YES]; }else{[self reset:NO];} . make sense?

Now, let’s define the reset function. Add the following method to iTennisViewController.m

picture-7

The first thing we do is pause the game.  Remember pausing the game causes the “Tap to Begin” Message to Display. Next, we center the ball on the screen.  If YES/true was passed in for the newGame variable, we need to do a few things.  First, we check who won by comparing the computer and player scores.  Next, we update the “tapToBegin” message to notify the player who won.  You could add another label for this, but I am just recycling this one… Finally, we reset the player and computer scores to 0 because a new game is starting.

If it is not a new game, we need to reset the tapToBegin message to display “tapToBegin”.  This has to be done in case the message was altered to say “Player/Computer wins!”. Finally, we update the labels on the screen to reflect the new scores.  Now you should be good to go…

Click Build and Go and battle the computer in an epic game of iTennis!  If you have any comments or questions, leave them here or ask me on Twitter.  You can also download the source for this tutorial here

As Promised, Here are some challenges

 

  • Improve on user interaction – Make it so when the user taps, the racquet moves towards the tap rather than moves directly to the tap location
  • Improve collision detection – When the ball hits the paddle, use some simple physics to make the speed of the paddle affect the speed (and direction) of the ball
  • Improve on the AI – add some randomness to your AI, make it attempt to “predict” where the ball is going to be
  • Improve Scoring – Make it used tennis scores 15, 30 , etc…
  • Improve scoring – Make it so you must win by 2 points

 

Stay tuned for the next tutorial when I will be going over game audio, splash screen, about, and some other polishing… Happy iCoding!

  • Pingback: New iPhone Game Programming Tutorial Post On iCodeBlog | Brandon Trebitowski

  • Koplimi

    Thank you for the next part in this very helpful guide!

    I have learned some new things following tyour guides and will now attempt to do the “improvements” you challenged me with.

    To make the ball bounce correctly on the walls (instead of halfway in)

    add this in the right place at the bounce logic.

    (ball.frame.size.width / 2)

    ex.
    ball.center.y > (self.view.bounds.size.height – (ball.frame.size.width / 2) )

    It worked with this also:
    (ball.bounds.size.width / 2)

    But i don’t know which one of them that is preferred.

    Please spread your wisdom once again!

  • http://www.lichen1985.com Chen Li

    Very good tutorial!

    I have a question: if the user touches the Home button, and want to return the previous game later, how do you store the game data? I think this is very important, can you give me some quick hint?

  • Naren

    @Chen
    If you click on home button and went back to the previous screen. just pause the game by using gameState = kgameStatePause and store all the data like ball x,y positions and racquets xy positions , scores and do this in applicationwillterminate and viewWillappear method. viewwillappear will be called when you come back to the screen and applicationwillterminate will be called when you got a phone call or message.
    or just put one breakpoint on viewwillload, didload, willappear, didappear. which ever is getting called pass the stored values their and gameState = kgameStateRunning. Hope it will work.
    Thanks

  • Naren

    For collision detection
    better than comparing the center positions of ball and racquets , use CGRectIntersectsRect method
    like if(CGRectIntersectsRect([ball frame],[racquet_yellow frame])) why i m saying this is because for a good practise, in future if u will make a game where you are using multiple balls then this will help you a lot.

  • http://www.lotofwallpapers.com Chintan

    @Naren…

    You are right. The best way to detect collision is CGRectIntersectsRect method. I have used it to make my own version of pong and it works very well.

    There are complicated collision detection methods which work better as they detect collision at pixel level (Chipmunk/Cocos2d) but they need some expertise to be used.

    One drawback of CGRectIntersectsRect is that even if you have an oval ended paddle, the ball will reflect from the invisible Rect part without touching the oval edge of the paddle. So i had to use rectangular paddles instead of oval. Any solution for this??

  • Koplimi

    Hello again!
    I am in need of some advice.
    The game now will show the status bar on the top and therefor only allow us(me) to use a screen size of 320*460.

    How do I remove the status bar in the top?

    And one other question!
    How do I rotate an object in interface builder 90 degrees?
    Or could that be done in code?

    Hope anyone knows. Thanks!

  • Koplimi

    Found a solution to hiding the status bar.

    Add string:
    UIStatusBarHidden

    to info.plist rightclick and select valuetype->boolean
    check the square.
    The status bar is now hidden.

    You might need to make changes to the iTennisViewController.xib

  • Nasser

    Hello,
    thank you for your tutorial. but why the ball movement is not smooth?
    is it because the use of the timer?, any alternatives?
    thanks again

  • Koplimi

    @Nasser

    Decrease timerinterval to 0.02

    set
    kBallSpeedX 3
    kBallSpeedY 5

    much smoother

  • Chen Li

    Thanks a lot Naren!

    Yeah I know how to save and restore data now from your hint.
    Basically, save data when applicationWillTerminate (probably during runtime if there’re so much data), and restore data when applicationDidFinishLaunching. I’ve used NSUserDefaults to save my data.

    A problem is, all the data has to be converted into float or int or similar popular data types to be saved. Do you know if there’s any way that I can directly save objects with my own class type?

  • Naren

    @Chen
    Make a class which is subclass of NSobject,
    declare some variable that you want to save,
    and in applicationWillTerminate call the class’s object to save the values. like class_obj.ballX = ball.center.x;
    something like that, that will help you .

    @Chintan,
    actually the problem is we are taking a uiimageview and within it we are taking the ball , so our touches method will work as per uiimageview not the ball’s shape. so no matter it is oval, triangle or polygon. results will be for rectangle . if you want to acheive the same try using button of oval shape, give its background the image. and check in rectIntersects method. or directly take uiimage and then check for that. but the problem is you need to make uiimage directly or with the help of CoreGraphics classes. that is a bit hard of some noobs and complicated for the programming. if you want to make the ball dynamically then google GravityTutorial part1 to part5. i did not try with buttons but you can try.

  • http://www.lotofwallpapers.com Chintan

    @Naren….

    Yes, i know thats the problem. I have thought about what you suggest but then it would bring in much complications. I am already having some memory issues. Right now, the rectangular paddle is doing great. :) ..

    Yes, i have coded the whole gravity tutorial also but i dont want to change so much code. So i think this is how i will submit my game to App Store.

  • chesterF

    Thanks for the great tutorials! They have given me many useful tools to develop with, I really appreciate your effort.

  • BerryMelong

    Finally!!
    I’ve been Waiting for this tutorial for years! iCodeBlog had been very helpful for me since i’m new to iPhone Programming. Thanks for your great job! I’ll be waiting for your next tutorial!

  • http://wayneice.com Matt

    Awesome dude, youre the shit.

  • Shaman

    How do I cap the ball speed? Speeding up and down is great, but sometimes it goes crazy and I would like to remove that.

  • Matthew

    I have been trying to follow the 2nd post to stop the ball going through the racquet, but with not much success. Is it:

    if(ball.center.y > self.view.bounds.size.height – (ball.frame.size.width / 2) || ball.center.y < 0) {

    or am I missing something?

    Great tutorial!

  • jitesh61

    Nice tutorial again !!

    All works completely fine for me .. all the changes which are suggested have also worked perfectly.

    Just having some problem at runtime …..

    I changes the kCompMoveSpeed to 5 ….. Some time the game goes into infinite loop …..

    when computer’s racquet is not able to hit ball properly towards user and it goes behind the comp’s racquet ….the ball just stuck over there … :(

    and I have to press the home button to come out of the game …..

    It do not happens every time …but only sometime ……..

  • Christopher

    I came back to this post just to see if anyone else had the same issue as I did. It looks like ‘jitesh61′ already asked the question though.

    I’m wondering what causes the ball to behave this way and never actually hit the wall behind the computer’s racquet and score a point.

    I have had it bounce behind my own racquet as well.

    Im wondering if our racquet objects are too big? I havent taken the time to try to size them down to see if that helps or not.

  • Keiran

    @Christopher & @Jitesh61:

    What’s probably happening is the ball is getting “stuck” due to the fact that on back to back “running”s of the game loop, the ball is technically still “colliding” with the computer’s racquet, and thus keeps reversing direction and appearing to be “stuck”.

    To fix this, I added in an additional if statement before the collision detection of each racquet to ensure the detection was only occuring if the ball were heading in the proper direction, so when the ball reverses direction, no collision detection would be in place for the current racquet. So around the collision detections, put:

    if(ballVelocity.y 0) {
    {bottom racquet collision detection code here}
    }

    Hope this makes sense.

  • Keiran

    Tags were stripped, the code is:

    if(ballVelocity < 0) {
    {top racquet collision detection}
    }

    if(ballVelocity > 0) {
    {bottom racquet collision detection}
    }

  • http://brandontreb.com Brandon

    Thanks for all of your comments. Sorry it has taken me so long to respond. I have updated the tutorial to include the suggestion made by @Naren.

    Also, I have improved it so that the ball no longer gets caught on the paddles.

    The source code has also been updated to include tweaks for the variables that produce smoother animation. Sorry for my delay on this…

  • Naren

    @Brandon
    Thanks for checking and implementing my suggestion. and thanks for all the users to read it.

  • http://mdreeling.wordpress.com Mick D

    Great 2nd Tutorial, and with the comments from Naren, that really smooths out some of the issues.

  • Brian

    Hello,
    I would like to use this tutorial for a game i would like to create. Instead of moving an object horizontally (like the yellow racket) i would like to move the object vertically. I tried to modified the code under the TouchesMoved method but i was not successful, by changing the X into Y my image move diagonal but that’s about it. Any help would be welcome. Thanks.

    • Jnani Weibel

      What you could do to be able to move the racquet anywhere would be to remove the line in touches moved that says:

      CGPoint xLocation = CGPointMake(location.x,racquet_yellow.center.y);

      from:

      - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
      UITouch *touch = [[event allTouches] anyObject];
      CGPoint location = [touch locationInView:touch.view];
      CGPoint xLocation = CGPointMake(location.x,racquet_yellow.center.y);
      racquet_yellow.center = Location;
      }

      • Jnani Weibel

        woops messed up the bottom two lines shouldn’t be crossed out.

  • guy tavor

    Hi !
    thanks for a great tutorial.

    Ai code could be shortened as follows:
    //
    // Move computer racquet.
    //
    int diff = racquet_green.center.x – ball.center.y;
    CGPoint newLocation =
    CGPointMake(racquet_green.center.x
    + (diff < 0 ? kComputerSpeed : -kComputerSpeed),
    racquet_green.center.y);
    racquet_green.center = newLocation;

    Just a suggestion. Thanks again for a great initiative. hope you keep these tutorials coming.

  • Rich

    Hey.

    First I’d like to say thanks for your tutorials. I’m really excited about this stuff.

    Second, I’m sorry to say that I followed your code and instructions to the ‘T’ but kept getting an error related to the calls to CGRectIntersectsRect. The message was something about missing symbols.

    I fished around my code, comparing it to the site, and I couldn’t find anything different. Then I downloaded your code and compared the two sets of code, both manually and by use of FileMerge. Nothing (important) was different.

    I noticed, after firing up your project and seeing it compile w/o error and trying to compile my project w/errors that you have one more framework included in your project that I did. CoreGraphics(? sorry, I’ve shut down stuff for the night). I fished around your two posts for mention of that and there was none. Not that I could see. Then I had to fish around to find out where it was located on my drive. I included it and BAM! It compiled and I could play iTennis w/o problems.

    Other than that, not too many problems. Your use of IB seems like you haven’t used it too much before, though. You could totally option+drag things to duplicate them (the scores and the paddles) rather than keep dragging stuff from the pallet. Sizing with the mouse is fine, but if you want precision you should find the dimensions of the image and then just type them into the dimensions area in IB. I’m not trying to be mean. It’s just stuff I learned a long time ago when I first started out.

    Thanks again. I look forward to many great tutorials from you and this site.

  • http://thinkjoke.servemp3.com Rush

    Love your Tutorial. Can’t wait for part 3, please post it soon.

  • jitesh61

    Hi all,

    I checked the complete code, but no where I have found “Default.png”.

    This image has been added to the Resources folder but, it’s not at all used in code … and when we run this application first thing which comes on view is Default.png image.

    This image also has been not used in Interface builder.

    I m bit confused, why this image is appearing as a first view and only for some time interval?

    Looking forward for some more tutorials. :)

  • Fredster

    Would someone be able to help me implement playing a sound when the ball hits the walls (sound1) and (sound2) when the ball hits the paddles?

  • Fredster

    Also, does anyone know how to change an image based on a count? Something like stringWithFormat:(“%d.png”, player_score_value); or something like that?

    I don’t even know how to change an image dynamically to do this. Where to declare it, etc?

  • Oh Dreamer

    I really appreciate this tutorial, I’m going to be making an iPhone game for one of my project-based classes and this is a good start.

    I was having trouble with the updated collision detection code posted, but with the help of Keiran’s post I think I figured it out. Here is the collision detection code that works for me:

    if(ballVelocity.y > 0) {
    {top racquet collision detection code}
    }

    if(ballVelocity.y < 0) {
    {bottom racquet collision detection code}
    }

    The tutorial has the “stuck” checking code inside the collision detection code when it should be outside, and Keiran’s code has the comparator signs backwards (for me at least…)

  • Oh Dreamer

    Actually, Keiran’s comparator signs are correct, my bad lol. I had the yellow racquet first. So it truly is:

    if(ballVelocity.y 0) {
    {bottom (yellow) racquet collision detection code}
    }

    Sorry Keiran!

  • Oh Dreamer

    Mulligan:

    if(ballVelocity.y 0) {
    {bottom (yellow) racquet collision detection code}
    }

  • Oh Dreamer

    Fail :(

  • Pingback: iPhone Dev - Games/Apps - Top Bookmarks « Java Developer / Fledgling iPod Touch Developer

  • Sameer Kumar

    i have the same question as jitesh61: where is the startup image set??

    great tutorial….your a legend!!!

  • Meta

    Hy

    My quastion is that, how can I detect collision between UIImageView with ellipse object?

  • rramnel

    Hi there,

    Great tutorial indeed. I was wondering how can I ensure that the ball is “stuck” to the racquet once a point is taken. I tried the following in the “// Begin Scoring Logic” sequence.

    ball.center = racquet_yellow.center;

    It works only if I remove my hand after the point is played. If I still touch the screen and move it then, the racquet moves, but the ball’s position is at the last position where the racquet was. Any suggestions on how to move the ball’s position along with the racquet’s position when it is moved?

  • Adil

    Thanks a lot for this great tutorial !!!

  • http://knightbeatz.com Mike

    I am having trouble with one part. . . . .
    http://img27.imageshack.us/my.php?image=picture1aql.png

  • rabi

    Hello all,
    thnks a lot for gr8 !! tutorial !!! and good suggestion as well…

    i have same question like “jitesh61″ that gow to add default.png and how it shows as first view for few sec. only ??

  • John

    When is the next tutorial going to be put up??

  • Chris

    The Default.png is used by SpringBoard (the application launcher). If you have a default.png file in your project’s resources, it will be loaded and displayed by the launcher until your application is fully up and running.

  • http://knightbeatz.com Michael

    I posted a comment with a screenshot of an error im getting and you deleted it? i dont understand why? is it possibly cause its something simple?

  • Will

    Anyone know how to move the paddle on the x and y axis?

  • Alex

    Hey does anyone know to improve the collision detection?

  • zKarp

    *Improve on user interaction – Make it so when the user taps, the racquet moves towards the tap rather than moves directly to the tap location

    How do I do this? I tried but when i tap the position is moves just abit, when I hold it goes there instantly. >_>

    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view];
    if(location.y racquet_yellow.center.y) {
    CGPoint yLocation = CGPointMake(racquet_yellow.center.x, racquet_yellow.center.y + kCompMoveSpeed);
    racquet_yellow.center = yLocation;
    }
    }

    thats what I got, might be wrong. *btw its horizontal not vertical)

  • Pingback: iPhone development Tutorials « The Brook Song - ঝর্ণার গান

  • LakshmiKanth Reddy

    can anyone provide me the books for Iphone Development on Gaming.

  • someone

    what about sound? i try but no sucess so far.. ;)

  • http://www.bictrainer.com Rafael

    Very good
    But I got a question:
    Why do you call the reset function everytime you increase a score?
    Wouldn`t be better if we call it just when it`s needed instead to send to it a boolean flag telling to the function if it should work or not?

    Another question, but about Mac OS, everytime I press End it sends me to end of the page, can I make this send the cursor to end of line instead?

  • http://www.solvengineer.com Mike

    Man, I love these tutorials. Can you make one with a game menu (like New Game, Quit, Options)

  • Pingback: iPhone game development guide: On the go tutorial | iPhone Footprint

  • Bjorn

    Thanks for a great tutorial.

    Everything works perfectly for me up until the first point is scored. After that the green racquet (computer player) will not bounce the ball but the ball will instead go straight through. Any idea what might be wrong?

  • http://ammadat@pacbell.net Stefan

    I’m trying to make a game and was wondering if I could have Brandon Treb’s email bcuz I have a few questions for you.

    Can you make a game tutorial on getting certain amounts of money for doin stuff and spending it to buy stuff in the game?
    Thanx for the tutorials it helps a lot

  • wiegeabo

    I’m having the same problem Rich had. When I try to use CGRectIntersectsRect I get a symbol error, and it obviously won’t compile. Any idea how I can get this to work?

  • wiegeabo

    I should have read the rest of Rich’s post. Because once I included the CoreGraphics framework for my latest SDK, the app loaded fine.

    Might want to mention that in the tutorial.

  • http://www.developingforiphone.com Create

    Great tutorials. I have noticed that there is a book on iPhone game development due to be published in June (found it on Amazon) – something worth checking out!

  • chris

    Hey i am having problems with the ball getting stuck on the paddle!! I saw what it said about it in the tut so i put that code in my program and it still dosn’t work!!
    Can someone please help
    Thanks
    chris

  • chris

    Hey i am having problems with the ball getting stuck on the paddle!! I saw what it said about it in the tut so i put that code in my program and it still dosn’t work!!
    Can someone please help!!
    Thanks
    chris

  • chris

    sorry about the duplicate my comp was acting up

  • DcWHaT

    Does anyone know how to speed the ball up? I tried messing with ballvelocity = CGMakePoint(kballspeedx + 1, kballspeedy +) and the ball flys off the screen? Or I got it to where it randomly changes directions wherethr speed is changed

  • ZOT

    Hey, great tutorial, just one question thought — in the reset function, when you call self.view.center, do you get the correct value for y? When I call self.view.bounds, the height value is 460 (which I would expect — 480 vertical pixels – 20 for the menu bar), but self.view.center.y is coming out at 250. Why is center not half the height?! It’s not even half the height of the display…

    Best,
    -Z

    • Rafael

      Hello ZOT,

      I had the same problem, so instead of using the “self.view.center” I used the actual values…

      ball.center = CGPointMake(160,230);

      That way the ball is properly centered…

      Best,
      Rfl

  • Steve

    First of all help me say the is by far the best iPhone programming tutorial i have come across thus far. What i was trying to figure put was how do i get the ball to go straight instead of diagonal for the first serve .

    Thanks again for a great tutorial

  • JayyB

    How would you handle the touchesMoved event if lets say this was a 2 player game?

    For instance if the green raquet was also being controlled by a user. I’m still learning objective c so please bear with me.
    Any help would be greatly appreciated.

    Great tutorial by the way!

    • Gregory Ellis

      use this in touches began and it should allow you to use both paddles by dragging them. I’ve never tested it outside a simulator so not 100% sure how well it would work on an iphone

      UITouch *touch = [[event allTouches] anyObject];
      CGPoint location = [touch locationInView:self.view];
      if ([touch view] == racquet_green) {
      // move the image view
      racquet_green.center = location;
      }
      if ([touch view] == racquet_yellow) {
      // move the image view

      racquet_yellow.center = location;
      }

      • Wesley

        This answers seems to be a solution, but a players figner would have to be one the racquet view. Another solution allowing each user more freedom may be:

        if (location.y self.view.bounds.size.height / 2) {
        // move the image view
        }

        Something like this may allow the yellow player to make gestures below the net, and the green player to make gestures above the net. Each gesture moving the paddle on the side of the net the gesture was made.

        I have not tried this. I’m busy looking for an answer to my won problem :-D

      • Wesley

        Well that code failed to display properly…

        Anyway, the point was to say check if the gesture’s y location is below or above the net, then move the according paddle.

  • Merimim

    hello,
    i’m not a pro of game development, but maybe you can test the point where the touch is done.
    If it is in the upper part of the screen, then you move the green raquet.
    If it is in the lower part, then you move the yellow raquet.

    And of course, desactivate the IA part of the code.

  • JayyB

    I’ll give that a try. My concern is which location will be returned if two users are controling their raquets at the same time.

  • Dcybele

    For animating the movement of the yellow racquet I added this code:

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    [UIView beginAnimations:@"Move Racquet" context:nil]; <—–added
    CGPoint location = [touch locationInView:touch.view];
    CGPoint xLocation = CGPointMake(location.x,racquet_yellow.center.y);
    racquet_yellow.center = xLocation;
    [UIView commitAnimations]; <—– added
    }

    Got this from “Beginning iPhone Development, Exploring the iPhone SDK” book by Dave Mark and Jeff LaMarche, chapter 5. Course this will become a collectors item with sdk 3.0 coming out :-P

  • gagagames

    Did anyone accomplish this task:
    Improve collision detection – When the ball hits the paddle, use some simple physics to make the speed of the paddle affect the speed (and direction) of the ball

    If so, can you provide some hints?
    How do you find out how fast the paddle is moving on the player side? Is there a way to track the speed the user is moving the paddle?

    Thanks!

  • qwe123

    Hello, I received a problem when I tried to debug this. It says there is a a syntax problem before ‘if’. Help?

    if(CGRectIntersectsRect(ball.frame,racquest_yellow.frame)) {
    if(ball.center.y < racquest_yellow.center,y) {
    ballVelocity.y = -ballVelocity.y;
    }
    }
    }

  • Andrew

    @Brian

    To Move the image vertically you must change:

    CGPoint xLocation = CGPointMake(location.x,racquet_yellow.y);

    to:

    CGPoint xLocation = CGPointMake(raquet_yellow.x,locaton.y);

  • Ryan

    The problem with the ball getting stuck on the paddle has to do with the switching the velocity of the y value on the ball.

    What happens is that sometimes the frame of the ball still intersects the paddle frame after a game loop, and when it comes down to see where the ball is, it thinks it is another collision rather than the ball leaving the paddle and not getting far enough away yet. It can be fixed by making a simple check to see if the value for the velocity is already negative or posative depending on which paddle you are checking.

    For example:

    if(racquet_yellow.center.x 0) {
    ballVelocity.y = -ballVelocity.y
    }
    }

    and

    if(racquet_green.center.x < self.view.bounds.size.width) {
    if(ballVelocity.y < 0) {
    ballVelocity.y = -ballVelocity.y
    }
    }

  • Ryan

    The problem with the ball getting stuck on the paddle has to do with the switching the velocity of the y value on the ball.

    What happens is that sometimes the frame of the ball still intersects the paddle frame after a game loop, and when it comes down to see where the ball is, it thinks it is another collision rather than the ball leaving the paddle and not getting far enough away yet. It can be fixed by making a simple check to see if the value for the velocity is already negative or posative depending on which paddle you are checking.

    For example:

    if(CGRectIntersectsRect(ball.frame,recquet_yellow.frame))
    {
    if(ball.center.y < racquet_yellow.center.y)
    {
    if(racquet_yellow.center.x 0) {
    ballVelocity.y = -ballVelocity.y
    }
    }
    }

    and

    if(CGRectIntersectsRect(ball.frame,racquet_green.frame))
    {

    if(racquet_green.center.y > racquet_green.center.y) {
    if(ballVelocity.y < 0) {
    ballVelocity.y = -ballVelocity.y
    }
    }
    }

  • Anthony

    great tutorial. really easy to follow.

    your source download has a typo tho, you wrote #define kGameStatusPuased instead of #define kGameStatusPaused.

    also i changed the info.plist and viewcontroller.m file so the game runs and starts up in landscape right, but the code is written to be run in portrait. so the paddles move along the x-axis instead of the y-axis. how the hell do i fix this? i’ve tried just about everything..

  • jeff

    hey, im trying to change the speed of the ball when it is hit and i dont even know where to begin. are you going to be posting another tutorial on how to do some of the things you mentioned as challenges? thanks =D

  • Noobatron 2k

    @Bjorn

    I was having the same issue with the ball passing through the green paddle after the second point. I believe it is simply a side-affect of the boundingbox of the green paddle and the CGRectIntersectsRect function. If the ball is going fast enough, and the position of the ball is just right/wrong then the ball will pass through the Rect of the green paddle inbetween gameLoop events. To test this i just decreased the NSTimer from .05 seconds to .025 seconds and twiddled with the speeds to get the program to simply “sample” the gameLoop more often. Viola it started detecting the ball even after the second point!

    Another thing I thought of trying was simply increasing the size of the bounding box of the green paddle. This has the issue, however, that this starts extending the paddle behind and to the side.

    My question is, “What is the best way to detect these collisions?” At this point the program samples quickly to detect collisions. Is it possible to create an event, or check to see if the previous position of the ball in conjunction with the current position would show that it must have passed through the paddle and should thus be bounced?

    Is this the normal operation of iphone games, fast sampling? I suppose one way of working this would be to change the NSTiming invterval based on the speed of the ball/paddle. You could theoretically make it so that it had to check every time the ball moved one of its lengths. Or does NSTimer not allow such interactivity?

  • Pingback: DevTutorial #14 – Creiamo il nostro primo gioco, Pong! (Parte II) - Bubi Devs

  • Jitesh

    Hi,

    First of all thanks for posting this nice tutorial.

    I m making the similar app like this tennis game where i have to detect the collision between two UIImageView’s from which one is stable and only one is moving using touch events.

    In CGRectIntersectsRect method i have simply use one NSLog for checking collision.

    Now, the problem is i m not able to detect the collision between two UIImageView’s, instead the collision occurs when i move my object to (0,0) coordinates of iPhone screen.

    Can anyone tell me what is my mistake.

    - Jitesh

  • http://itouchapps.de Cornelius

    Hi,

    thank you for this nice tutorial. I just want to make the frame smaller, so the ball bounce when the ball hits a white line.
    So I changed if(ball.center.x >= self.view.bounds.size.width || ball.center.x = self.view.bounds.size.width || ball.center.x < 20). But no the ball is only bouncing away at the left side, but I want it bouncing away at the right side too. How can I do this?

  • Pizzabox

    Fantastic tutorial.

    Just one thing I noticed: the collision detection didn’t seem to work for the yellow paddle until I changed:

    if(ball.center.y racquet_yellow.center.y)

  • Pizzabox

    Sorry forgot the escape characters for the html.

    Changed less than to greater than for the detection.

  • Pingback: Quick Post: iPhone Game Tutorials | Thomas Nicholson iPhone Developer Newbie

  • Kevin

    Sorry, if this is an ovious question, but I can’t seem too find part 1 of this tutorial and would really like too learn from it. So can someone link me too part one?

  • getskilled

    hi i got the problem that the green racquet just moves out of the screen on the left side at start any ideas whats wrong ??

  • Steve

    I CANNOT get this tutorial game to run properly in the iPhone simulator.. The project builds and compiles with ZERO errors. When the newly generated app runs on the simulator, the “Default.png” splash briefly appears on the screen, then disappears and is replace with ONLY the court.png background image. The ball and racquet png images are not visible, nor are the score labels, number text fields and the “Tap To Begin” text field. I just get the court image only, the program does nothing else and clicking on the screen does nothing either.

    I have gone over the code several times, and cannot find any difference with the tutorial code. The view panels all seem to be connected to their IBOutlet names in interface builder. Again NO compile errors, yet game does not work, at all.

    I am not a noob to game programming. I have written far, far more complex games in Flash ActionScript using custom classes, with multiple sound effects triggered at once and more advanced AI than this tutorial covers. That said, I can’t figure out why this little pong game will not work (obviously do to my lack of experience with Object C and iPhone programming) and something that is missing (instruction wise) from this tutorial. A Flash game programming veteran should be able to get something this simple to work on iphone, you would think..

    Therefore, in my opinion, this tutorial is only suitable for people with prior experience using Xcode, Object C, and Interface builder who have successfully gotten something even more simple (if that is possible) to run. I’ll probably now just go to an extremely simple Apple provided tutorial on how to program the most elementary non game app. Then try to figure out why I can’t get Pong 101 to work at all.

    This tutorial looked good to get a start on games with iPhone, but it didn’t work out for me.

  • Golem95

    I’d swear that the collision logic for the paddles is reversed. If the green paddle is on the top, and the yellow paddle is on the bottom, shouldn’t we be checking if the ball.center.y is LESS THAN the green paddle’s center, and GREATER THAN the yellow paddle’s center?

    If I enter the code as shown above, it doesn’t work. If I reverse the greater than/less than signs, it works.

    However, it works in the downloaded example, but I’ll be darned if I can figure out why. I thought maybe the IBOutlets were reversed in InterfaceBuilder, but they’re not.

  • codebx

    Just as a warning to those who’ve read other tutorials beforehand, I had an issue with the collision detection not working properly because I had used “cmd + =” to shrink the frame to an exact fit of the image instead of manually resizing the frame with the mouse. Once I brought out the frame/bounding box a little bit outside the image, the collision detection worked really well.

  • Golem95

    Codebx, that’s a common problem with this kind of collision detection. If the dx/dy (i.e. velocity) of the ball is greater than the width of the paddle, it’s possible for the ball to “pass through” the paddle without ever actually intersecting it. By increasing the bounding box of the paddle, you’re increasing the chances of an intersection with larger areas.

    Another fix would be to decrease the dx/dy of the ball so that it moves in smaller increments, increasing the chance for a collision with a skinny paddle. You’d probably want to increase the overall game to compensate.

  • Floyd

    Excellent tutorial. I actually understood it! Anyway, I’m having problems with collision detection. After a point is scored it no longer works on the yellow paddle. It still works on the green. I’m sure it’s just a reset issue when the game is paused but I can’t figure it out.

  • Stephen

    Great Tutorial!!!!!!

    I used this as a starting point and created a much more complex game my only problem is i can’t figure out how to get better collision detection so that the ball hits the racket “ball velocity” will be determined by what part of the racket it contacted

    any help would be greatly appriciated

  • Kartik

    Fantastic tutorial!!

    I have one question though. After writing the “Begin Simple AI” code and trying to run the program, I get a few errors.

    1. It says that the “touchesBegan” is undeclared (first use in this function). Is XCode meant to recognise this or can someone direct me as to what is the syntax to declared this?

    2. It says “Expected declaration or statement at end of input” and is pointing at the very last “@end” at the bottom of the coding (I’m in the iTennisViewController.m screen). Do I have to insert @end somewhere else?

    Thanks a lot everyone!!

  • http://topofstack.site40.net Sadi

    Hello everyone,
    Excellent tutorial for beginners of iphone game developers like me i will really appreciate if any one can give me suggestion for starting learning iGame development.

    Another ques : is there any more topics posted after this part-2 of itennis?

    Sadi
    CSE,BUET

  • Gray

    Hi, I am new to objective-c but have been playing around with Ruby for some while. when I try and compile I get many errors. As I said I’m new, so these errors don’t make sense to me. I will put the line of code with the error next to it as follows:
    iTennisViewController.h:

    @property(nonatomic,retain) IBOutlet NSInteger *gameState;
    error: property ‘gameState’ with ‘retain’ attribute must be of object type

    @property(nonatomic,retain) IBOutlet CGPoint *ballVelocity;
    error: property ‘ballVelocity’ with ‘retain’ attribute must be of object type

    iTennisViewController.m:

    @synthesize ball,raquet_green,raquet_yellow,P1_Score,Comp_Score,gameState,ballVelocity,tapToBegin;
    error: typer of property ‘gameState’ does not match type of ivar ‘gameState’ and error: typer of property ‘ballVelocity’ does not match typer of ivar ‘ballVelocity’

    If anyone can help, please do!
    Thanks in advance, Gray!

  • Gray

    Sorry, I didn’t see these last two:

    iTennisViewController.m:

    if(CGRectIntersectsRect(ball.frame,raquet_yellow.frame)) {
    error: expected identifier or ‘(‘ before ‘if’

    and the same for the second collision detecion.

    Thanks, Gray!

  • Linhnh

    Hello, thank you about tutorial.
    I am trying to do the same thing in landscape mode, but it couldn’t work well.
    The view bound and center position have been changed in landscape mode and I don’t know how to fix it.
    Can anyone tell me the solution.

    Thanks.
    Linh.

  • Max

    @Gray, change:

    @property(nonatomic,retain) IBOutlet NSInteger *gameState;
    @property(nonatomic,retain) IBOutlet CGPoint *ballVelocity;

    to:

    @property(nonatomic) NSInteger gameState;
    @property(nonatomic) CGPoint ballVelocity;

    For:
    error: expected identifier or ‘(‘ before ‘if’

    perhaps lacks or a ‘;’ or some parenthesis in some previous statement.

  • Marc

    I followed the instructions, but when I reset the game the ball moves faster and the collision detection goes away.

    Any ideas

  • Shanthan

    Hi,

    I am not ableto run this program … I an following your tut word by word… But my debugger says error of not declaring ‘center’ and ‘frame’

    please help!!! I love this tut and I wish I can get it done

  • ramalekshmi

    i am beginner.it’s an excellent tutorial.everything works well for me.at the beginning i got some errors. but it’s easily identified and rectified.the credit goes to the excellent tutorial

  • Brandon

    Hey i love this tutoral, would love to see one on a more complex game and possibly adding networking :P

  • Steven

    New to the Obj C. Did i miss something when i ran it prior to doing the scoring and reset sections the ball just shoots off the screen. Did i miss a collision detection for the boundaries of the court?

    Thanks and great tutorial. Like some others i am coming from a .NET background and with your descriptions I am getting past the architecture and the syntax and getting my head back to thinking out the logic.

    Steven

  • Opent

    Improve collision detection – When the ball hits the paddle, use some simple physics to make the speed of the paddle affect the speed (and direction) of the ball

    Improve on the AI – add some randomness to your AI, make it attempt to “predict” where the ball is going to be.

    Im new to objective-c so go easy on me.

    i tried both of these, but i couldn’t manage to do either. Well i kinda pulled of the making the speed go up using a timer but i tried to make the ball’s speed increase each time it collided with either of the racquets, this is how it looked like when i tried:

    if(CGRectIntersectsRect(ball.frame,raquet_yellow.frame)) {
    if(ball.center.y < raquet_yellow.center.y) {
    ballvelocity.y = -ballvelocity.y-1;
    NSLog(@"%f %f",ball.center,raquet_green.center);
    }
    }

    if(CGRectIntersectsRect(ball.frame,raquet_yellow.frame)) {
    if(ball.center.y < raquet_yellow.center.y) {
    ballvelocity.y = -ballvelocity.y-1;
    NSLog(@"%f %f",ball.center,raquet_green.center);
    }
    }

    When it bounced for the first time on the yellow(player) racquet it would go off as usual but it wouldn't collide with the green one and i just didnt find a way to make it work so if anyone could show me a way to solve the challenge id greatly appreciate it.

    I would also like to know a way to make the green racquet start moving in direction of the ball a lil before the center but i didnt know how to write it down.

    thanks for the great tutorials they've been lots of help and thanks in advance.

  • Aaron

    I seem to be having an issue with this game on the 3.2 platform. It compiles fine, but after loading there seems to be no response from the game.

    I can set breakpoints and see that it’s actually operating, but the “Tap to Begin” label never appears, and neither to the ball or racquets for that matter. It’s as though it’s stuck, but for the life of me I can’t figure out why.

    Thoughts?

    (Aside from this little hiccup, I have to say this tutorial was far better than the one in the iPhone programming for Dummies book!)

  • Eric

    Hi,

    Thanks for the great tutorial! It’s really a great help to beginner!

    I haven’t gone to the “Scoring State”, I just finished the “Begin Simple AI” but I got 1 error and failed to compile the program, I copy the message as follow:

    Checking Dependencies
    error: There is no SDK with the name or path ‘iphoneos2.2′

    I’m new to Xcode and I’m using version 3.1.4. I really want to move on the tutorial as this is my first time to build a game program so any help would be appreciated!

    Thanks in advance.

  • iPhone Dev.

    Hi,
    Xcode says: error: expected identifier or ‘(‘ before ‘if’ in: ViewController.m

    // Begin Simple AI

    if(ball.center.y <= self.view.center.y) {

    What's wrong?

    • Shubhojit

      I believe by now you would have sorted the mystery

      but still

      you need to put the

      //Begin Simple AI
      if stmt inside the -(void) gameLoop { }
      method

      then its all good

  • Shubhojit

    Hi! i am also getting the error

    Xcode says: error: expected identifier or ‘(‘ before ‘if’ in: ViewController.m

    // Begin Simple AI

    if(ball.center.y <= self.view.center.y) {

    What's wrong?

    plz reply

  • iPhone Dev.

    // Begin Simple AI
    if(ball.center.y <= self.view.center.y) {
    if(ball.center.x < racquet_green.center.x) {
    CGPoint compLocation = CGPointMake(racquet_green.center.x – kCompMoveSpeed, racquet_green.center.y):
    racquet_green.center = compLocation;
    }

  • iPhone Dev.

    Same problem again!

  • J. Cohen

    If the ball is 16×16 it won’t work. It took me an hour to figure out why the ball kept falling through my paddle, and after trying about 40 things, it turned out that resizing the ball to 18×18 fixed it. Strange, because the .png image is 16×16 in size.

    I wish I understood why. Strangest thing is it worked off the computer’s paddle, but just went right through mine.

  • Bill

    Most games now have the ability to use tilt instead of touch screen. Is there an easy way to incorporate this so when I tilt my iPhone the paddles move?

  • Bill

    Is it possible to create a link to tutorial part 1-4 so I can easily navigate thru this tutorial?

  • Arndt Bieberstein

    I just found a Bug in my Code.

    When you make the racquet too small the interaction method (CGRectInteractsRect…) never
    gets an intersection between racquet and ball.

    Buuuuut
    Very very very nice tutorial :)

  • Edmond

    Hi, i got an error “Method definition not in @implementation context”, and I’m new to programming and i don’t know what that means. Also u spelled racquet_yellow and raquet_yellow is there a difference. I’m not sure what i did wrong so i posted most of my coding from the “iTennisViewController.m”. Can you please help me out?

    //
    // iTennisViewController.m
    // iTennis
    //
    // Created by ed on 4/5/10.
    // Copyright __MyCompanyName__ 2010. All rights reserved.
    //

    #import “iTennisViewController.h”

    #define kScoreToWin 5
    -(void) gameLoop{// Begin Scoring Game Logic}
    if(ball.center.y = kScoreToWin)];
    }
    }
    if(ball.center.y > self.view.bounds.size.height) {
    computer_score_value++;
    [self reset:(player_score_value >= kScoreToWin)];

    #define kCompMoveSpeed 15
    - (void) gameLoop{ // Begin Simple AI}
    if(ball.center.y <= self.view.center.y){
    if(ball.center.x racquet_green.center.x){
    CGPoint compLocation = CGPointMake(racquet_green.center.x + kCompMoveSpeed, racquet_green.center.y);
    racquet_green.center = compLocation;
    }
    }

    #define kGameStateRunning 1
    #define kGameStatePaused 2

    #define kBallSpeedX 10
    #define kBallSpeedY 15

    @implementation iTennisViewController
    @synthesize ball,raquet_yellow,raquet_green,player_score,computer_score,gameState,ballVelocity,tapToBegin;

    -(void) gameLoop {
    if(gameState == kGameStateRunning) {

    ball.center = CGPointMake(ball.center.x + ballVelocity.x , ball.center.y +ballVelocity.y);

    if(ball.center.x > self.view.bounds.size.width || ball.center.x self.view.bounds.size.height || ball.center.y <0){
    ballVelocity.y = -ballVelocity.y;
    }
    } else {
    if(tapToBegin.hidden){
    tapToBegin.hidden = NO;
    }
    }
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(gameState == kGameStatePaused) {
    tapToBegin.hidden = YES;
    gameState = kGameStateRunning;
    }
    }

    - (void)dealloc {
    [super dealloc];
    [ball release];
    [raquet_green release];
    [raquet_yellow release];
    [player_score release];
    [computer_score release];
    [tapToBegin release];
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(gameState == kGameStatePaused) {
    tapToBegin.hidden = YES;
    gameState = kGameStateRunning;
    } else if(gameState == kGameStateRunning) {
    [self touchesMoved:touches withEvent:event];
    }
    }

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view];
    CGPoint xLocation = CGPointMake(location.x,raquet_yellow.center.y);
    racquet_yellow.center = xLocation;
    }

  • belbelts

    I think that this tutorial was very great. I’m now trying to make a game because of this tutorial, but I have a problem. In my game I need a lot of walls, so I made an array inside the game loop that creates the walls. I then ran the app and after a few minutes the game started to slow down.

    • belbelts

      what do I do? please comment

  • Balloonboy

    I am having problem with:

    Improve collision detection – When the ball hits the paddle, use some simple physics to make the speed of the paddle affect the speed (and direction) of the ball.

    What I’m trying to do is to make it so that:
    - Every time the ball hits the paddle it increases the speed a little.
    - The ball’s deflection angle determined by how far is the ball from the center of the paddle when it hits.

    Can anyone help me on these?

    • Harrison

      On collision compare the ball.center.x to the racquets.center.x and change the deflection and speed based on difference between them

  • Buru

    Hi, I’m having som toubles when trying to make the Game Mechanics: Scoring part.
    When I click ‘build’, en error appears in the line : (iTennisViewController.m)
    - (void) reset:(BOOL) newGame { (!) ‘RESET’ UNDECLARED (2)
    self.gameState = kGameStatePaused;
    …………………

    and at the end of the code, at the last line after all the dealloc part :
    ….
    }
    @end /!\ Incomplete implementation of class ‘ItennisViewController’ (2)

    Can somebody help me? Thanks all and thanks for the tutorial!

    • Buru

      ok! I’ve sloved the problem ^^ I had to change the ‘order’

      • Tom

        Buru, what was the solution to the final
        @end
        warning message, I am getting the same error,

        I am also getting a ‘touchesMoved’ undeclared error, ( whatever I place as the second section gets this undeclared error)

        Thank you so much, I would be very grateful if you could help with these problems,

        The Code is below,

        #import “iTennisViewController.h”
        #define kCompMoveSpeed 15
        #define kGameStateRunning 1
        #define kGameStatePaused 2

        #define kScoreToWin 5

        #define kBallSpeedX 10
        #define kBallSpeedY 15

        @implementation iTennisViewController
        @synthesize ball,racquet_yellow,racquet_green,player_score,computer_score,gameState,ballVelocity,tapToBegin;

        - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        if(gameState == kGameStatePaused) {
        tapToBegin.hidden = YES;
        gameState = kGameStateRunning;
        } else if(gameState == kGameStateRunning) {
        [self touchesMoved:touches withEvent:event];
        }

        -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        UITouch *touch = [[event allTouches] anyObject];
        CGPoint location = [touch locationInView:touch.view];
        CGPoint xLocation = CGPointMake(Location.x.racquet_yellow.center.y);
        racquet_yellow.center = xLocation;
        }

        -(void) gameLoop {
        if(gameState == kGameStateRunning) {

        ball.center = CGPointMake(ball.center.x + ballVelocity.x , ball.center.y + ballVelocity.y);

        if(ball.center.x > self.view.bounds.size.width || ball.center.x self.view.bounds.size.height || ball.center.y < 0) {
        ballVelocity.y = -ballVelocity.y;
        }
        // Crash detection CGRectIntersectsRect.

        if(CGRectIntersectsRect(ball.frame,racquet_yellow.frame)){
        if(ball.center.y < racquet_yellow.center.y) {
        ballVelocity.Y = -ballVelocity.y;

        }
        }
        if(CGRectIntersectsRect(ball.frame,racquet_green.frame)){
        if(ball.center.y < racquet_green.center.y) {
        ballVelocity.Y = -ballVelocity.y;
        } else {
        if(tapToBegin.hidden) {
        tapToBegin.hidden = NO;
        }
        }

        // Begin Simple AI}
        if(ball.center.y <= self.view.center.y){
        if(ball.center.x racquet_green.center.x){
        CGPoint compLocation = CGPointMake(racquet_green.center.x + kCompMoveSpeed, racquet_green.center.y);
        racquet_green.center = compLocation;
        }
        }
        // Begin Scoring Game Logic}
        if(ball.center.y = >= kScoreToWin)]:
        }

        if(ball.center.y > self.view.bounds.size.height) {
        computer_score_value++;
        [self reset:(computer_score_value >= kScoreToWin)];
        }

        -(void)reset:(BOOL)newGame{
        self.gameState = kGameStatePaused;
        ball.center = self.view.center;
        if(newGame) {
        If (computer_score_value > player_score_value) {
        tapToBegin.text =@”Computer Wins”;
        } else {
        tapToBegin.text =@”Player Wins!”;

        }
        computer_score_value = 0;
        player_score_value = 0;

        } else {
        tapToBegin.text = @”Tap to Begin”;
        }
        player_score.text = [NSString stringWithFromat:@"%d", player_score_value];
        computer_score.text = [NssString stringWithFromat:@"%d",computer_score_value];
        }

        // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
        - (void)viewDidLoad {
        [super viewDidLoad];
        self.gameState = kGameStatePaused;
        ballVelocity = CGPointMake(kBallSpeedX,kBallSpeedY);
        [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(gameLoop) userInfo:nil repeats:YES];
        }

        /*
        // Override to allow orientations other than the default portrait orientation.
        - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
        }
        */

        - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning]; // Releases the view if it doesn’t have a superview
        // Release anything that’s not essential, such as cached data
        }

        - (void)dealloc {
        [super dealloc];
        [ball release];
        [racquet_green release];
        [racquet_yellow release];
        [player_score release];
        [computer_score release];
        [tapToBegin release];
        }

        }
        }
        }
        }

        @end

  • Ehab Amer

    I’ve figured out why sometimes the ball would fall through the paddle, its not that the intersection doesn’t happen but its because that sometimes the first intersection happens WHEN the ball’s center is already behind the paddle.

    there r 3 ways to fix this :)

    1- increase the size of the ball, as already mentioned by “J. Cohen”
    2- slow down the ball on the Y axis

    (those 2 solutions make the intersection happen before the ball’s center passes the paddle)

    3- just remove the center checking condition and change the direction directly on collision (which i don’t prefer)

  • shus

    how do i get the exact dimensions of the object other then a square.

  • MAT

    Just something I noticed with the initial code. While the collision with green racquet works, yellow one always misses the ball. By decreasing kBallSpeedY constant from 15 to 10, then the skipped pixels are caught with the ball’s and racquet’s boundary every time.

  • alex

    to sort out your problems with collision detection: if speed of ball is greater than ballsize+paddlesize it will not detect collision.

    solution:
    check for collisions along the _path_ of the ball from current position to next position. if collision happens set ball to point of collision and change velocity.

  • Pingback: iTennis – iPhone Game Tutorials – iPhone App Academy

  • TessoMC

    Im having the strangest problem..
    When i hit build and go, it all works fine, till the simulator launches the app, it show the itennis loading screen, and then… just quits the game.

    Any thoughts?

    • Noah

      I’m having the same problem here. I have no idea what is causing this. When I run debugging, it says “GDB: Program received signal SIGABRT.”

    • Danny Brewski

      Same problem with game quitting after loading screen. I did a little debugging and eventually found out the view wasn’t connected to file’s owner. Fix: double click iTennisViewController.xib to open interface builder, go to view connections tab. Make sure “view” is connected to “file’s owner” If it isn’t, then drag from new referencing outlet to file’s owner and then select view to make the connection. Good luck.

  • Gio

    There is an error I’m getting with the player movement, it says “Request of member “view” in something not a structure or union” on the line with CGPoint location. can anyone help?

  • jorge

    hi me puedes enseñar a como poner el score cuando el personaje del juego se mueve tiene que dar puntos en el escore deacuerdo a cuanto se mueve puede obtener un puntaje
    GRacias
    espero tu respuesta

  • Pingback: App development per iOS, i tutorial - TheAppleLounge

  • Philipp

    Hi, i’ve got a problem with the collosion, if the first “goal” was reached, the ball fall through the racket of the computer.. :(

    (Sorry for my bad english, i am german..)

  • Philipp

    i’ve found the problem, my rackets were to short..
    But, it’s the BEST tutorial for iPhone Developing EVER!

  • Aaron Trahan

    This Tutorial is awesome!

    I did notice that when the ball “hit” the sides (x) of the game screen it looks like half of the ball leaves the screen.

    This is because the collision detection on the ball is done from the center and does not account for the width of the ball.

    I modified the code slightly to account for this.
    I estimated the radius of the ball (16×16)pixels to be 8 pixels.

    add to iTennisViewController.m

    #define kBallRadius 8
    .
    .
    .

    inside GameLoop

    // collision detection for the sides
    if(ball.center.x + kBallRadius self.view.bounds.size.width || ball.center.x – kBallRadius < 0) {
    ballVelocity.x = -ballVelocity.x;
    }

    Thank you
    Aaron

  • http://dannyquinn.co.uk Dan

    cool tutorial, just what I was looking for. Thanks.

  • Pingback: Blog,Forum,Music,Download,Photos,Video,Social Network || WhoWhatWhich.Com » Blog Archive » icodeblog game loop

  • Ben

    I found the problem with the ball bouncing above the green paddle instead of scoring. I added kBallRadius where I shouldn’t have. Whoops.

    Still working on the rest…

  • Momo

    Not sure I understand what stmt is.. can someone simplify this slightly?
    I’m having a much too similar problem here as well.

  • Bradley Buckland

    i actually have the opposite problem will bounce off my paddle but not comp

  • http://pulse.yahoo.com/_FRRIXZN536OK3KTH5KNH3LKBD4 Jesica Wills

    Thats very very nice post. Thanks for sharing the iPhone game programming information. Regards.

  • Bz_mortalgrip

    Thanks a lot for this tutorials!

    And a thing that may be helpful for other users:
    Such collision detection may cause a following bug – so far as our ball centre moving in a discrete way (Y-axis with a kBallSpeedY set to 15: 0, 15, 30, 45 etc.); raquets’ .png has height of 5px, and half of ball .png height is 8px. 15px – 8px = 7px. So you can get a situation when ball ‘steps over’ a raquet and no collision detected. This can be repaired by changing the ball Y-speed to a lesser value.

    Be careful =)

    • JB

      Hi, I noticed this bug when testing but I don’t understand very well the actual “bug”,  can you please explain me the heights issue?

      • JB

        I also have another problem, sometimes te ball hits the score bounds but it simply bounces and the game continues, no score detected.

  • Maheen Khalid

    Hey, First of all Thanks for the tutorials. I was looking for some resource and couldn’t find better than this.

    I am having a small problem. Up to this point when I run the code, the application exits immediately. Can you suggest what I am I doing wrong? I am following your code from A-Z. No additions or subtractions from my side.

    Thanks in advance.
    Maheen

    • Asda

      This was happening to me, and I had to fix my timer. Check your NSTimer letter for letter with his.

  • Cédric

    Thanks a lot for yours clever tutorials and this website.

    I have a question : I’ve just started to try to learn the iOS development. So, I have the latest SDK installed.

    When I launch this game, with the iPad SDK (4.3), the app launching and is “squeezed” by a white screen.
    And when I try to understand with your source, I cannot change the path of UIKit and Core.frameworks, which are missing apparently :(

    Is there anyone to help me ?

    Thanks a lot

    Cédric

  • Vikas Shanbhogue

    Hey .. This was a great tutorial .. Very well explained.
    I’m a programmer but have had a problem with how to structure games and this helped a lot.

     I noticed a problem with your code, let me know if anyone else faced this issue. 

    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px}
    p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #401a7f}
    p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #508187}
    p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #d0271c}
    p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo}
    span.s1 {color: #000000}
    span.s2 {color: #bb23a0}
    span.s3 {color: #508187}
    span.s4 {color: #733aa7}
    span.s5 {color: #3523d5}
    span.s6 {color: #401a7f}
    span.Apple-tab-span {white-space:pre}

    if (CGRectIntersectsRect(ball.frame, racquet_yellow.frame)) 
    {if (ball.center.y < racquet_yellow.center.y) 
    ballVelocity.y = – ballVelocity.y;}}

    So you explained the purpose of having ball.center.y < racquet_yellow.center.y. A problem I faced was that when the ball was going back in an upwards direction it would intersect with racquet_yellow.frame and meet the second if condition and keep moving back and forth. I faced the same problem with the green racquet. A simple fix is as follows:

    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px}
    p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #401a7f}
    p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #508187}
    p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #d0271c}
    p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo}
    span.s1 {color: #000000}
    span.s2 {color: #bb23a0}
    span.s3 {color: #508187}
    span.s4 {color: #733aa7}
    span.s5 {color: #3523d5}
    span.s6 {color: #401a7f}
    span.Apple-tab-span {white-space:pre}

    if (CGRectIntersectsRect(ball.frame, racquet_yellow.frame)) {
    if (ball.center.y 0) {
    ballVelocity.y = – ballVelocity.y;
    }
    }This ensures that the only time the ball gets deflected is when the ball is moving towards the yellow racquet and not when it is moving away from it.Similarly for the green racquet’s if condition I would add “&& ballVelocity.y < 0 ". I did not watch your video but an additional note:  To ensure that frames intersect, I would increase the height of both racquets a little (only if they don't intersect on both sides).I hope this helped rather than confused people. Also let me know if there was an easier fix! 

    • Callum_holland

      Bit confusing but i figured it out, u fixed a huge problem iv been working on with the ball getting ‘stuck’ on the racquet, thanks man 

      • Vikas Shanbhogue

        No worries .. Yeah the formatting is weird because I copied it straight out of XCode .. 

        I don’t understand why I can’t edit my comment.. 

  • Vikas Shanbhogue

    Sorry about the messy comment .. I don’t know how to edit it.

  • Joe Griffin

    Thanks for the iphone game development. With the Apple phone’s extreme popularity, this is definitely a good place for those interested in the field to start out. 

  • http://www.iamsamrat.com/ Samrat Mazumdar

    I want to keep a cross icon on iTennisViewController.xib and make it a UIButton and when it is pressed it will comeout of the game. How to do that?

  • Appsdeveloper2

    Very useful post. Thanks a lot.

canakkale canakkale canakkale balik tutma search canakkale vergi mevzuati bagimsiz denetim vergi mevzuati ozurlu engelliler