Subscribe ( RSS )

iPhone Programming Tutorials


 

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

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

Advertisement

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!

 

103 Responses

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

February 18th, 2009 at 4:43 pm

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

Koplimi Says:

February 18th, 2009 at 6:11 pm

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!

Chen Li Says:

February 18th, 2009 at 7:56 pm

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 Says:

February 18th, 2009 at 10:16 pm

@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 Says:

February 18th, 2009 at 10:20 pm

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.

Chintan Says:

February 19th, 2009 at 6:40 am

@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 Says:

February 19th, 2009 at 10:10 am

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 Says:

February 19th, 2009 at 12:21 pm

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 Says:

February 19th, 2009 at 1:05 pm

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 Says:

February 19th, 2009 at 1:08 pm

@Nasser

Decrease timerinterval to 0.02

set
kBallSpeedX 3
kBallSpeedY 5

much smoother

Chen Li Says:

February 19th, 2009 at 9:35 pm

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 Says:

February 19th, 2009 at 10:16 pm

@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.

Chintan Says:

February 20th, 2009 at 12:14 am

@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 Says:

February 20th, 2009 at 1:31 am

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

BerryMelong Says:

February 20th, 2009 at 2:08 am

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!

Matt Says:

February 20th, 2009 at 2:36 pm

Awesome dude, youre the shit.

Shaman Says:

February 20th, 2009 at 4:35 pm

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 Says:

February 21st, 2009 at 5:36 pm

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 Says:

February 23rd, 2009 at 4:59 am

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 Says:

February 23rd, 2009 at 5:09 pm

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 Says:

February 25th, 2009 at 11:13 am

@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 Says:

February 25th, 2009 at 11:17 am

Tags were stripped, the code is:

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

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

Brandon Says:

February 25th, 2009 at 4:57 pm

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 Says:

February 25th, 2009 at 10:31 pm

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

Mick D Says:

February 26th, 2009 at 6:50 am

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

Brian Says:

February 26th, 2009 at 2:42 pm

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.

guy tavor Says:

February 28th, 2009 at 3:59 am

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 Says:

March 1st, 2009 at 10:47 am

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.

Rush Says:

March 3rd, 2009 at 10:35 pm

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

jitesh61 Says:

March 5th, 2009 at 1:21 am

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 Says:

March 8th, 2009 at 10:16 pm

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 Says:

March 8th, 2009 at 10:18 pm

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 Says:

March 8th, 2009 at 11:06 pm

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 Says:

March 9th, 2009 at 12:28 am

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 Says:

March 9th, 2009 at 12:29 am

Mulligan:

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

Oh Dreamer Says:

March 9th, 2009 at 12:30 am

Fail :(

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

March 10th, 2009 at 11:13 pm

[...] iPhone Game Programming Tutorial Part 2- User Interaction, Simple AI, Game  [...]

Sameer Kumar Says:

March 11th, 2009 at 2:12 pm

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

great tutorial….your a legend!!!

Meta Says:

March 12th, 2009 at 4:22 am

Hy

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

rramnel Says:

March 15th, 2009 at 8:33 pm

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 Says:

March 16th, 2009 at 5:09 pm

Thanks a lot for this great tutorial !!!

Mike Says:

March 16th, 2009 at 8:46 pm

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

rabi Says:

March 17th, 2009 at 8:10 pm

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 Says:

March 18th, 2009 at 5:29 am

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

Chris Says:

March 18th, 2009 at 11:29 am

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.

Michael Says:

March 18th, 2009 at 4:18 pm

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 Says:

March 19th, 2009 at 10:12 am

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

Alex Says:

March 19th, 2009 at 9:49 pm

Hey does anyone know to improve the collision detection?

zKarp Says:

March 21st, 2009 at 10:39 pm

*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)

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

March 24th, 2009 at 12:36 pm

[...] 36. Game tutorial-2 [...]

LakshmiKanth Reddy Says:

March 27th, 2009 at 2:59 am

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

someone Says:

April 1st, 2009 at 5:05 am

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

Rafael Says:

April 6th, 2009 at 3:21 pm

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?

Mike Says:

April 7th, 2009 at 11:17 am

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

iPhone game development guide: On the go tutorial | iPhone Footprint Says:

April 14th, 2009 at 1:12 am

[...] the first part deals with the creation of different folders within the main project folder.  The second part talks about user interaction, Simple game AI, game logic etc.The third and the final part contains [...]

Bjorn Says:

April 15th, 2009 at 7:03 pm

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?

Stefan Says:

April 17th, 2009 at 6:12 pm

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 Says:

April 18th, 2009 at 4:23 pm

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 Says:

April 18th, 2009 at 5:31 pm

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.

Create Says:

April 24th, 2009 at 7:50 pm

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 Says:

April 26th, 2009 at 2:04 pm

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 Says:

April 26th, 2009 at 2:05 pm

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 Says:

April 26th, 2009 at 2:06 pm

sorry about the duplicate my comp was acting up

DcWHaT Says:

April 26th, 2009 at 3:06 pm

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 Says:

May 2nd, 2009 at 2:10 pm

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

Steve Says:

May 14th, 2009 at 4:58 pm

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 Says:

June 3rd, 2009 at 9:49 pm

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!

Merimim Says:

June 4th, 2009 at 12:25 am

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 Says:

June 4th, 2009 at 11:56 am

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 Says:

June 22nd, 2009 at 7:08 pm

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 Says:

June 26th, 2009 at 4:00 pm

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 Says:

June 30th, 2009 at 10:29 pm

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 Says:

July 1st, 2009 at 3:28 pm

@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 Says:

July 1st, 2009 at 5:07 pm

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 Says:

July 1st, 2009 at 5:14 pm

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 Says:

July 3rd, 2009 at 2:47 pm

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 Says:

July 16th, 2009 at 10:52 am

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 Says:

July 20th, 2009 at 6:12 pm

@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?

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

July 27th, 2009 at 8:58 am

[...] e “Bubi Devs”. La versione originale inglese del tutorial è disponibile a questo indirizzo: “iPhone Game Programming Tutorial, Part 2 – iCodBlog“. I meriti quindi relativamente alla versione inglese, sono del legittimo [...]

Jitesh Says:

July 31st, 2009 at 12:40 am

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

Cornelius Says:

August 11th, 2009 at 2:35 pm

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 Says:

August 13th, 2009 at 2:34 pm

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 Says:

August 13th, 2009 at 2:35 pm

Sorry forgot the escape characters for the html.

Changed less than to greater than for the detection.

Quick Post: iPhone Game Tutorials | Thomas Nicholson iPhone Developer Newbie Says:

August 19th, 2009 at 1:31 pm

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

Kevin Says:

August 23rd, 2009 at 1:24 pm

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 Says:

August 26th, 2009 at 6:27 am

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 Says:

October 6th, 2009 at 9:39 pm

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 Says:

October 19th, 2009 at 7:02 pm

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 Says:

October 20th, 2009 at 2:20 pm

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 Says:

October 20th, 2009 at 6:09 pm

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 Says:

November 25th, 2009 at 11:53 am

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 Says:

November 30th, 2009 at 5:16 pm

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 Says:

December 9th, 2009 at 7:01 pm

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!!

Sadi Says:

January 5th, 2010 at 1:48 am

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 Says:

January 6th, 2010 at 5:57 pm

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 Says:

January 6th, 2010 at 5:59 pm

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 Says:

January 14th, 2010 at 2:29 am

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 Says:

January 14th, 2010 at 12:10 pm

@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 Says:

January 19th, 2010 at 10:18 am

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

Any ideas

Shanthan Says:

January 19th, 2010 at 10:25 pm

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 Says:

January 20th, 2010 at 3:13 pm

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 Says:

January 25th, 2010 at 1:25 pm

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

Steven Says:

January 26th, 2010 at 4:24 pm

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

Leave a Reply