6th January 2009

“Dust” for iPhone

OK, this is still awaiting review, but should hopefully be out any day, so I’m going to start hyping it.

http://www.bit-101.com/dust/

My first full iPhone app. Open GL ES 10,000 particles at 60 fps and runs beautifully. $0.99. that’s $0.000099 per particle! What a deal! I’ll let you know when it’s ready for purchase.

posted in Objective C, iPhone | 13 Comments

6th January 2009

glRotatef… HELP!

I usually try to share solutions on this blog, but sometimes I just feel dumb and need some help. I've searched all over for this one, but I know some wicked smart people read this blog, so maybe they can help me.

So I am rendering some points in OpenGL ES on the iPhone and want to rotate them with touches. Swipe left/right to rotate on y axis, up/down on x axis. Simple. If you open up XCode and build a project from the OpenGL ES Application template, and then make the following changes, you'll have what I have...

1. in EAGL.h, add these vars:

C:
  1. CGFloat dx, dy;
  2.     CGPoint startPoint;

2. in EAGL.m, change the drawView method to the following:

C:
  1. - (void)drawView {
  2.    
  3.     // Replace the implementation of this method to do your own custom drawing
  4.    
  5.     const GLfloat squareVertices[] = {
  6.         -0.5f, -0.5f, -0.5f,
  7.         0.5f,  -0.5f, -0.5f,
  8.         -0.5f,  0.5f, -0.5f,
  9.         0.5f,   0.5f, -0.5f,
  10.         -0.5f, -0.5f, 0.5f,
  11.         0.5f,  -0.5f, 0.5f,
  12.         -0.5f,  0.5f, 0.5f,
  13.         0.5f,   0.5f, 0.5f
  14.     };
  15.     const GLubyte squareColors[] = {
  16.         0, 0, 0, 255,
  17.         0, 0, 0, 255,
  18.         0, 0, 0, 255,
  19.         0, 0, 0, 255,
  20.         0, 0, 0, 255,
  21.         0, 0, 0, 255,
  22.         0, 0, 0, 255,
  23.         0, 0, 0, 255,
  24.     };
  25.    
  26.     [EAGLContext setCurrentContext:context];
  27.    
  28.     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
  29.     glViewport(0, 0, backingWidth, backingHeight);
  30.    
  31.     glMatrixMode(GL_PROJECTION);
  32.     glLoadIdentity();
  33.     glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
  34.    
  35.     glMatrixMode(GL_MODELVIEW);
  36.     glRotatef(dx, 1.0f, 0.0f, 0.0f);
  37.     glRotatef(dy, 0.0f, 1.0f, 0.0f);
  38.     dx = dy = 0.0;
  39.    
  40.     glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
  41.     glClear(GL_COLOR_BUFFER_BIT);
  42.    
  43.     glVertexPointer(3, GL_FLOAT, 0, squareVertices);
  44.     glEnableClientState(GL_VERTEX_ARRAY);
  45.     glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
  46.     glEnableClientState(GL_COLOR_ARRAY);
  47.    
  48.     glPointSize(4.0f);
  49.     glDrawArrays(GL_POINTS, 0, 8);
  50.    
  51.     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  52.     [context presentRenderbuffer:GL_RENDERBUFFER_OES];
  53. }

This adds a few points to make a cube, colors all the points black, and renders them as points. And rotates them around based on the dx, dy values.

3. Add these two methods to EAGL.m:

C:
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     UITouch *touch = [touches anyObject];
  3.     startPoint = [touch locationInView:self];
  4. }
  5.  
  6. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  7.     UITouch *touch = [touches anyObject];
  8.     CGPoint point = [touch locationInView:self];
  9.     dx = point.y - startPoint.y;
  10.     dy = point.x - startPoint.x;
  11.     startPoint = point;
  12. }

This just calculates dx, dy as the distance the touch moved.

Now this all works fine for starters. Swipe left/right or up/down and the cube moves correctly. But rotate it down 90 degrees and then swipe horizontally and the thing rotates in the z axis. I know, I know, it's still rotating on the local y axis, but that's not what I want. I just want it so that no matter what the orientation, when I drag up and down, it looks like I'm dragging it that way, and same for left/right. I've hit a brick wall with this one. Some combination of push/pop matrix? mult matrix? Do I need to use quaternions? Am I just screwed? My brain is locked up.

