260 likes | 374 Views
Moving Image – 1st iPhone programming exercise. CSE 391 Fall 2012 Tony Scarlatos. Define a UIImageView. Create a Single View Application. Save the project folder to your desktop (I named my project “ Wolfie ”).
E N D
Moving Image –1st iPhone programming exercise CSE 391 Fall 2012 Tony Scarlatos
Define a UIImageView • Create a Single View Application. Save the project folder to your desktop (I named my project “Wolfie”). • In the header file (WolfieViewController.h in the Wolfie directory) define a UIImageViewobject. Your code should look like this: #import <UIKit/UIKit.h> @interfaceWolfieViewController : UIViewController { } @property (nonatomic, strong) IBOutletUIImageView *imageView; @end 3. Save the Xcode project.
Add a resource and build the interface • Find an image and make it 160 pixels square. Create a Resources folder in your project window, and be sure to check the checkbox to copy it to the destination folder. • Click the .storyboard file to launch Interface Builder. Drag a UIImageView object from the Library to the View window. Use the Image View Size tab in the Inspector to size the image object to 160 X 160. • Select Wolfie View Controller in the Document window, and connect the Image View Outlet from the Inspector’s connections icon to the image view object in the View window. • Click on the image object to highlight it and select the Attributes inspector. In the property field named Image, use the dropdown list to select the image file you imported into Resources in Xcode. (My file was SBUsports.gif). • Save your work in IB. If you select Run in Xcode you should see your image in the iPhone Simulator.
Touch-up • My image has a white background, but the default background in IB is gray. I could change that in the Inspector by selecting the View window (not the image object) and choosing a different color for the background from a dropdown list in the Attributes tab. (If the image has a transparent background it will be supported in IB, and this could be quite useful.) • However, we could also set the background color in code in the ViewController.mfile in Xcode. You’ll have to add this line to the viewDidLoadmethod: self.view.backgroundColor=[UIColorwhiteColor];
Either way, it’s OK… Animated UIView image object with alpha background UIView image object with solid background
Creating motion based onrandom origins • Our animation will start in one corner of the screen and move to another corner. The origin will be a randomly selected corner. • We will generate a pseudorandom number (since it is generated by a fixed algorithm, if you generate it several times, you’ll get the same sequence of numbers). So we will seed the algorithm, and then start generating random numbers. We’ll seed it only once, before we generate any numbers. We will do this in the viewDidLayoutSubviewsmethod. • To pick a random number for the seed we will use the the current date and time, so if we start the program at two different times we will get two different seeds.
Seeding the randomnumber generator • The NSDate class has a class method named date that returns an NSDate object representing the current date and time. We’ll call that object’s timeIntervalSince1970 method, which will give us the number of seconds since midnight, January 1, 1970 (considered by many languages to be the epoch, or beginning of time). • The following statement is a common way to seed a random number generator: srand([[NSDatedate] timeIntervalSince1970]);
Multi-threaded programming • The iPhone’s CPU can’t actually do two things at the same time, but it can execute a thread for a few nanoseconds, and then a second thread, and a third, and so on, giving the illusion of simultaneous execution. • Objective-C supports multi-threaded programming. We spawn a separate thread of execution to perform a task. We might have a thread that runs a clock, another thread that moves objects around the screen, and another thread that counts from 1 to 100.
Setting a timer • The NSTimer class has a method we can use to spawn a separate thread of execution. We pass to this method: • A time interval • A reference to an object • A method to be called when the time interval passes • userInfo (pass nil) • A NO or a YES • If we pass NO for the last argument, the timer will call the specified method only once, after the time interval passes the first time. If we pass YES the timer will call the specified method repeatedly each time the interval passes.
Timer, continued • The object that we pass as the second argument is the object on which the method operates. Typically this method is defined in the current class, and we pass self as the second argument. • In this single line of code we set a timer that calls our move method repeatedly (every 1.6 seconds): [NSTimerscheduledTimerWithTimeInterval:1.6target:selfselector:@selector(move) userInfo:nilrepeats:YES];
Timer, final • Since we want the move method to be called immediately (not after the 1.6 second delay) we call it ourselves: [selfmove]; • So now all together the viewDidLayoutSubviewsmethod is: -(void)viewDidLayoutSubviews { srand([[NSDatedate] timeIntervalSince1970]); [NSTimerscheduledTimerWithTimeInterval:1.6target:selfselector:@selector(move) userInfo:nilrepeats:YES]; [selfmove]; }
Picking a random number • We want to pick a random number representing the four corners of the screen (i.e. 0, 1, 2, or 3). Each number corresponds to the origin of the animation in either the top left, top right, bottom right, or bottom left corner. • The rand() function, however, will pick a random integer between 0 and 2 billion, so we need to limit its output. We will use the modulus operator which means “divide and take the remainder” to do this. • The following line of code calls the rand() function to get a random number, then divides by 4, and takes the remainder (which has to be 0, 1, 2, or 3). NSIntegerran=rand()%4;
Positioning the image • UIView objects have a property called frame which indicates the location and size of the object. We want to vary the left and top pixel positions. • The top left corner of the view is 0,0 (x,y). Top right is 319,0. Bottom left is 0,479. Bottom right is 319, 479. We can use negative values for x and y to position the image off-screen. • We will declare 4 variables: left, top, gotoX, and gotoY. We will use 4 if statements to set values for those variables.
The positioning code The code below is in one continuous column in Xcode starting with NSInteger left; NSIntegerleft; NSInteger top; NSInteger gotoX; NSInteger gotoY; if(ran==0) { left=-self.view.frame.size.width/2; top=-self.view.frame.size.width/2; gotoX=self.view.frame.size.width; gotoY=self.view.frame.size.height; } if(ran==1) { left=self.view.frame.size.width; top=-self.view.frame.size.width/2; gotoX=-self.view.frame.size.width/2; gotoY=self.view.frame.size.height; } if(ran==2) { left=self.view.frame.size.width; top=self.view.frame.size.height; gotoX=-self.view.frame.size.width/2; gotoY=-self.view.frame.size.width/2; } if(ran==3) { left=-self.view.frame.size.width/2; top=self.view.frame.size.height; gotoX=self.view.frame.size.width; gotoY=-self.view.frame.size.width/2; }
Create an animation block • The following line of code constructs a CGRect to use as a frame for the initial position of the image: _imageView.frame=CGRectMake(left,top,160,160); • In the animation block we will change the frame, and specify a time duration for the animation: [UIViewanimateWithDuration:1.5animations:^{ _imageView.frame=CGRectMake(gotoX,gotoY,160,160); }]; • The code on the next slide brings all of these steps together, and is added just above the @end statement in the ViewController.m file. Add your code, save your file, and test your app by clicking Run.
Animation code, all together The code below is in one continuous column in Xcode starting with – (void) move -(void)move { NSIntegerran=rand()%4; NSIntegerleft; NSInteger top; NSInteger gotoX; NSInteger gotoY; if(ran==0) { left=-self.view.frame.size.width/2; top=-self.view.frame.size.width/2; gotoX=self.view.frame.size.width; gotoY=self.view.frame.size.height; } if(ran==1) { left=self.view.frame.size.width; top=-self.view.frame.size.width/2; gotoX=-self.view.frame.size.width/2; gotoY=self.view.frame.size.height; } if(ran==2) { left=self.view.frame.size.width; top=self.view.frame.size.height; gotoX=-self.view.frame.size.width/2; gotoY=-self.view.frame.size.width/2; } if(ran==3) { left=-self.view.frame.size.width/2; top=self.view.frame.size.height; gotoX=self.view.frame.size.width; gotoY=-self.view.frame.size.width/2; } _imageView.frame=CGRectMake(left,top,160,160); [UIView animateWithDuration:1.5 animations:^{ _imageView.frame=CGRectMake(gotoX,gotoY,160,160); }]; }
Improving the animation • Now let’s have the image move to the middle of the screen, and then to another corner. We will delete several lines of code from the move method (we won’t need the gotoX and gotoY variables anymore). We will have to add a new method, moveOff, to move the image from the center of the screen to some corner. • We will add two a line of code to the animation block which provides one of its methods to call when the animation ends, moveOff. Note that the animation duration was cut in half, and the remaining half will be used for the second half of the animation.
Revised move method The code below is in one continuous column in Xcode starting with – (void) move - (void) move { NSIntegerran=rand()%4; NSIntegerleft; NSInteger top; if(ran==0) { left=-self.view.frame.size.width/2; top=self.view.frame.size.width/2; } if(ran==1) { left=self.view.frame.size.width; top=-self.view.frame.size.width/2; } if(ran==2) { left=self.view.frame.size.width; top=self.view.frame.size.height; } if(ran==3) { left=-self.view.frame.size.width/2; top=self.view.frame.size.height; } _imageView.frame=CGRectMake(left,top,160,160); [UIView animateWithDuration:.75 animations:^{ _imageView.frame=CGRectMake(80,160,160,160); } completion:^(BOOL finished) { [self moveOff]; }]; }
The moveOff method The code below is in one continuous column in Xcode starting with – (void) moveOff - (void) moveOff { NSIntegerran=rand()%4; NSIntegerleft; NSInteger top; if(ran==0) { left=-self.view.frame.size.width/2; top=-self.view.frame.size.width/2; } if(ran==1) { left=self.view.frame.size.width; top=-self.view.frame.size.width/2; } if(ran==2) { left=self.view.frame.size.width; top=self.view.frame.size.height; } if(ran==3) { left=-self.view.frame.size.width/2; top=self.view.frame.size.height; } [UIView animateWithDuration:.75 animations:^{ _imageView.frame=CGRectMake(left,top,160,160); }]; }
Changing the image and using scale • A student, Chenghao Lin, added a couple of interesting aspects to this basic exercise in his project “Superman”. His project switches between 3 views of Superman – front, heading left, and heading right. He also changed the width and height parameters in the animation block to create an appearance of flying off into space by scaling the image size down.
Changing the Image View • The Superman project had to define 3 methods to load the 3 views of Superman. They were defined in the header file (.h) and implemented in the .m file. In the .h file new code was added below for the definitions for move and move off, as in: -(void)changeLeftSuperman; -(void)changeRightSuperman; -(void)changeToSuperman;
Loading the images In the .m file, the IBActions were implemented like this: -(void)changeLeftSuperman{ _imageView.image=[UIImageimageNamed:@"LeftSuperman.png"]; } -(void)changeRightSuperman{ _imageView.image=[UIImageimageNamed:@"RightSuperman.png"]; } -(void)changeToSuperman{ _imageView.image=[UIImageimageNamed:@"image.png"]; }
Changes to the move method -(void) move{ NSInteger ran=rand()%4; NSInteger left; NSInteger top; if(ran==0){ left=-160; top=-160;[selfchangeToSuperman]; } if(ran==1){ left=320; top=-160; [selfchangeToSuperman]; } if(ran==2){ left=320; top=480; [selfchangeLeftSuperman]; } if(ran==3){ left=-160; top=480; [selfchangeRightSuperman]; } imageView.frame=CGRectMake(left,top,100,100); _imageView.frame=CGRectMake(left,top,100,100); [UIView animateWithDuration:1.5 animations:^{ _imageView.frame=CGRectMake(80,160,100,100); } completion:^(BOOL finished) { [self moveOff]; }];
Changes to the move off method if(ran==2){ left=320; top=520; [selfchangeToSuperman]; } if(ran==3){ left=-160; top=520; [selfchangeToSuperman]; } [UIView animateWithDuration:1.5 animations:^{_imageView.frame=CGRectMake(left,top,w,h);}]; -(void) moveOff{ NSInteger ran=rand()%4; NSInteger left; NSInteger top; NSIntegerw=100; NSIntegerh=100; if(ran==0){ left=10; top=120; [selfchangeLeftSuperman]; w=0; h=0; } if(ran==1){ left=280; top=120; [selfchangeRightSuperman]; w=0; h=0; }
Wrapping up • What kind of animation will you make? Experiment with loading different images, multiple timers, randomness, maybe even sound. • Upload screenshots to your e-portfolio. Zip the project file when you are done and email it to cse392@cs.stonybrook.eduwith the link to your e-portfolio. • Have fun!