Categories
Articles

IPhone Basic Dice Roller Animation Using XCode

This is a basic IPhone example that demonstrates an animated UIImageView. The example demonstrates how to take a sequence of images and animate them.

Ready to Animate State

To make the example interesting, I decided to use the roll of one die. This does not show a rolling 3D dice. Rather it is a sequential swapping of die faces on a single plane. When you start the die roll, you can choose when to stop. When the animation is stopped, I am using a random number to select which die value. As such the last animated die face is not the die face for the roll value. I set the animating fast enough for the simulator at least to make it difficult to see which die value was last animated when the stop button is released.

I also shows setting the user interaction states for when the die is being rolled and when it is not. I include some constants for determining the view state based on when the die is rolling or not. For example in this view the app is not animating so the roll button is enabled and the stop button is disabled.

The images for the die faces are very simple.

Source Download
XCode 4 Project

I used the IOS “View-based Application” when creating a new project in XCode. All the coding is in the AnimatedDieFaceViewController UIViewController.

AnimatedDieFaceViewController.h

This sets out the interface for the view controller.

The controller needs to set the enabled and alpha properties of the roll and stop button respectively named as rollButton and stopButton. To do this they are declared as IBOutlet so they can be linked up in the XIB file.

The rollDiceImageView UIImageView is where we will swap 6 images of die faces. Those are UIImage objects stored in the animationImages NSArray.

The method rollButtonPressed, stopButtonPressed, setAnimatingState, animateImages and stopAnimatingImages are explained with the implementation code.

#import <UIKit/UIKit.h>

@interface AnimatedDieFaceViewController : UIViewController {
    UIImageView *rollDiceImageView;
    UIButton *rollButton;
    UIButton *stopButton;
    NSArray *animationImages;

}
@property (nonatomic, retain) IBOutlet UIImageView *rollDiceImageView;
@property (nonatomic, retain) IBOutlet UIButton *rollButton;
@property (nonatomic, retain) IBOutlet UIButton *stopButton;
-(IBAction) rollButtonPressed:(id) sender;
-(IBAction) stopButtonPressed:(id) sender;
-(void) setAnimatingState:(int)animatingState;
-(void) animateImages;
-(void) stopAnimatingImages;
@end

[ad name=”Google Adsense”]

AnimatedDieFaceViewController.m

On lines 9 and 11 I declared two constants,ANIMATING_YES and ANIMATING_NO to indicate the animation state. Those are values to pass to setAnimatingState where the rollButton and the stopButton enabled and alpha properties are set.

In the viewDidLoad method starting on line 84, the animatingImages NSArray is populated with images.

Animating State

Also initial properties for the rollDiceImageView UIImageView are set including

  • image for the initial image when the app starts up.
  • animationImages set to our animatingImages NSArray.
  • animationDuration set to .5 or 1/2 of a second.
  • animationRepeatCount set to 0 to keep the animation running indefinitely.

When the rollButton is pressed, the rollButtonPressed method is called on line 13 which in turn calls the animateImages method on line 18. It is in animateImages the the view state is set and the animation is started. The view state is set so the roll button is disabled and the stop button is enabled.

On line 26 the stopButtonPressed method leads us to the stopAnimatingImages method on line 31. In this method we compute a random number rollValue for the dice roll using arc4random on line 38.

Then on line 40 rollValue is used to determine which image in the animationImages NSArray to assign to the image property of rollDiceImageView UIIMageView.

Line 42 calls setAnimatingState to reset the roll to an enabled state and stop button to a disabled state.

#import "AnimatedDieFaceViewController.h"

@implementation AnimatedDieFaceViewController
@synthesize rollDiceImageView;
@synthesize rollButton;
@synthesize stopButton;

// State is animating. Used to set view.
static const int ANIMATING_YES = 1;
// State is not animating. Used to set view.
static const int ANIMATING_NO = 0;

-(IBAction) rollButtonPressed:(id) sender
{
    NSLog(@"rollButtonPressed");
    [self animateImages];
}
-(void) animateImages
{
    NSLog(@"animateImages");
    //Set view to animating state.
    [self setAnimatingState:ANIMATING_YES];
    // Start the animation
	[rollDiceImageView startAnimating];
}
-(IBAction) stopButtonPressed:(id) sender
{
    NSLog(@"RotatingDiceEx01ViewController.stopButtonPressed");
    [self stopAnimatingImages];
}
-(void) stopAnimatingImages
{
    NSLog(@"RotatingDiceEx01ViewController.stopAnimatingImages");

    // Stop the animation.
    [rollDiceImageView stopAnimating ];
    // Generate a random number from 0 to 5;
    int rollValue =  arc4random() %  6  ;
    // Assign image from the animationImages NSArray using the rollValue as index.
    rollDiceImageView.image = [animationImages objectAtIndex:rollValue];
    //Set view to not animating state.
    [self setAnimatingState:ANIMATING_NO];
}
-(void) setAnimatingState:(int)animatingState
{
    NSLog(@"RotatingDiceEx01ViewController/setAnimatingState(...) - animatingState %i:", animatingState);
    // Set view state to animating.
    if (animatingState == ANIMATING_YES)
    {
        rollButton.enabled = false;
        rollButton.alpha = 0.5f;
        stopButton.enabled = true;
        stopButton.alpha = 1.0f;
    }
    // Set view state to not animating.
    else if (animatingState == ANIMATING_NO)
    {
        rollButton.enabled = true;
        rollButton.alpha = 1.0f;
        stopButton.enabled = false;
        stopButton.alpha = 0.5f;
    }
}
- (void)dealloc
{
    [animationImages release];
    [rollDiceImageView dealloc];
    [rollButton dealloc];
    [stopButton dealloc];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    NSLog(@"RotatingDiceEx01ViewController.viewDidLoad");
    // Build an array of UIImage objects.
    animationImages = [[NSArray arrayWithObjects:
                        [UIImage imageNamed:@"die_face_01.png"],
                        [UIImage imageNamed:@"die_face_02.png"],
                        [UIImage imageNamed:@"die_face_03.png"],
                        [UIImage imageNamed:@"die_face_04.png"],
                        [UIImage imageNamed:@"die_face_05.png"],
                        [UIImage imageNamed:@"die_face_06.png"],
                        nil] retain ];
    // Set the starting image.
    rollDiceImageView.image = [UIImage imageNamed:@"die_face_01.png"];
    // Initialize the animation properties
    rollDiceImageView.animationImages = animationImages; // NSArray of UImage objects.
	rollDiceImageView.animationDuration = .5; // Default = .033333 1/30 sec
	rollDiceImageView.animationRepeatCount = 0; // 0 = continuous

    [super viewDidLoad];
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.rollDiceImageView = nil;
    self.rollButton = nil;
    self.stopButton = nil;

}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end

[ad name=”Google Adsense”]

AnimatedDieFaceViewController.xib

AnimatedDieFaceViewController UIView

This is the layout of the interface.

The UIButton with the Stop caption has its enabled property unchecked and its alpha property set to 0.5;

The dimensions of the UIImageView is set to 100 by 100. Each of the die face images are 100 by 100. The UIImageView is dead center in the UIView.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
AnimatedDieFaceViewController IBOutlets and IBActions

The IBOutlets are for the two UIButtons and the UIImageView so their properties in the controller code can be changed. You can see on lines 40, 97, 99, 100 and 101 setting rollDiceImageView UIImageView properties. In the setAnimatingState method starting on line 44 the alpha and enabled properties for the buttons are set.

The view outlet was set when I choose the IOS View-based Application to create the XCode project.

The IBActions are for the two buttons when the Touch Up Inside event is initiated. You can see the methods rollButtonPressed and stopButtonPressed linked to that event for each button.