CS 489.02 - Computers and Games - Spring 2009
iPhone Pick up the Peanuts


Loyola College > Department of Computer Science > Dr. James Glenn > CS 489.02 > Examples and Lecture Notes > iPhone Pick up the Peanuts

EAGLView.m

#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import <ApplicationServices/ApplicationServices.h>

#import "EAGLView.h"
#import "peanutsmodel.h"
#import "sprite.h"

#define USE_DEPTH_BUFFER 0

@interface EAGLView ()
// boilerplate omitted

- (void)drawRectangleX1:(double)x1 y1:(double)y1 x2:(double)x2 y2:(double)y2 color:(UIColor*)c;

@end


@implementation EAGLView

// synthesized properties and initWithCoder omitted

- (void)drawView {
  [EAGLContext setCurrentContext:context];
  
  glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
  glViewport(0, 0, backingWidth, backingHeight);
  
  // set up ortho projection to show game area of (0, 0) to (1, 1) [should use model getWidth...]
  // note that the view is 50% taller than wide in portrait mode so we have a little extra space there
  
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrthof(0.0, 1.0f, -0.25f, 1.25f, -1.0f, 1.0f);
  glMatrixMode(GL_MODELVIEW);
  
  // clear view
  
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
  
  // draw borders
  
  [self drawRectangleX1:0.0 y1:-0.25 x2:1.0 y2:0.0 color:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]];
  [self drawRectangleX1:0.0 y1:1.0 x2:1.0 y2:1.25 color:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]];
  
  NSArray* sprites = [model getSprites];
  
  for (int i = 0; i < [sprites count]; i++)
    {
      Sprite* s = (Sprite*)[sprites objectAtIndex:i];
      [self drawRectangleX1:[s getX] - [s getBoundingRadius] / 2
	                 y1:[s getY] - [s getBoundingRadius] / 2
	                 x2:[s getX] + [s getBoundingRadius] / 2
	                 y2:[s getY] + [s getBoundingRadius] / 2
	                 color:[s getColor]];	
    }
  
  glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (void)drawRectangleX1:(double)x1 y1:(double)y1 x2:(double)x2 y2:(double)y2 color:(UIColor*)c
{
	GLfloat* verts = malloc(sizeof(GLfloat) * 8);
	GLubyte* colors = malloc(sizeof(GLubyte) * 16);
	
	verts[0] = x1;
	verts[1] = y1;
	verts[2] = x2;
	verts[3] = y1;
	verts[4] = x1;
	verts[5] = y2;
	verts[6] = x2;
	verts[7] = y2;
	
	const CGFloat* colorComponents = CGColorGetComponents(c.CGColor);
	int numComponents = CGColorGetNumberOfComponents(c.CGColor);
	
	for (int v = 0; v < 4; v++)
	{
		for (int c = 0; c < 4; c++)
		{
			if (c < numComponents - 1)
			{
				colors[v * 4 + c] = (int)(colorComponents[c] * 255);
			}
			else if (c == 3)
			{
				// alpha is last component
				
				colors[v * 4 + c] = (int)(colorComponents[numComponents - 1] * 255);
			}
			else
			{
				// assume grayscale; use 1st component
				
				colors[v * 4 + c] = (int)(colorComponents[0] * 255);
			}
		}
	}
	
	glVertexPointer(2, GL_FLOAT, 0, verts);
	glEnableClientState(GL_VERTEX_ARRAY);
	glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
	glEnableClientState(GL_COLOR_ARRAY);
	
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);		

	free(verts);
	free(colors);
}

// layoutSubviews, createFramebufer, destroyFramebuffer omitted

- (void)update
{
	if (model != nil)
	{
		[model update];
	}
	
	[self drawView];
}

- (id) init
{
	model = nil;
	
	return [super init];
}

- (void)associate:(PeanutsModel*) d
{
	model = [d retain];
}

- (void)startAnimation {
    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(update) userInfo:nil repeats:YES];
}

// stopAnimation, setAnimationTimer, setAnimationInterval omitted

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
	[model movePlayerXDir:1 yDir:0];
	
	// haven't enabled multi-touch, so anyObject gets _the_ touch
	
	UITouch* touch = [touches anyObject];
	CGPoint location = [touch locationInView:self];
	// compute touch location in world space (hard-coded (0,-.25)-(1,1.25) viewport)
	
	double touchX = (location.x - self.bounds.origin.x) / self.bounds.size.width;
	double touchY = 1.25 - (location.y - self.bounds.origin.y) / self.bounds.size.height * 1.5;
	
	double playerX = [[model getPlayer] getX];
	double playerY = [[model getPlayer] getY];
	
	// figure out direction from player to touch
	
	int dx = 0;
	if (touchX + 0.1 < playerX)
	{
		dx = -1;
	}
	else if (touchX - 0.1 > playerX)
	{
		dx = 1;
	}
	
	int dy = 0;
	if (touchY + 0.1 < playerY)
	{
		dy = -1;
	}
	else if (touchY - 0.1 > playerY)
	{
		dy = 1;
	}
	
	[model movePlayerXDir:dx yDir:dy];
}

- (void)dealloc {
    
    [self stopAnimation];
    
    if ([EAGLContext currentContext] == context) {
        [EAGLContext setCurrentContext:nil];
    }
    
	if (model != nil)
	{
		[model release];
	}
	
    [context release];  
    [super dealloc];
}

@end

elephant.m

#import "elephant.h"
#import "peanutsmodel.h"
#import "hole.h"

@implementation Elephant

-(id) initAtX:(double)initX y:(double)initY
{
  [super initWithX:initX y:initY vx:0.0 vy:0.0 radius:ELEPHANT_DEFAULT_SIZE color:[UIColor grayColor]];

  peanutsEaten = 0;

  return self;
}
	 
-(double) getMaximumSpeed
{
  return 0.2;
}

-(void) updateForTime:(double)t model:(GameModel*)m
{
  PeanutsModel* pm = (PeanutsModel*)m;

  if ([self getState] != STATE_FULL)
    {
      // get direction to peanut

      double peanutX = [[pm getPeanut] getX];
      double peanutY = [[pm getPeanut] getY];

      double dx = peanutX - [self getX];
      double dy = peanutY - [self getY];

      // change to one of 8 compass directions

      if (fabs(dx) < [self getBoundingRadius] / 4)
	{
	  dx = 0;
	}
      else
	{
	  dx = (dx == 0 ? 0 : dx / fabs(dx)); // signum(dx)
	}

      if (fabs(dy) < [self getBoundingRadius] / 4)
	{
	  dy = 0;
	}
      else
	{
	  dy = (dy == 0 ? 0 : dy / fabs(dy)); // signum(dy)
	}

      [self setVelocityX:dx * [self getMaximumSpeed] y:dy * [self getMaximumSpeed]];

      if (peanutsEaten > MAX_PEANUTS && [self getStateTime] > LAST_PEANUT_TIME)
	{
	  [self setState:STATE_FULL];
	}
    }
  else
    {
      [self setVelocityX:0.0 y:0.0];

      if ([self getStateTime] > RECOVERY_TIME)
	{
	  [self setState:STATE_NORMAL];
	  [m addSprite:[[[Hole alloc] initAtX:[self getX] y:[self getY]] autorelease]];
	  peanutsEaten = 0;
	}
    }

  [super updateForTime:t model:m];
}

-(void) eatPeanut
{
  peanutsEaten++;
  [self setState:STATE_NORMAL];
}


-(void) dealloc
{
  [super dealloc];
}

@end

gamemodel.m

#import "gamemodel.h"
#import "sprite.h"

@implementation GameModel

-(id) init
{
  [super init];

  sprites = [[NSMutableArray alloc] init];
  toAdd = [[NSMutableArray alloc] init];
  toRemove = [[NSMutableArray alloc] init];
  lastUpdate = 0.0;

  return self;
}

-(NSArray*) getSprites
{
  NSMutableArray* result = [[[NSMutableArray alloc] init] autorelease];

  [result addObjectsFromArray:sprites];
  [result removeObjectsInArray:toRemove];

  return result;
}

-(void) addSprite:(Sprite*)s
{
  if (![sprites containsObject:s] && ![toAdd containsObject:s])
    {
      [toAdd addObject:s];
    }
}

-(void) removeSprite:(Sprite*)s
{
  if (![toRemove containsObject:s] && [sprites containsObject:s])
    {
      [toRemove addObject:s];
    }
}

-(double) getWidth
{
  return 1.0;
}

-(double) getHeight
{
  return 1.0;
}

-(void) processRemovedSprites
{
  [sprites removeObjectsInArray:toRemove];
  [toRemove removeObjectsInRange:NSMakeRange(0, [toRemove count])];
}

-(void) processAddedSprites
{
  [sprites addObjectsFromArray:toAdd];
  [toAdd removeObjectsInRange:NSMakeRange(0, [toAdd count])];
}

-(void) update
{
  // get current time since 1970

  NSDate* currentDate = [NSDate date];
  NSTimeInterval currentTime = [currentDate timeIntervalSince1970];

  if (lastUpdate != 0.0)
    {
      for (int i = 0; i < [sprites count]; i++)
	{
	  [(Sprite*)[sprites objectAtIndex:i] updateForTime:currentTime - lastUpdate model:self];
	}
    }

	[self checkCollisions];
	
  [self processRemovedSprites];
  [self processAddedSprites];

  lastUpdate = currentTime;
}

-(void) checkCollisions
{
  for (int i = 0; i < [sprites count]; i++)
    {
      Sprite* s1 = [sprites objectAtIndex:i];

      for (int j = i + 1; j < [sprites count]; j++)
	{
	  Sprite* s2 = [sprites objectAtIndex:j];

	  if ([s1 collidesWith:s2])
	    {
	      [self handleCollisionSprite:s1 with:s2];
	    }
	}
    }
}

-(void) handleCollisionSprite:(Sprite*)s1 with:(Sprite*)s2
{
}

-(void) dealloc
{
  [sprites release];
  [toAdd release];
  [toRemove release];

  [super dealloc];
}

@end

hole.m

#import "hole.h"

@implementation Hole

-(id) initAtX:(double)initX y:(double)initY
{
  [super initWithX:initX y:initY vx:0.0 vy:0.0 radius:HOLE_DEFAULT_SIZE color:[UIColor blackColor]];

  return self;
}

-(void) dealloc
{
  [super dealloc];
}

@end

peanut.m

#import "peanut.h"

@implementation Peanut

-(id) initAtX:(double)initX y:(double)initY
{
  [super initWithX:initX y:initY vx:0.0 vy:0.0 radius:PEANUT_DEFAULT_SIZE color:[UIColor brownColor]];

  return self;
}

-(int) getValue
{
  double t = [self getStateTime];

  if (t < 2.0)
    {
      return 50;
    }
  else if (t < 4.0)
    {
      return 20;
    }
  else
    {
      return 10;
    }
}

-(void) dealloc
{
  [super dealloc];
}

@end

PeanutsAppDelegate.m

#import "PeanutsAppDelegate.h"
#import "EAGLView.h"
#import "peanutsmodel.h"

@implementation PeanutsAppDelegate

// synthesis of properties omitted

- (id)init
{
	[super init];
	
	model = [[PeanutsModel alloc] init];
	
	return self;
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    
	glView.animationInterval = 1.0 / 60.0;
	[glView startAnimation];
	[glView associate:model];
}

// applicationWillResignActive, applicationDidBecomeActive omitted

- (void)dealloc {
	[window release];
	[glView release];
	[model release];
	[super dealloc];
}

@end

peanutsmodel.m

#import <stdlib.h>

#import "peanutsmodel.h"
#import "elephant.h"
#import "player.h"
#import "peanut.h"
#import "hole.h"

@implementation PeanutsModel

-(id) init
{
  [super init];

  elephant = [[[Elephant alloc] initAtX:0.9 y:0.5] autorelease];
  [self addSprite:elephant];

  player = [[[Player alloc] initAtX:0.1 y:0.5] autorelease];
  [self addSprite:player];

  [self makePeanut];

  score = 0;

  gameLength = DEFAULT_GAME_LENGTH;
    
  NSDate* currentDate = [NSDate date];
  startTime = [currentDate timeIntervalSince1970];

  return self;
}

-(int) getPlayerScore
{
  return score;
}

-(Peanut*) getPeanut
{
  return peanut;
}

-(Player*) getPlayer
{
	return player;
}

-(void) movePlayerXDir:(int)dx yDir:(int)dy
{
  [player moveDirX:dx y:dy];
}

-(void) makePeanut
{
  if (peanut != nil)
    {
      [self removeSprite:peanut];
    }

  double px = (double)random() / RAND_MAX;
  double py = (double)random() / RAND_MAX;

  peanut = [[[Peanut alloc] initAtX:px y:py] autorelease];

  [self addSprite:peanut];
}

-(int) getTimeLeft
{
  NSDate* currentDate = [NSDate date];
  NSTimeInterval currentTime = [currentDate timeIntervalSince1970];
  
  NSTimeInterval timeElapsed = currentTime - startTime;

  if (timeElapsed > gameLength)
    {
      return 0;
    }
  else
    {
      return (int)(gameLength - timeElapsed);
    }
}

-(void) update
{
  if ([self getTimeLeft] > 0)
    {
      [super update];
    }
}

-(void) handleCollisionSprite:(Sprite*)s1 with:(Sprite*) s2
{
  if ([s1 isMemberOfClass:[Peanut class]] || [s2 isMemberOfClass:[Peanut class]])
    {
      // swap to make s1 the one that ate the peanut

      if ([s1 isMemberOfClass:[Peanut class]])
	{
	  Sprite* temp = s1;
	  s1 = s2;
	  s2 = temp;
	}

      if ([s1 isMemberOfClass:[Player class]])
	{
	  // player ate peanut

	  int value = [(Peanut*)s2 getValue];
	  score += value;

	  [self makePeanut];
	  
	  // and add a value display when you make them
	}
      else if ([s1 isMemberOfClass:[Elephant class]])
	{
	  // elephant ate peanut

	  [(Elephant*)s1 eatPeanut];
	  [self makePeanut];
	}
      else
	{
	  // something else ran into the peanut
	}
    }
  else if ([s1 isMemberOfClass:[Elephant class]] && [s2 isMemberOfClass:[Player class]])
    {
      // player runs into elephant

      [(Player*)s2 trample];
    }
  else if([s2 isMemberOfClass:[Elephant class]] && [s1 isMemberOfClass:[Player class]])
    {
      // elephant tramples player

      [(Player*)s1 trample];
    }
  else if ([s1 isMemberOfClass:[Player class]] && [s2 isMemberOfClass:[Hole class]])
    {
      // player falls in hole

      [(Player*)s1 fallInHole];
      [self removeSprite:s2];
    }
  else if ([s2 isMemberOfClass:[Player class]] && [s1 isMemberOfClass:[Hole class]])
    {
      // hole attacks player

      [(Player*)s2 fallInHole];
      [self removeSprite:s1];
    }
}

-(void) dealloc
{
  [super dealloc];
}

@end

player.m

#import "player.h"
#import "gamemodel.h"

@implementation Player

-(id) initAtX:(double)initX y:(double)initY
{
  [super initWithX:initX y:initY vx:0.0 vy:0.0 radius:PLAYER_DEFAULT_SIZE color:[UIColor redColor]];

  return self;
}

-(double) getMaximumSpeed
{
  return 0.2;
}

-(void) moveDirX:(int)dx y:(int)dy
{
  if ([self getState] != STATE_TRAMPLED)
    {
      [self setVelocityX:[self getMaximumSpeed] * dx y:[self getMaximumSpeed] * dy];
    }
  else
    {
      recoverDx = dx;
      recoverDy = dy;
    }
}

-(void) trample
{
  if ([self getState] != STATE_TRAMPLED)
    {
      [self setState:STATE_TRAMPLED];
      recoverDx = 0;
      recoverDy = 0;
      recoveryTime = PLAYER_RECOVERY_TIME;
    }
}

-(void) fallInHole
{
  if ([self getState] != STATE_TRAMPLED)
    {
      [self setState:STATE_TRAMPLED];
      recoverDx = 0;
      recoverDy = 0;
      recoveryTime = PLAYER_CLIMBING_TIME;
    }
}

-(void) updateForTime:(double)t model:(GameModel*)m
{
  if ([self getState] == STATE_TRAMPLED)
    {
      if ([self getStateTime] > recoveryTime)
	{
	  // recovered from trampling or falling

	  [self setState:STATE_NORMAL];
	  [self moveDirX:recoverDx y:recoverDy];
	}
      else
	{
	  [self setVelocityX:0.0 y:0.0];
	}
    }

  [super updateForTime:t model:m];

  // do wraparound

  if ([self getX] < [self getBoundingRadius] / 2)
    {
      x = [m getWidth] - [self getBoundingRadius] / 2;
    }
  else if ([self getX] + [self getBoundingRadius] / 2 > [m getWidth])
    {
      x = [self getBoundingRadius] / 2;
    }

  if ([self getY] < [self getBoundingRadius] / 2)
    {
      y = [m getHeight] - [self getBoundingRadius] / 2;
    }
  else if ([self getY] + [self getBoundingRadius] / 2 > [m getHeight])
    {
      y = [self getBoundingRadius] / 2;
    }
}

-(void) dealloc
{
  [super dealloc];
}

@end

sprite.m

#import <math.h>

#import "sprite.h"

@implementation Sprite

-(id) initWithX:(double)initX y:(double)initY radius:(double)r
{
  [super init];

  x = initX;
  y = initY;
  vx = 0.0;
  vy = 0.0;
  radius = r;
  color = [[UIColor blackColor] retain];
  state = 0;
  stateTime = 0.0;

  return self;
}
  
-(id) initWithX:(double)initX y:(double)initY vx:(double)initVx vy:(double)initVy radius:(double)r
{
  [super init];

  x = initX;
  y = initY;
  vx = initVx;
  vy = initVy;
  radius = r;
  color = [[UIColor blackColor] retain];
  state = STATE_NORMAL;
  stateTime = 0.0;

  return self;
}

-(id) initWithX:(double)initX y:(double)initY vx:(double)initVx vy:(double)initVy radius:(double)r color:(UIColor *)c
{
  [super init];

  x = initX;
  y = initY;
  vx = initVx;
  vy = initVy;
  radius = r;
  color = [c retain];
  state = 0;
  stateTime = 0.0;

  return self;
}

-(double) getX
{
  return x;
}

-(double) getY
{
  return y;
}

-(UIColor*) getColor
{
  return color;
}

-(double) getMaximumSpeed
{
  return 1e+10;
}

-(void) setVelocityX:(double)newVx y:(double)newVy
{
  vx = newVx;
  vy = newVy;

  // limit speed to max velocity

  double v = sqrt(vx * vx + vy * vy);
  double maxV = [self getMaximumSpeed];

  if (v > maxV)
    {
      vx = vx / (v / maxV);
      vy = vy / (v / maxV);
    }
}

-(double) getBoundingRadius
{
  return radius;
}

-(BOOL) collidesWith:(Sprite*)s
{
  double dx = x - [s getX];
  double dy = y - [s getY];
  double dist = sqrt(dx * dx + dy * dy);

  return (dist < radius + [s getBoundingRadius]);
}

-(void) updateForTime:(double)t model:(GameModel*)m
{
  stateTime += t;

  x += vx * t;
  y += vy * t;
}

-(int) getState
{
  return state;
}

-(void) setState:(int)s
{
  state = s;
  stateTime = 0.0;
}

-(double) getStateTime
{
  return stateTime;
}

-(void) dealloc
{
  [color release];
  
  [super dealloc];
}
@end

EAGLView.h


#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>

@class PeanutsModel;

@interface EAGLView : UIView {
    
@private
  // boilerplate from OpenGL ES template omitted
  
  NSTimer *animationTimer;
  NSTimeInterval animationInterval;
  
  PeanutsModel *model;
}

@property NSTimeInterval animationInterval;

// more boilerplayer omitted

- (void)update;
- (void)associate:(PeanutsModel*) model;

@end

elephant.h

#import "sprite.h"

@interface Elephant : Sprite
{
  int peanutsEaten;
}

#define ELEPHANT_DEFAULT_SIZE 0.025
#define MAX_PEANUTS 4
#define STATE_FULL 1
#define RECOVERY_TIME 2.0
#define LAST_PEANUT_TIME 1.0

-(id) initAtX:(double)initX y:(double)initY;
-(double) getMaximumSpeed;
-(void) updateForTime:(double)t model:(GameModel*)m; 
-(void) eatPeanut;
-(void) dealloc;

@end

gamemodel.h

#import <Foundation/Foundation.h>

@class Sprite;

@interface GameModel : NSObject
{
  NSMutableArray* sprites;
  NSMutableArray* toRemove;
  NSMutableArray* toAdd;

  NSTimeInterval lastUpdate;
}

-(id) init;
-(NSArray*) getSprites;
-(void) addSprite:(Sprite*)s;
-(void) removeSprite:(Sprite*)s;
-(double) getWidth;
-(double) getHeight;
-(void) processRemovedSprites;
-(void) processAddedSprites;
-(void) update;
-(void) checkCollisions;
-(void) handleCollisionSprite:(Sprite*)s1 with:(Sprite*) s2;
-(void) dealloc;

@end

hole.h

#import "sprite.h"

@interface Hole : Sprite

#define HOLE_DEFAULT_SIZE 0.01

-(id) initAtX:(double)x y:(double)y;
-(void) dealloc;
@end

peanut.h

#import "sprite.h"

@interface Peanut : Sprite

#define PEANUT_DEFAULT_SIZE 0.01

-(id) initAtX:(double)initX y:(double)initY;
-(int) getValue;
-(void) dealloc;

@end

PeanutsAppDelegate.h

#import <UIKit/UIKit.h>

@class EAGLView;
@class PeanutsModel;

@interface PeanutsAppDelegate : NSObject <UIApplicationDelegate> {
  // default members omitted
  PeanutsModel* model;
}

// property declarations omitted

- (id)init;
- (void)dealloc;

@end

peanutsmodel.h

#import <Foundation/Foundation.h>

#import "gamemodel.h"

@class Player;
@class Elephant;
@class Peanut;

@interface PeanutsModel : GameModel
{
  Player* player;
  Elephant* elephant;
  Peanut* peanut;

  NSTimeInterval startTime;
  NSTimeInterval gameLength;
  int score;
}

#define DEFAULT_GAME_LENGTH 180;

-(id) init;
-(int) getPlayerScore;
-(Peanut*) getPeanut;
-(Player*) getPlayer;
-(void) movePlayerXDir:(int)dx yDir:(int)dy;
-(void) makePeanut;
-(int) getTimeLeft;
-(void) handleCollisionSprite:(Sprite*)s1 with:(Sprite*) s2;

@end

player.h

#import "sprite.h"

@interface Player : Sprite
{
  int recoverDx;
  int recoverDy;
  double recoveryTime;
}

#define PLAYER_DEFAULT_SIZE 0.025

#define PLAYER_RECOVERY_TIME 0.5
#define PLAYER_CLIMBING_TIME 0.2

#define STATE_TRAMPLED 1

-(id) initAtX:(double)initX y:(double)initY;
-(double) getMaximumSpeed;
-(void) moveDirX:(int)dx y:(int)dy;
-(void) trample;
-(void) fallInHole;
-(void) updateForTime:(double)t model:(GameModel*)m;
-(void) dealloc;

@end

sprite.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class GameModel;

@interface Sprite : NSObject
{
  double x;
  double y;
  double vx;
  double vy;
  double radius;
  UIColor *color;
  int state;
  double stateTime;
}

#define STATE_NORMAL 0

-(id) initWithX:(double)initX y:(double)initY radius:(double)r;
-(id) initWithX:(double)initX y:(double)initY vx:(double)initVx vy:(double)initVy radius:(double)r;
-(id) initWithX:(double)initX y:(double)initY vx:(double)initVx vy:(double)initVy radius:(double)r color:(UIColor *)c;
-(double) getX;
-(double) getY;
-(UIColor*) getColor;
-(double) getMaximumSpeed;
-(void) setVelocityX:(double)newVx y:(double)newVy;
-(double) getBoundingRadius;
-(BOOL) collidesWith:(Sprite*)s;
-(void) updateForTime:(double)t model:(GameModel*)m;
-(int) getState;
-(void) setState:(int)s;
-(double) getStateTime;
-(void) dealloc;

@end
This code can also be downloaded from the files
EAGLView.m, elephant.m, gamemodel.m, hole.m, peanut.m, PeanutsAppDelegate.m, peanutsmodel.m, player.m, sprite.m, EAGLView.h, elephant.h, gamemodel.h, hole.h, peanut.h, PeanutsAppDelegate.h, peanutsmodel.h, player.h, and sprite.h.