Oh, and yes, I know how glRotatef works - rotate n degrees around a vector defined by the last three params. I've tackled it that way too, to no avail. I think I've exhausted every bright idea I've had on this one.

posted in Objective C, iPhone | 6 Comments

5th January 2009

CoreSWF: AS3 in XCode

So for the last two weeks, I've been exclusively using XCode, doing Objective-C iPhone stuff. Haven't even opened Flex Builder. Back to work today and back to Flex Builder. My fingers are tripping over themselves trying to figure out shortcuts. The two environments are similar enough - yet different enough - to cause major brain cramps. I was just wondering if there was a way to code AS3 in XCode. I mentioned my pain on Twitter, and got a reply about this project called CoreSWF.

Can't vouch for this one yet, as I just heard about it and haven't had a chance to try it out, but this looks pretty interesting:

http://enefekt.com/sansbrowser/2008/07/28/core-swf-flexas3-for-xcode/

Google Code site:

http://code.google.com/p/coreswf/

I'm sure I'll be trying it out, and will post my feedback.

And yes, Sam Robbins, I remember you rigged together something for ActionScript in XCode way back when, when you were on a Mac and I was a PC guy. But that was 4-5 years ago (God, has it been that long???) Flash 7, AS2, some ancient version of XCode. I imagine that would need some major work to get functional again.

posted in ActionScript | 5 Comments

31st December 2008

2008: My year in review.

For the last few years, I've done a year-end post examining the past year and looking forward to the new.

2008 was very good to me.

Personally, I lost 36 pounds and for the first time in 8 years dipped below 200 pounds. I slipped a bit over the holidays, so have some make up to do, but confident I can get back to it.
Spoke at three conferences, FiTC Toronto in April, FlashForward San Francisco in August, and Flash on the Beach in Brighton in September. Conceived, contracted, wrote, and saw in print my next book, Advanced ActionScript Animation. Started www.artfromcode.com and put up a few hundred pieces of generative art. Launched the new 25 Line ActionScript Contest and had the first monthly contest, with over 90 entries and the winner receiving a CS4 Master Suite. Revived Wicked Pissah Games and launched Gravity Pods 2. Started learning Objective C 2.0 and iPhone development, working on a port of Gravity Pods for the iPhone. Spent two weeks in Japan. Bought a house and a car. Just before the start of the year, started working at Infrared5, which I can say without reservation is the best job I've had. Saw my daughter Kris start Kindergarten. There's probably some other stuff, but that's what comes to mind.

Yeah, pretty good year. In fact, when I listed it out like that, I gave myself a nice ego boost. Very good year.

So, where from here?

Who knows? The one thing I'm really excited about now is Objective C and iPhone / Mac development. Once you get over the initial hurdles, it's a lot of fun learning a new language, with all kinds of new capabilities. It's fun applying what I've learned in my years of doing Flash to a whole new platform, seeing the similarities and differences, and getting a deeper understanding of things when you have to do them in 10 steps instead of 1 or 2. Even my company, Infrared5 has some iPhone projects in the works, which is great. One thing I miss, coming from the world of Flash, is the immediacy of publishing. In Flash, I can write some code, test movie, upload it to a server, blog about it and the whole world can see it. With iPhone apps, the process is a BIT more complicated. :)

Other than that, no big plans for 2009. No job changings, house buyings, or book writings planned, but you never know about the books. I'll be speaking at FiTC Amsterdam in February, and Flash on the Beach Brighton later in the year. No commitments to conferences outside of that. And I'll most likely spend another week or two in Japan at my wife's mother's place in the mountains. Kris will start first grade. I hope to get down to my target weight of 180. Plan to continue on with Art from Code and 25 Lines for sure.

But you never know. Art from Code was a spur of the moment idea one Sunday morning. The idea for 25 Lines came into my head in September when I was preparing for my FlashForward talk on "putting the Flash back in Flash". It was really only about 3-4 weeks ago that I decided to get Gravity Pods 2 done, and my iPhone development kick sprung from that. So ideas can come up quickly and change everything. Can't really plan for that stuff, but I'm sure a few other cool opportunities like those will spring up. So I look forward to see what surprised 2009 will bring.

posted in General | 8 Comments

30th December 2008

iGravityPods progress

This is going better than I thought. Did a bunch of refactoring last night, and added gravity pods themselves today.

posted in iPhone | 4 Comments

30th December 2008

Gravity Tutorial for iPhone, Part 5

For the final installment in this series, we'll add accelerometer support to the ball, allowing you to tilt the device to change the direction of "down". Note, although you can rotate the device in the iPhone simulator, this does not simulate acceleration. The only way you'll be able to see this in action is on a physical device. This means that you'll have to pay $99 sign up for and be accepted to the iPhone Developer program, and figure out how to provision apps to your device. I'm not going to cover that here, so I'll assume that you've figured that out on your own. OK, let's jump in.

So far, we have gravity in the ball, affecting its y velocity. If we know which way the device is tilted, we can change that to affect the velocity on the x axis as well, proportional to the degree of tilt. For example, if you tilted the device 90 degrees to the left, gravity should only affect the x velocity. If you turn it upside down, it will affect only the y velocity again, but in the opposite direction. In most cases, it will not be exactly straight, so there will be some x velocity and some y, proportional to the angle of tilt.

To respond to acceleration, we need to do three things:

1. Have a class specify the UIAccelerometerDelegate protocol. This is similar to implementing an interface in ActionScript. But less strict. It's telling the application that you expect this class to respond to acceleration, and it may have some of the methods associated with this protocol. But unlike an interface, you are not required to implement all or even any of the methods.

2. Set the class as a delegate for accelerometer events. Think of this as adding an event listener.

3. Create a method to respond to the events. Here is where you will change gravity.

OK, step 1, specifying the protocol. We'll have the Ball class do this directly, as that's where gravity is. You just put the protocol name in angle brackets after the class name and and super classes, like so:

C:
  1. @interface Ball : NSObject <UIAccelerometerDelegate> {
  2. ...

I'm not really sure what this does to be honest, as it seems you can be a delegate without specifying the protocol (although you will get a warning), and you can specify the protocol without being a delegate. But you're supposed to do it, so do it. :)

Step 2. Set self as a delegate. We'll do that in the init method in Ball.m:

C:
  1. - (id) init
  2. {
  3.     self = [super init];
  4.     if (self != nil) {
  5.         position = CGPointMake(100.0, 100.0);
  6.         velocity = CGPointMake(5.0, 5.0);
  7.         radius = 20.0;
  8.         color = [UIColor greenColor].CGColor;
  9.         bounce = -0.9f;
  10.         gravity = 0.5f;
  11.         dragging = NO;
  12.         [[UIAccelerometer sharedAccelerometer] setDelegate:self];
  13.     }
  14.     return self;
  15. }

sharedAccelerometer is a class (static) property of the UIAccelerometer class, I assume it's like getInstance of a Singleton. You are calling setDelegate on that object, passing self (this). Simple enough.

Step 3. Create a method which will be called on acceleration. Again, right in Ball.m:

C:
  1. - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
  2.     NSLog(@"x: %f, y: %f", acceleration.x, acceleration.y);
  3. }

You don't need to declare this, as you specified the protocol, which, come to think of it, is probably why you set the protocol.

The method is called accelerometer and passes a pointer to a UIAccelerometer object, and a pointer to a UIAcceleration object. It's this last one we're interested in, as that will tell us the amount of tilt.

Here I've just put in a log statement so you can see that it's working. The acceleration parameter passed in will contain x, y, and z properties, which will range from -1.0 to +1.0. We're only interested in x and y. x will be -1.0 when the device is tilted 90 degrees to the left, 0.0 when it's upright and +1.0 when tilted to the right. Likewise, y will be -1.0 when upright, and vary towards 0.0 on either side, and then to +1.0 when the device is upside down.

So, rather than a single value for gravity, we'll need x and y values for gravity. We can store these in a point object. Declare it in Ball.h:

C:
  1. CGPoint acceleratedGravity;

Leave gravity there, as that will affect the overall strength of gravity and generally stays the same. This new variable will change constantly according to tilt.

You can also initialize this in the init method:

C:
  1. acceleratedGravity = CGPointMake(0.0, gravity);

Note that the x value is initialized to 0.0 and y to gravity, indicating no rotation.

Now we can change the acceleration method to alter this variable:

C:
  1. - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
  2.     acceleratedGravity.x = acceleration.x * gravity;
  3.     acceleratedGravity.y = -acceleration.y * gravity;
  4. }

Note that the y value is reversed, otherwise the ball would fall "up".

Finally, we just need to alter the update method in Ball.m to utilize acceleratedGravity instead of just gravity:

C:
  1. - (void)update {
  2.    
  3.     if(dragging) return;
  4.    
  5.     velocity.x += acceleratedGravity.x;
  6.     velocity.y += acceleratedGravity.y;
  7.     position.x += velocity.x;
  8.     position.y += velocity.y;
  9. ...

And that's it! Pretty simple actually. Now you tilt the device and the ball will always fall "down". It will settle in a corner, or on the "top" of the device, or whatever direction is down. Amazing just how easy that was. Less than 10 lines of code in all.

And that brings us to the end of this series. Bear in mind that I'm a beginner at this stuff, and was writing this for my own selfish reasons - to learn the language and drill it into my head. I've already seen several places where the code in this project is not up to snuff at all. I may go back and correct it at some point, but I'll just say for now to take what I've written here as a jump start. It will get you up and running, but you really need to learn more about the right way to do things, like I am already doing. And if you find something that indicates I did something incorrectly, it's probably right.

posted in Objective C, iPhone | 4 Comments

29th December 2008

iGravityPods Video

Not the best quality, and for some reason PhotoBooth likes to record mirror images. But you get the idea of where it's going. Not bad for a couple days.

posted in iPhone | 9 Comments

29th December 2008

iGravityPods

Not sure what the actual name will be, but I am working on an iPhone / iPod Touch version of Gravity Pods. It's going pretty well considering I just started yesterday. Here's a screenshot:

igravitypodspreview

It's quite a challenge creating a workable user interface with such little screen real estate. But I've got some decent ideas. Those buttons on the right fade in only when you touch the gun, and fade out when you release it. They allow you to rotate the gun in 1 degree or 0.1 degree intervals. And the GO! button shoots. You can also drag to aim the gun with your right hand when you have it selected with the left hand. Feels pretty natural and ergonomic to me.

Next up, shooting the bullet, then a target, pods, and walls. I might be looking for some beta testers in the next month or so.

posted in iPhone | 6 Comments

29th December 2008

25 Line ActionScript contest entries source posted

http://www.25lines.com/?p=168

Now you have 80-something files of cool effects, inspiration, and horrible coding practices to learn from. :)

Next contest starts in a few days.

posted in ActionScript | 1 Comment

28th December 2008

Gravity Tutorial for iPhone part 4

I have to admit, I'm writing these things for purely selfish reasons. Same reason I write books. You learn WAY more by teaching. If you think you are getting some knowledge from reading these, realize that I am getting SO much more knowledge and understanding from writing them. :)

Now let's use one of the really neat features of the iPhone, that lovely touch screen. There are three methods we can add to our view controller to listen for touch events: touchesBegan, touchesMoved, and touchesEnded. It inherits these from the UIResponder class, so you don't need to declare them, just implement them. Note that UIView is a UIResponder too, so you could put touches methods in there, but it makes more sense in this app to have it in the view controller, where we have a constant reference to the ball. To start with, add these method to GravityTutorialViewController.m:

C:
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     NSLog(@"touches began");
  3. }
  4.  
  5. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  6.     NSLog(@"touches moved");
  7. }
  8.  
  9. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  10.     NSLog(@"touches ended");
  11. }

Open up your console and run the app and see that it does indeed respond to these actions.

You see that each method gets passed an NSSet of touches as a first parameter. An NSSet is "an unordered collection of distinct elements". Realize that the touch screen is multitouch, so a touch event may have several simultaneous touches going on - one for each finger. Here of course, we're really only concerned with a single touch. We get that by calling the anyObject method of the set. This will give us a single UITouch object. We can then call the locationInView method of the UITouch object to get a CGPoint showing the x, y location of that touch.

We'll store this point in a class variable, but let's actually make two, one for the last touch, and one for the current touch, so we can track movement and velocity. Declare these two in the view controller's .h file:

C:
  1. #import <UIKit/UIKit.h>
  2. #import "Ball.h"
  3.  
  4. @interface GravityTutorialViewController : UIViewController {
  5.     Ball *ball;
  6.     CGPoint lastTouch;
  7.     CGPoint currentTouch;
  8. }
  9.  
  10. - (void)onTimer;
  11.  
  12. @end

We don't need to make properties or synthesize these, as they are only used in the class. Now, we can grab the current touch location in each of the touch methods. Actually, we don't really need it in touchesEnded, as you'll see in a moment.

C:
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     UITouch *touch = [touches anyObject];
  3.     currentTouch = [touch locationInView:self.view];
  4. }
  5.  
  6. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  7.     UITouch *touch = [touches anyObject];
  8.     currentTouch = [touch locationInView:self.view];
  9. }

First off, in touchesBegan, we need to see whether or not the user has touched the ball. Unlike in ActionScript where you have handy mouse down and mouse up and click events that tell you whether or not you clicked on something, here you have to do it all by hand. We'll just check the currentTouch location's distance from the ball's location. If that is less than the ball's radius, the user touched the ball.

Oddly enough, there doesn't even seem to be a built in distance method here, so we have to roll our own for that too. No problem though, we know Pythagorus quite well, right? A squared plus B squared and all that.

C:
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     UITouch *touch = [touches anyObject];
  3.     currentTouch = [touch locationInView:self.view];
  4.     CGFloat dx = currentTouch.x - ball.position.x;
  5.     CGFloat dy = currentTouch.y - ball.position.y;
  6.     CGFloat dist = sqrt(dx * dx + dy * dy);
  7.     if(dist <ball.radius) {
  8.         ball.velocity = CGPointMake(0.0, 0.0);
  9.         ball.dragging = YES;
  10.     }
  11.     lastTouch = currentTouch;
  12. }

So, if the user has touched the ball, what do we do? First of all, we kill the velocity by setting it to 0.0. That way if he touches and releases it without moving, it will just drop to the floor, rather than continue on the way it was going.

Then we set the ball's dragging property to YES (true). I know, that property doesn't exist yet, but we'll be adding it soon. But first, let's wrap up the touch stuff. Finally, in this method, we assign the currentTouch to lastTouch so we know how far it moved, if and when it moves.

In touchesMoved, we need to move the ball to the current touch. Simple enough. We also need to update the velocity by subtracting the lastTouch from the currentTouch. In other words, how far did the touch move since last time? Well that's the ball's current velocity. If the user releases it, that's how fast it should go, and in what direction.

C:
  1. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     UITouch *touch = [touches anyObject];
  3.     currentTouch = [touch locationInView:self.view];
  4.     ball.position = currentTouch;
  5.     ball.velocity = CGPointMake(currentTouch.x - lastTouch.x, currentTouch.y - lastTouch.y);
  6.     lastTouch = currentTouch;
  7. }

Finally, in touchesEnded, we just tell the ball we are not dragging it anymore.

C:
  1. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  2.     ball.dragging = NO;
  3. }

Now, onto this dragging stuff. We'll declare a BOOL variable in Ball.h and make it a property.

C:
  1. @interface Ball : NSObject {
  2.     CGPoint position;
  3.     CGPoint velocity;
  4.     CGFloat radius;
  5.     CGColorRef color;
  6.     CGFloat bounce;
  7.     CGFloat gravity;
  8.     BOOL dragging;
  9. }
  10.  
  11. @property CGPoint position;
  12. @property CGPoint velocity;
  13. @property CGFloat radius;
  14. @property CGColorRef color;
  15. @property CGFloat bounce;
  16. @property CGFloat gravity;
  17. @property BOOL dragging;
  18.  
  19. - (void)update;
  20. - (CGRect)getRect;
  21.  
  22. @end

And synthesize it in Ball.m:

C:
  1. #import "Ball.h"
  2.  
  3.  
  4. @implementation Ball
  5. @synthesize position;
  6. @synthesize velocity;
  7. @synthesize radius;
  8. @synthesize color;
  9. @synthesize bounce;
  10. @synthesize gravity;
  11. @synthesize dragging;
  12. ...

Finally, in the update method, we check to see if we are dragging the ball or not. If so, we just return. We don't want to do all that gravity and bouncing nonsense. We just want to let the user drag the ball.

C:
  1. - (void)update {
  2.    
  3.     if(dragging) return;
  4.    
  5.     velocity.y += gravity;
  6.     position.x += velocity.x;
  7.     position.y += velocity.y;
  8.    
  9.     if(position.x + radius> 320.0) {
  10. ...

That if statement up at the top is the only change to this method.

Now, we are about half way there. Oh, no, wait, we are done! Yup. Run the application (I still want to say "Test Movie" but I'm working on it) and you should have a dragable, throwable, bouncable, thoroughly lovable ball on your iPhone, iPod, or at very least, simulator.

Next up... accelerometer!

posted in Objective C, iPhone | 5 Comments

Who is reading BIT-101?