Skip to content

Instantly share code, notes, and snippets.

@SecondReality
Created May 26, 2012 22:24
Show Gist options
  • Save SecondReality/2795499 to your computer and use it in GitHub Desktop.
Save SecondReality/2795499 to your computer and use it in GitHub Desktop.
GameMain
//
// GameMain.h
//
// Created by Steven Mark Rose on 25/09/2010.
// Copyright 2010 Second Reality. All rights reserved.
//
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import "Texture2D.h"
#import "GameOptions.h"
#import "BackgroundProtocol.h"
#import "SoundTypes.h"
@class OalPlayback;
@class Mouse;
@class Flexer;
@class Vector2D;
@class MouseRenderer;
@class UITapTapTap;
@protocol ToyProtocol;
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
@interface GameMain : NSObject
{
@private
EAGLContext *context;
OalPlayback * playback;
// The pixel dimensions of the CAEAGLLayer
GLint backingWidth;
GLint backingHeight;
// Height divided by width
float aspect;
// The OpenGL ES names for the framebuffer and renderbuffer used to render to this view
GLuint defaultFramebuffer, colorRenderbuffer;
CFTimeInterval lastTime;
id <ToyProtocol> currentToy;
id currentRenderer;
id <BackgroundProtocol> currentBackground;
MouseRenderer * mouseRenderer;
GameOptions options;
ALuint sounds[SoundTypeEnd];
SoundType soundToPlay;
@public
UIView * view;
UIView * menuView;
UITableView * tableView;
UIButton * titleImageView;
UITapTapTap * unlockSlider;
}
- (void)render;
- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)createMainMenuWithOptions;
- (void)MainMenuClosedWithToy:(int)toy;
- (id)initWithView:(UIView*)viewIn;
- (void)orientateTo:(UIInterfaceOrientation)orientation;
-(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context;
- (void)imagePressed:(id)sender;
- (void)unlockAction:(id)sender;
@end
//
//
// Created by Steven Mark Rose on 25/09/2010.
// Copyright 2010 Second Reality. All rights reserved.
//
#import "GameMain.h"
#import "Cube.h"
#import "Quad.h"
#import "Mouse.h"
#import "Spider.h"
#import "Frog.h"
#import "FrogRenderer.h"
#import "SpiderRenderer.h"
#import "Vector2D.h"
#import "Vector3D.h"
#import "Flexer.h"
#import "GraphicsUtility.h"
#import "MouseRenderer.h"
#import "RatRenderer.h"
#import "MainMenuDelegate.h"
#import "UIViewRotationController.h"
#import "PingPongBallToy.h"
#import "PingPongBallRenderer.h"
#import "SimpleBackground.h"
#import "RatBackground.h"
#import "UITapTapTap.h"
#import "OalPlayback.h"
@implementation GameMain
- (id)initWithView:(UIView*)viewIn
{
if ((self = [super init]))
{
view = viewIn;
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context])
{
[self release];
return nil;
}
// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
glGenFramebuffersOES(1, &defaultFramebuffer);
glGenRenderbuffersOES(1, &colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
glEnable(GL_TEXTURE_2D);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// Setup a light:
GLfloat LightAmbient[]= { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat LightDiffuse[]= { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat LightPosition[]= { 0.5f, 0.0f, 1.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
glEnable(GL_LIGHT1); // Enable Light One
glEnable(GL_LIGHTING);
lastTime = CFAbsoluteTimeGetCurrent();
CGRect mainBounds = [[UIScreen mainScreen] bounds];
float sizeScale = mainBounds.size.height < 1024 ? 1.8f : 1.0f;
currentToy = [[Mouse alloc] initAsMouse:true WithSize:sizeScale];
currentRenderer=[[MouseRenderer alloc] init];
currentBackground = [[SimpleBackground alloc] initWithTexture:@"backgroundMouse.jpeg"];
options.speed=1.0f;
options.sound=false;
[self createMainMenuWithOptions];
// Initialise the sound system:
playback = [[OalPlayback alloc] init];
for(int i=0; i<SoundTypeEnd; i++)
{
ALuint newSound=[playback createSound:soundTypeFile(i)];
sounds[i]=newSound;
}
soundToPlay=SoundTypeEnd;
}
return self;
}
- (void)dealloc
{
[currentToy release];
[currentRenderer release];
[currentBackground release];
// Tear down GL
if (defaultFramebuffer)
{
glDeleteFramebuffersOES(1, &defaultFramebuffer);
defaultFramebuffer = 0;
}
if (colorRenderbuffer)
{
glDeleteRenderbuffersOES(1, &colorRenderbuffer);
colorRenderbuffer = 0;
}
// Tear down context
if ([EAGLContext currentContext] == context)
[EAGLContext setCurrentContext:nil];
[context release];
context = nil;
// Free sounds and sound system
[playback stopSound];
for(int i=0; i<SoundTypeEnd; i++)
{
alDeleteBuffers(1, &sounds[i]);
}
[playback release];
[super dealloc];
}
- (void)createMainMenuWithOptions
{
CGRect mainBounds = [[UIScreen mainScreen] bounds];
// Create the table view for the main menu:
CGRect mainFrame = view.frame;
CGRect menuTableFrame = { 0, 0, 300, mainBounds.size.height };
// Create the table that is used to draw the main menu:
tableView = [[UITableView alloc] initWithFrame:menuTableFrame style:UITableViewStyleGrouped];
MainMenuDelegate *mainMenuDelegate = [[MainMenuDelegate alloc] initWithOptions:&options Delegate:self];
tableView.scrollEnabled = NO;
tableView.delegate = mainMenuDelegate;
tableView.dataSource = mainMenuDelegate;
tableView.opaque = NO;
tableView.backgroundView = nil;
tableView.backgroundColor = [UIColor clearColor];
if(mainBounds.size.height>=1024)
{
tableView.rowHeight=65;
}
[tableView reloadData];
menuView = [[UIView alloc] initWithFrame:mainFrame];
menuView.multipleTouchEnabled=YES;
[menuView addSubview:tableView];
UIViewRotationController *controller = [[UIViewRotationController alloc] init];
controller.view = menuView;
controller->gameMain=self;
[view addSubview:menuView];
// Create the title image:
titleImageView =[UIButton buttonWithType:UIButtonTypeCustom];
UIImage * titleImage = [UIImage imageNamed:@"logo.png"];
[titleImageView setBackgroundImage:titleImage forState:UIControlStateNormal];
[menuView addSubview:titleImageView];
CGPoint titleCenter = {0, 0};
titleImageView.center=titleCenter;
CGRect bounds={0,0, titleImage.size.width, titleImage.size.height};
titleImageView.bounds=bounds;
[titleImageView addTarget:self action:@selector(imagePressed:) forControlEvents:UIControlEventTouchUpInside];
float imageRatio = mainBounds.size.height / 1024;
CGRect testFrame2 = { 0, 0, (int)(titleImage.size.width * imageRatio), (int)(titleImage.size.height * imageRatio)};
titleImageView.contentMode = UIViewContentModeScaleToFill;
titleImageView.frame = testFrame2;
// Setup our initial orientation if we're portrait:
[self orientateTo:controller.interfaceOrientation];
}
- (void)imagePressed:(id)sender
{
int funSound=rand()%SoundTypeEnd;
soundToPlay=funSound;
NSLog(@"Funsound: %d", funSound);
}
- (void)MainMenuClosedWithToy:(int)toy
{
if(toy!=options.toy)
{
options.toy=toy;
// Release the current toy and create a new one:
// TODO: Check if we need to mutex here.
[currentToy release];
[currentRenderer release];
[currentBackground release];
CGRect mainBounds = [[UIScreen mainScreen] bounds];
float sizeScale = mainBounds.size.height < 1024 ? 1.8f : 1.0f;
switch(options.toy)
{
case 0:
{
currentToy = [[Mouse alloc] initAsMouse:true WithSize:sizeScale];
currentRenderer=[[MouseRenderer alloc] init];
currentBackground=[[SimpleBackground alloc] initWithTexture:@"backgroundMouse.jpeg"];
break;
}
case 1:
{
currentToy = [[Mouse alloc] initAsMouse:false WithSize:sizeScale];
currentRenderer=[[RatRenderer alloc] init];
currentBackground=[[RatBackground alloc] init];
break;
}
case 2:
{
currentToy = [[PingPongBallToy alloc] initWithSize:sizeScale];
currentRenderer=[[PingPongBallRenderer alloc] init];
currentBackground=[[SimpleBackground alloc] initWithTexture:@"backgroundPingPongBall.jpeg"];
break;
}
case 3:
{
currentToy = [[Frog alloc] initWithSize:sizeScale];
currentRenderer=[[FrogRenderer alloc] init];
currentBackground=[[SimpleBackground alloc] initWithTexture:@"backgroundFrog.jpeg"];
break;
}
case 4:
{
currentToy = [[Spider alloc] initWithSize:sizeScale];
currentRenderer=[[SpiderRenderer alloc] init];
currentBackground=[[SimpleBackground alloc] initWithTexture:@"backgroundSpider.jpeg"];
break;
}
}
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.90f];
tableView.transform = CGAffineTransformMakeTranslation(-menuView.bounds.size.width, 0.0);
titleImageView.transform = CGAffineTransformMakeTranslation(-menuView.bounds.size.width, 0.0);
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView commitAnimations];
}
-(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
// Remove the views:
[tableView retain];
[tableView removeFromSuperview];
[titleImageView retain];
[titleImageView removeFromSuperview];
// Create the slider that appears around the edge of the screen:
CGRect unlockSliderBounds = menuView.bounds;
unlockSliderBounds.origin.y=unlockSliderBounds.size.height-90;
unlockSliderBounds.size.height=90;
unlockSlider = [[UITapTapTap alloc] initWithFrame:unlockSliderBounds];
[unlockSlider addTarget:self action:@selector(unlockAction:) forControlEvents:UIControlEventValueChanged];
unlockSlider.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleWidth;
unlockSlider.frame=unlockSliderBounds;
unlockSlider.alpha=0.0f;
[menuView addSubview:unlockSlider];
// Fade in the unlock slider here:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
unlockSlider.alpha=1.0f;
[UIView commitAnimations];
}
- (void)orientateTo:(UIInterfaceOrientation)orientation
{
CGRect mainBounds = [[UIScreen mainScreen] bounds];
if(UIInterfaceOrientationIsPortrait(orientation))
{
// Calculate the size of the table:
int tableSize=tableView.rowHeight*8;
int heightOffset = (mainBounds.size.height -tableSize) / 2.0f;
CGRect titleBounds=titleImageView.bounds;
int tableHeight = heightOffset+(int)(mainBounds.size.height*0.5f)+ titleBounds.size.height/2;
CGPoint center = {(int)(mainBounds.size.width/2), heightOffset};
titleImageView.center=center;
CGPoint menuCenter = {(int)(mainBounds.size.width/2), tableHeight };
tableView.center=menuCenter;
}
else
{
CGPoint center = {mainBounds.size.height/3, mainBounds.size.width/3};//240};
titleImageView.center=center;
CGPoint menuCenter = {(int)(mainBounds.size.height*0.66f), 120+512};
tableView.center=menuCenter;
}
}
- (void)unlockAction:(id)sender
{
tableView.transform = CGAffineTransformMakeTranslation(-menuView.bounds.size.width, 0.0);
titleImageView.transform = CGAffineTransformMakeTranslation(-menuView.bounds.size.width, 0.0);
[menuView addSubview:tableView];
[menuView addSubview:titleImageView];
// We need to animate them back into place:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.90f];
tableView.transform = CGAffineTransformMakeTranslation(0, 0.0);
titleImageView.transform = CGAffineTransformMakeTranslation(0, 0.0);
[UIView commitAnimations];
[unlockSlider removeFromSuperview];
[unlockSlider release];
}
- (void)render
{
// Sound logic:
if(options.sound)
{
SoundType toySound=[currentToy getSoundToPlay];
if(soundToPlay!=SoundTypeEnd || toySound!=SoundTypeEnd)
{
SoundType finalSound = soundToPlay==SoundTypeEnd ? toySound : soundToPlay;
Vector2D toyPosition = [currentToy soundPosition];
CGPoint toyPositionCG = {toyPosition.x*200.0f, toyPosition.y*200.0f};
playback.sourcePos=toyPositionCG;
[playback stopSound];
[playback attachBufferToSource:sounds[finalSound]];
[playback startSound];
soundToPlay=SoundTypeEnd;
}
}
// Calculate the frame delta:
CFTimeInterval time = CFAbsoluteTimeGetCurrent();
float delta = time - lastTime;
lastTime = time;
// Cap the time so that strange things can't happen:
if(delta>=0.1f)
{
delta=0.1f;
}
float timeMultiplier=1.0f;
delta*=timeMultiplier;
// Update our state:
[currentToy updateTimeDeltaSeconds:delta*options.speed aspect:aspect];
// This application only creates a single context which is already set current at this point.
// This call is redundant, but needed if dealing with multiple contexts.
[EAGLContext setCurrentContext:context];
// This application only creates a single default framebuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple framebuffers.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Setup the projection matrix:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate aspect ratio:
aspect = (float)backingHeight/(float)backingWidth;
glFrustumf(-1.0f, 1.0f, -aspect, aspect, 1.5f, 20.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
[currentBackground renderWithAspect:aspect Toy:currentToy];
[currentRenderer render:currentToy];
[currentBackground renderAfterToyWithAspect:aspect Toy:currentToy];
// This application only creates a single color renderbuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple renderbuffers.
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
{
// Allocate color buffer backing based on the current layer size
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
{
NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSEnumerator *enumerator = [touches objectEnumerator];
UITouch* touch;
while ((touch = [enumerator nextObject]))
{
CGPoint locationInView=[touch locationInView:view];
[currentToy respondToTouchesBegan:touch at:locationInView];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSEnumerator *enumerator = [touches objectEnumerator];
UITouch* touch;
while ((touch = [enumerator nextObject]))
{
CGPoint locationInView=[touch locationInView:view];
[currentToy respondToTouchesMoved:touch at:locationInView];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSEnumerator *enumerator = [touches objectEnumerator];
UITouch* touch;
while ((touch = [enumerator nextObject]))
{
CGPoint locationInView=[touch locationInView:view];
[currentToy respondToTouchesEnded:touch at:locationInView];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSEnumerator *enumerator = [touches objectEnumerator];
UITouch* touch;
while ((touch = [enumerator nextObject]))
{
CGPoint locationInView=[touch locationInView:view];
[currentToy respondToTouchesEnded:touch at:locationInView];
}
}
@end
@SecondReality
Copy link
Author

The main game object for Cat Toys. It handles the initialization of OpenGL, game state and manages the display of the main menu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment