Sep 20

In this tutorial I’m going to expand on my previous example TestGame featured in my post Getting Started with the Cocos2d Game Engine.  This follow up borrows heavily from the cocos2d sample file SpritesTest.  If you haven’t seen the SpritesTest demo, see my article on Running the Cocos2d examples. The objective is to reverse engineer that demo and use it to show you how to build your own test app.

Why Build a Test App ?

My background is in testing software libraries.  I have a lot of experience breaking down functionality into manageable test harnesses.  The test harnesses usually let you select one isolated feature and test it.  It’s a great way for learning how a library works.  It’s also a great way to try something.  By building a test harness you don’t have to build a whole project from scratch just to test one feature.  This is especially handy when you run into features that you can only test on the actual device.

Getting Started

In order to complete this tutorial you first you need to go through the steps of my post Getting Started with the Cocos2d Game Engine.

If you are using git you may want to save and tag the original project and try expanding on it here in a new branch.

Graphic Files

For this tutorial you will need to copy some additional graphic files from the cocos2d-iphone sample folders to your projects Resources folder:

  • Resources/Images/grossini images/grossini.png (male cartoon character)
  • Resources/Images/grossini images/grossini_sister1.png (female cartoon character)
  • Resources/Images/menu related images/b1.png (back arrow)
  • Resources/Images/menu related images/b2.png (back arrow highlighted)
  • Resources/Images/menu related images/f1.png (next arrow)
  • Resources/Images/menu related images/f2.png (next arrow highlighted)
  • Resources/Images/menu related images/r1.png (reset button)
  • Resources/Images/menu related images/r2.png (reset button highlighted)

Classes / TestGameAppDelegate.m

For this tutorial I’ve borrowed from the SpritesTest code and added some new functionality to TestGameAppDelegate.m:

//
//  TestGameAppDelegate.m
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//
// Some code and images borrowed from cocos2d SpritesTest sample code.
//
// See these links for additional info and credit:
// http://mitchallen.com/iphone/archives/371
// http://mitchallen.com/iphone/archives/304
 
#import "TestGameAppDelegate.h"
 
@implementation TestGameAppDelegate
 
- (void)applicationDidFinishLaunching:(UIApplication *)application { 
 
	UIWindow *window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
 
	[window setUserInteractionEnabled:YES];
	[window setMultipleTouchEnabled:YES];
 
	// DEPRECATED: [[Director sharedDirector] setLandscape: YES];
	[[Director sharedDirector] setDeviceOrientation: CCDeviceOrientationLandscapeLeft ];
	[[Director sharedDirector] attachInWindow: window];
 
	// display FPS (useful when debugging)
	[[Director sharedDirector] setDisplayFPS:YES];
 
	// frames per second
	[[Director sharedDirector] setAnimationInterval:1.0/60];
 
	[window makeKeyAndVisible];
 
	// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
	// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565
	// You can change anytime.
	[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA8888];
 
	TestScene *game = [TestScene node];
	[[Director sharedDirector] runWithScene: game];
}
 
// getting a call, pause the game
-(void) applicationWillResignActive:(UIApplication *)application
{
	[[Director sharedDirector] pause];
}
 
// call got rejected
-(void) applicationDidBecomeActive:(UIApplication *)application
{
	[[Director sharedDirector] resume];
}
 
// purge memroy
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
	[[TextureMgr sharedTextureMgr] removeAllTextures];
}
 
- (void) dealloc
{
		[super dealloc];
}
 
// next delta time will be zero
-(void) applicationSignificantTimeChange:(UIApplication *)application
{
	[[Director sharedDirector] setNextDeltaTimeZero:YES];
}
 
@end

Test Scene

There are no changes to TestScene from the previous project.  As a reminder:

  • A simple TestScene class is defined based on cocos2d Scene class
  • The TestScene loads a TestLayer based on a cocos2d Layer class

Test Layer

There have been several changes made to TestLayer.

  • Now TestLayer serves as a base class for additional test layers that you can customize based on what you want to test
  • It manages the loading of two sprites from the cocos2d samples: grossini and tamara
  • It loads a graphical menu for navigating between layers using arrows and restarting a layer
  • It has several functions to work with the menu to switch between layers
  • It has a centerSprites method for centering the two test sprites
  • It has a title method used by the UI that can be overridden by derived classes

Classes/TestScene.h

Both TestScene and TestLayer are defined in Classes/TestScene.*

//
//  TestScene.h
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
// See these links for additional info and credit:
// http://mitchallen.com/iphone/archives/371
// http://mitchallen.com/iphone/archives/304
 
#import
#import "cocos2d.h"
#import "chipmunk.h"
 
#pragma mark -
 
@interface TestScene : Scene { }
@end
 
#pragma mark -
 
@interface TestLayer : Layer {
	Sprite * grossini;
	Sprite *tamara;
}
-(void) centerSprites;
-(NSString*) title;
 
-(void) setLayer: (Class) classLayer;
 
-(void) backCallback:(id) sender;
-(void) nextCallback:(id) sender;
-(void) restartCallback:(id) sender;
@end

Classes/TestScene.m

One important thing to note here is the global static transitions string array.  When you add a new class based on TestLayer (see MyTests.* below), you need to add a string containing the name to the array. The navigation code uses NSClassFromString to convert the currently indexed string to a layer object to load.

//
//  TestScene.m
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
// See these links for additional info and credit:
// http://mitchallen.com/iphone/archives/371
// http://mitchallen.com/iphone/archives/304
//
 
#import "TestScene.h"
 
#pragma mark -
 
@implementation TestScene
 
-(id) init {
	self = [super init];
	if( self != nil ) {
		[self addChild: [TestLayer node] z:1];
	}
	return self;
}
 
@end
 
#pragma mark -
 
static int sceneIdx=-1;
 
///////////////////////////////////////////////////
// In order for a test layer to appear you must
// add a string for its class name to this array.
// Test layers are defined in MyTests.*
 
static NSString *transitions[] = {
	@"TestLayer01",
	@"TestLayer02" };
 
Class nextAction()
{
	// Retrieve the name of the next layer class
	// and return a class based on that string.
 
	sceneIdx++;
	sceneIdx = sceneIdx % ( sizeof(transitions) / sizeof(transitions[0]) );
	NSString *r = transitions[sceneIdx];
	Class c = NSClassFromString(r);
	return c;
}
 
Class backAction()
{
	// Retrieve the name of the previous layer class
	// and return a class based on that string.
 
	sceneIdx--;
	if( sceneIdx < 0 )
		sceneIdx = sizeof(transitions) / sizeof(transitions[0]) -1;
	NSString *r = transitions[sceneIdx];
	Class c = NSClassFromString(r);
	return c;
}
 
Class restartAction()
{
	// Retrieve the name of the current layer class
	// and return a class based on that string.
 
	if( sceneIdx < 0 || sceneIdx >= sizeof(transitions) ) return nil;
 
	NSString *r = transitions[sceneIdx];
	Class c = NSClassFromString(r);
	return c;
}
 
#pragma mark -
 
@implementation TestLayer
 
-(id) init {
	self = [super init];
	if(self != nil) {		
 
		// Initialize and add test images so they can be used by derived test layers.
 
		// Note that because we 'retain' the images,
		// we will need to release them in dealloc.
 
		grossini = [[Sprite spriteWithFile:@"grossini.png"] retain];
		tamara = [[Sprite spriteWithFile:@"grossinis_sister1.png"] retain];
 
		[self addChild: grossini z:1];
		[self addChild: tamara z:2];
 
		[self centerSprites];
 
		CGSize s = [[Director sharedDirector] winSize];
 
		// Display the title property for the current layer.
 
		Label* label = [Label labelWithString:[self title] fontName:@"Arial" fontSize:32];
		[self addChild: label];
		[label setPosition: ccp(s.width/2, s.height-50)];
 
		// Create a graphics-based layer navigation menu to be used by all derived test layers.
 
		MenuItemImage *item1 = [MenuItemImage itemFromNormalImage:@"b1.png" selectedImage:@"b2.png" target:self selector:@selector(backCallback:)];
		MenuItemImage *item2 = [MenuItemImage itemFromNormalImage:@"r1.png" selectedImage:@"r2.png" target:self selector:@selector(restartCallback:)];
		MenuItemImage *item3 = [MenuItemImage itemFromNormalImage:@"f1.png" selectedImage:@"f2.png" target:self selector:@selector(nextCallback:)];
 
		Menu *menu = [Menu menuWithItems:item1, item2, item3, nil];
		menu.position = CGPointZero;
		item1.position = ccp(480/2-100,30);
		item2.position = ccp(480/2, 30);
		item3.position = ccp(480/2+100,30);
		[self addChild: menu z:1];
	}
	return self;
}
 
-(void) centerSprites
{
	// Take our two test sprites and center them on the screen.
 
	CGSize s = [[Director sharedDirector] winSize];
 
	[grossini setPosition: ccp(s.width/3, s.height/2)];
	[tamara setPosition: ccp(2*s.width/3, s.height/2)];
}
 
-(NSString*) title
{
	// Create a default title for the opening layer.
 
	// Test layers should override this call.
 
	return @"Press Arrows to Continue";
}
 
-(void) dealloc
{
	// Since our test sprites were retained,
	// we must now release them.
 
	[grossini release];
	[tamara release];
	[super dealloc];
}
 
-(void) setLayer: (Class) classLayer {
 
	// Replace the current layer with one based another class object.
 
	if( classLayer == nil ) return;
 
	Scene *s = [Scene node];
	[s addChild: [classLayer node]];
	[[Director sharedDirector] replaceScene: s];
}
 
-(void) restartCallback: (id) sender
{
	// When the user clicks the restart button
	// (the green circle in the current UI)
	// reload the current layer,
	// triggering a restart of the action
 
	[self setLayer: restartAction()];
}
 
-(void) nextCallback: (id) sender
{
	// When the user clicks the next arrow
	// (the green right arrow in the current UI)
	// load the next layer in the list.
 
	[self setLayer: nextAction()];
}
 
-(void) backCallback: (id) sender
{
	// When the user clicks the back arrow
	// (the green left arrow in the current UI)
	// load the previous layer in the list.
 
	[self setLayer: backAction()];
}
 
@end

Classes/MyTests.h

When adding a new derived TestLayer you generally don’t have to do a lot in the header file (unless you want to add more functions and things like retained sprites to track).  For simple layers you just need to define interfaces based on TestLayer.

//
//  MyTests.h
//  TestGame
//
//  Created by Mitchell Allen on 9/20/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
 
// See these links for additional info and credit:
// http://mitchallen.com/iphone/archives/371
// http://mitchallen.com/iphone/archives/304
 
#import "TestScene.h"
 
///////////////////////////////////////////////////////
//
// Adding Test Layers to Test Game
//
// When a  dervied TestLayer is added, you must add it's name to
// the NSString transitions array in TestScene.m for it to appear
// in the test game.
 
@interface TestLayer01 : TestLayer
{}
@end
 
@interface TestLayer02 : TestLayer
{}
@end

Classes/MyTests.m

For simple layers you just need to define two things:

  • An onEnter method for setting up the actions in your layer
  • A title method that overrides the base TestLayer title method and returns a pointer to an NSString used by the UI

You also need to remember this important step:

  • When you add a new layer you need to add the name as a string to the transistions array in TestScene.m

For this tutorial I just borrowed the SpritesTest demo code from the SpriteMove and SpriteRotate classes.

You can use this file to add as many test layers as you would like.

//
//  MyTests.m
//  TestGame
//
//  Created by Mitchell Allen on 9/20/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
// See these links for additional info and credit:
// http://mitchallen.com/iphone/archives/371
// http://mitchallen.com/iphone/archives/304
 
#import "MyTests.h"
 
#pragma mark -
 
@implementation TestLayer01
 
-(void) onEnter
{
	// Code borrowed from cocos2d sample:
	// SpritesTest.m - SpriteMove class
 
	[super onEnter];
 
	CGSize s = [[Director sharedDirector] winSize];
 
	id actionTo = [MoveTo actionWithDuration: 2 position:ccp(s.width-40, s.height-40)];
 
	id actionBy = [MoveBy actionWithDuration:2  position: ccp(80,80)];
	id actionByBack = [actionBy reverse];
 
	[tamara runAction: actionTo];
	[grossini runAction: [Sequence actions:actionBy, actionByBack, nil]];
 
}
 
-(NSString *) title
{
	// Override the base classes title
	// that appears on the screen.
 
	return @"Test Layer 01 - Move";
}
@end
 
#pragma mark -
 
@implementation TestLayer02
 
-(void) onEnter
{
	// Code borrowed from cocos2d sample:
	// SpritesTest.m - SpriteRotate class
 
	[super onEnter];
 
	[self centerSprites];
 
	id actionTo = [RotateTo actionWithDuration: 2 angle:45];
	id actionBy = [RotateBy actionWithDuration:2  angle: 360];
	id actionByBack = [actionBy reverse];
 
	[tamara runAction: actionTo];
	[grossini runAction: [Sequence actions:actionBy, actionByBack, nil]];
}
 
-(NSString *) title
{
	// Override the base classes title
	// that appears on the screen.
 
	return @"Test Layer 02 - Rotate";
}
@end

Compile and Run

  • Click: Build and Go

Git Clone

If you have git installed, you can clone a copy of this project with the following command:

git clone git://github.com/mitchallen/TestGame.git

For my next tutorial I will be adding code to the repository. So to get back to the original state of this tutorial, you will need to execute the following at the command line:

git checkout v200

To get back to the state used in the previous tutorial you can use:

git checkout v100

Both v100 and v200 are tags that I’ve set on the master branch.

Tags:

Sep 17

If you scroll to the bottom of my previous post you will notice that I’ve updated it with a new section:

Git Clone

If you have git installed, you can clone a copy of this project with the following command:

git clone git://github.com/mitchallen/TestGame.git

Going forward, I will attempt to post all sample code using git. Usually this means that it will come wrapped in a full Xcode project.

I have several reasons for using git:

  • I don’t have to wrestle with creating a zip file and uploading it to some obscure server somewhere
  • You don’t have to wrestle with downloading a zip file and expanding it somewhere
  • You don’t need an account to copy my public repositories
  • All you have to do is enter one line in a terminal window
  • You instantly end up with a local copy of the repository that you can copy and branch any which way you like
  • It forces you to think about source control :)
  • If something is missing, I can just checkin new stuff and do a refresh
  • If I hack an existing project, I can just add a branch instead of forcing you and I to deal with multiple projects

So if you still haven’t installed git on your Mac yet, I suggest you go back and read my post on the subject again.  Also if you have, you may want to read it again.  I’ve added a few more links and info on filtering out certain files to keep your repository from getting cluttered.

Tags: ,

Sep 16

Introduction

What follows are notes that I gathered from looking at various tutorials on getting started with the Cocos2D Game Engine. You can find the tutorials that I used as a source for my notes here:

Additional links may be found in my entry here:

This tutorial was tested with cocos2d-iphone-0.8 – I had trouble compiling with 0.8.1.

UPDATE: I’ve added some notes for compiling using 0.8.2 – with the help of some reader comments below.

Build Options

There are a number of options for creating a Cocos2D Game Project:

  1. Use the engine as a shared library
  2. Start from a template
  3. Copy the engine components and put them in your project

For simplicity this article covers Option #3 – copying the engine components to your project.

If you would like to know more about the other options, see these links:

Setting Up the Project

  • Download and unpack the latest stable release of the Cocos2D Game Engine from here: http://code.google.com/p/cocos2d-iphone/
  • Launch Xcode
  • Select: File / New Project … / [iPhone OS : Application] / Window-based Application / Choose …
  • Save As: TestGame, Save
  • Delete: Resources / MainWindow.xib
  • Edit: TestGame-Info.plist:
  • Delete the line: Main nib file base name : MainWindow
  • Add the line: Status bar is initially hidden – and check it
  • Save the file
  • Click on the TestGame folder icon at the top of the Groups & Files pane
  • Select: Project / Add to Project … / cocos2d-phone-x.y.z / cocos2d
  • Hold down the Apple-key and also select: external
  • Click: Add
  • Check: Copy items in destination group’s folder (if needed)
  • Click: Recursively create groups for any added folders
  • Click: Add
  • Note that if you mess up and need to delete the folders, you also may have to go to the project folder itself and delete them.  Otherwise you may get an error if trying to add them again.
  • In the external folder, delete everything that is NOT the Chipmunk folder (if you are using 0.8.2 keep the FontLabel folder too!).  Why?  Because some of those items are experimental and may not compile.
  • From within the external / Chipmunk folder, delete everything that is NOT the src folder.
  • Right-click on the Resources folder and select: Add / Existing Files …
  • If using 0.8: cocos2d / Resources / Images / fps_images.png
  • If using 0.8.2: cocos2d / Resources / Fonts / fps_images.png
  • Add / Check Copy …, Recursive …, Add
  • Right-click on the Frameworks folder and select: Add / Existing Frameworks …
  • Select the Frameworks folder
  • Select: OpenGLES.framework
  • Click Shift and also select: QuartzCore.framework and click: Add, click Add again

Additional Steps for 0.8.2

If you are using 0.8.2 (or possibly a later version) you will need to also do the following steps to get the project to compile:

  • Double-click on Targets \ TestGame
  • Make sure that the General tab is selected in the dialog box
  • There are two sets of + / - buttons in the dialog, click the + button on the bottom under the list of Linked Libraries
  • Select libz.1.2.3.dylib and Add it

Add New Files

  • Right-click on the Classes folder and select:
  • Add / New File … / [iPhone OS : Cocoa Touch Class ] / Object-C class / [NSObject] / Next
  • File Name: TestScene.m, leave Also create “TestScene.h checked and click Finish

Make the following changes to Classes / TestScene.h:

  • Remove the line:  #import <Foundation/Foundation.h>
  • Add the following import lines:
  • #import <UIKit/UIKit.h>
  • #import “cocos2d.h”
  • #import “chipmunk.h”
  • Change the class definition so that it is based on Scene instead of NSObject
  • At the bottom of the file add another @interface called TestLayer based on Layer
//
//  TestScene.h
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
 
#import
#import "cocos2d.h"
#import "chipmunk.h"
 
@interface TestScene : Scene { }
@end
 
@interface TestLayer : Layer { }
@end

Make the following changes to Classes / TestScene.m:

  • Add init method that adds a TestLayer to the scene
  • Add an @implementation for TestLayer
  • Add init method to TestLayer that puts something on the screen
//
//  TestScene.m
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
 
#import "TestScene.h"
 
#pragma mark -
 
@implementation TestScene
 
-(id) init {
	self = [super init];
	if( self != nil ) {
		[self addChild: [TestLayer node] z:1];
	}
	return self;
}
 
@end
 
#pragma mark -
 
@implementation TestLayer
 
-(id) init {
	self = [super init];
	if(self != nil) {
		// Note that if you spell the fontName wrong, the label won't appear.
		Label *test = [Label labelWithString:@"Hello World" fontName: @"Helvetica" fontSize: 24];
		test.position = cpv(160, 240);	// cpv = Chipmunk vector
		[self addChild: test];	// Add the label to the layer.
	}
	return self;
}
 
@end

Edit the Existing Files

Make the following changes to Classes / TestGameAppDelegate.h:

  • Add two #import statements:
  • #import “cocos2d.h”
  • #import “TestScene.h”
  • Remove the two lines referencing the window property
//
//  TestGameAppDelegate.h
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//
 
#import 
 
#import "cocos2d.h"
#import "TestScene.h"
 
@interface TestGameAppDelegate : NSObject  {
}
 
@end

Make the following changes to Classes / TestGameAppDelegate.m:

  • Remove the line: @synthesize window;
  • Remove the dealloc method
  • Clear the contents of the method: applicationDidFinishLaunching and replace it with the code below
  • If you don’t want your game to start in landscape mode, comment out the line containing setDeviceOrientation
//
//  TestGameAppDelegate.m
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//
 
#import "TestGameAppDelegate.h"
 
@implementation TestGameAppDelegate
 
- (void)applicationDidFinishLaunching:(UIApplication *)application { 
 
	UIWindow *window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
 
	[window setUserInteractionEnabled:YES];
	[window setMultipleTouchEnabled:YES];
 
	// DEPRECATED: [[Director sharedDirector] setLandscape: YES];
	[[Director sharedDirector] setDeviceOrientation: CCDeviceOrientationLandscapeLeft ];
	[[Director sharedDirector] attachInWindow: window];
	[window makeKeyAndVisible];
 
	TestScene *game = [TestScene node];
	[[Director sharedDirector] runWithScene: game];
}
 
@end

Make the following changes to Other Sources / main.m:

  • Change the last argument in the call to UIApplicationMain to a string containing the name of the delegate: @”TestGameAppDelegate”
//
//  main.m
//  TestGame
//
//  Created by Mitchell Allen on 9/16/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//
 
#import 
 
int main(int argc, char *argv[]) {
 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 
	// MCA - changed last argument to name of delegate.
    int retVal = UIApplicationMain(argc, argv, nil, @"TestGameAppDelegate");
 
    [pool release];
    return retVal;
}

Compile and Run

  • Click: Build and Go

Git Clone

If you have git installed, you can clone a copy of this project with the following command:

git clone git://github.com/mitchallen/TestGame.git

For my next tutorial I will be adding code to the repository. So to get back to the original state of this tutorial, you will need to execute the following at the command line:

git checkout v100

Tags: , ,

Sep 04

Over the years I’ve worked with many source control management systems (CVS, SVN, SourceSafe, PerForce).   The problem is that they are oriented towards a central server.  Git on the other hand is a new and improved type of source control.  It can work with a server - in fact, it can work with many servers.  But it can also work with just your collaborators workstation across the hall – bypassing the need for a server completely.

If you are just working by yourself (as many iPhone developers are) you can run it on your local workstation – even without a network connection.  If later you want to make your repository available to others — or just create an offsite backup — you can either open up a share on your workstation or clone a repository to a server.

Instead of going into too much detail, I’m just going to provide links to resources for you to look at.  You can decide for yourself if it is right for you:

  • Git Home Page
  • http://progit.org/book/ - A free Web-based version of the book Pro Git.
  • Pro Git on Apress – You can help the author of Pro Git out by buying a PDF or hard-copy.
  • Git for OS X – This is what you’ll need to install it on your Mac.  In my case I had to make sure that I got the latest Intel / Leopard DMG file.
  • Installing Git on Leopard – For the most part you will just want the Git for OS X installer – but see the notes on setting up your config.
  • Gitx – GitX is a git GUI made for Mac OS X
  • Heroku tips on Git – Heroku is a cloud-based host for Rails apps – but you may find some of the generic tips and links useful.
  • Windows Installer – Why would an iPhone developer need a Windows installer?  It could make it easy to trade *.cpp files with your PC.  Plus you can use it for your other projects.  Git is platform independent.
  • GitHub.com – Free hosting for your open source projects.  Paid options also available.
  • Unfuddle - Also offers free hosting.  Unlike GitHub, the free plan can be private.

Installing on the Mac

When you download Git for OS X the DMG file should open up.  Launch the installer.

After installation completes, open up a terminal window and configure it via the command line (substitute your name and e-mail address):

git config --global user.name "John Doe"
git config --global user.email "john.doe@gmail.com"

When that is done type the following:

git config --list

Ignoring Files

On a PC, you would see several items listed.  On the Mac, apparently you have to set those yourself.  See the link Installing Git on Leopard for what other globals you have to set.  Be sure to configure the ability to use a .gitignore file for filtering what goes into the repository.

The link suggests that you put your .gitignore file in your user directory.  I prefer to put the file in the root of the project.  Yes, it is a hassle to always copy the file from project to project.  But it helps you make sure that whomever else downloads your repository has the right filter too.

So I would configure my globals like this:

git config --global core.excludesfile .gitignore

For iPhone SDK projects, here is what I have for a .gitignore file:

# xcode noise
build/*
*.xcclassmodel/*
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
 
# old skool
.svn
 
# osx noise
.DS_Store
profile

Here is what I have for .gitattributes – which also sits in the root directory of the project:

.pbxproj -crlf -diff -merg

For more info, see these links:

http://shanesbrain.net/2008/7/9/using-xcode-with-git

http://rudifa.wordpress.com/2009/05/19/git-xcode-and-projectlocker/

Hidden Files

One thing to note is that when you create a local repository it goes into a subfolder called “.git” under your projects directory.  On Windows you can see this folder.  It’s hidden by default on the Mac.  The same is true for .gitignore and .gitattributes.  If you are in a Terminal window, you can view hidden files using the -A flag for ls.  Example:

apple$ ls -l -A

If you would like to be able to view hidden files and folders in Finder enter this line from a Terminal window:

defaults write com.apple.Finder AppleShowAllFiles YES

The hidden files won’t appear until you restart Finder.  For more info, see this link. (Note: their steps for restarting Finder didn’t work for me – I just rebooted).

Git Hosting

If you do decide to setup a Git server, it can be a bit of work.  To get around that problem at work I just use file shares.  The good thing about Git is that it can refer to a server based reposiory either via http:// or file:/// (example:  file:///\\mywinsever\git\myproject.git – note that there are three slashes after “file:” ).  If that makes no sense to you now, don’t worry.  It will once you come up to speed.

If you want to share your project with the world, hosts like GitHub.com and Unfuddle can also save you a lot of work.   These sites are new and suffer from a lack of documentation.  But if you don’t mind being on the bleeding edge you may find them useful.

Tags: