SoundEffectsWithMenus

barbarousmonthMobile - Wireless

Dec 10, 2013 (4 years and 21 days ago)

169 views

Sound Effects



The library
Cocosdenshion

subproject of
cocos2d
-
iphone targeted at game audio needs




Sound effects can be loaded at application
startup, so there's no delay during play


http://www.cocos2d
-
iphone.org/wiki/doku.php/cocosdenshion:faq




What we have so far...

Source files:


AsteroidsAppDelegate.h/m



implements UIApplicationDelegate


AsteroidScene.h/m



is
-
a CCLayer (the game layer), and



implements CCTargetedTouchDelegate

What we will add...


Include the .wav files in the 'Resources' Group
(crtl
-
click → Add → Existing Files)


Import 'SimpleAudioEngine' in AsteroidsScene.h
to have access to the API



Make a '#define' for .wav files in
AsteroidsScene.h to reference them in multiple
places


Preload the .wav files in AsteroidsAppDelegate
applicationDidFinishLaunching


Play the .wav effects where needed

AsteroidScene.h

...

// Importing Chipmunk headers

#import
"chipmunk.h"



#import "SimpleAudioEngine.h"


//

// All of these wav files are preloaded in AsteroidsAppDelegate.m in

// AsteroidsAppDelegate::applicationDidFinishLaunching

// These wav files were maked as 'Public domain' and downloaded from

//
http://simplythebest.net/sounds/WAV/


#define MISSILE_HIT_ASTEROID_WAV @"explosion.wav"

#define MISSILE_FIRED_WAV @"cork_pop.wav"



enum

CollisionTypes

{

...

AsteroidAppDelegate.m


@synthesize

window;


-

(
void
) applicationDidFinishLaunching:(
UIApplication
*)application

{







// Turn on multiple touches


EAGLView

*view = [director
openGLView
];


[view
setMultipleTouchEnabled
:
YES
];



// Default texture format for PNG/BMP/TIFF/JPEG/GIF images


// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565


// You can change anytime.


[
CCTexture2D

setDefaultAlphaPixelFormat
:
kTexture2DPixelFormat_RGBA8888
];




[[SimpleAudioEngine sharedEngine] preloadEffect: MISSILE_HIT_ASTEROID_WAV];


[[SimpleAudioEngine sharedEngine] preloadEffect: MISSILE_FIRED_WAV];



[[
CCDirector

sharedDirector
]
runWithScene
: [
AsteroidsScene

scene
]];

}

AsteroidScene.m

// Handler called by Chipmunk Physics when it detects a collision between two registered objects.

// In this case a Missile and an Asterois.

int

beginMissileHitAsteroid(
cpArbiter

*arb,
cpSpace

*
space
,
void

*data
__attribute__

((unused))) {


NSLog
(
@"missileHitAsteroid!!!
\
n"
);



// Add code here to break up the asteroid if it's hasn't reached it's smallest size (in this


// case remove it). Quite important to note that you need to use 'post
-
step' callbacks to add or remove


// objects from the space. You CAN"T do it in a callback like this one. see...


//
http://files.slembcke.net/chipmunk/release/ChipmunkLatest
-
Docs/examples.html#CollisionCallbacks



// Get the cpShapes involved in the collision


// The order will be the same as you defined in the handler definition


cpShape

*
missileShape
, *asteroidShape;
cpArbiterGetShapes
(arb, &
missileShape
, &asteroidShape);



// Add a post step callback to safely remove the body and shape from the space.


// Calling cpSpaceRemove*() directly from a collision handler callback can cause crashes.


// You can only register one post step callback per object.


cpSpaceAddPostStepCallback
(
space
, (
cpPostStepFunc
)postStepDistroyAsteroid, asteroidShape,
NULL
);


cpSpaceAddPostStepCallback
(
space
, (
cpPostStepFunc
)postStepDistroyMissile,
missileShape
,
NULL
);



[[SimpleAudioEngine sharedEngine] playEffect:MISSILE_HIT_ASTEROID_WAV];



// The object is dead, don't process the collision further


return

0
;

}

AsteroidScene.m

// Invoked when the finger leaves the screen...

-

(
void
)ccTouchEnded:(
UITouch

*)touch withEvent:(
UIEvent

*)event {


CGPoint

loc = [touch
locationInView
: [touch
view
]];


loc = [[
CCDirector

sharedDirector
]
convertToGL
: loc];


cpVect

p =
shipBody
-
>
p
;


NSLog
(
@"ccTouchEnded shipBody <x,y> <%f,%f> loc <x,y> <%f,%f> touchMoved %@
\
n"
, p.
x
, p.
y
, loc.
x
, loc.
y
, (
touchMoved

?
@"Y"

:
@"N"
));



// If there was a "move" during this touch, then fire the thrusters, otherwise fire a missle


if

(
touchMoved
) {


// If the touch was near the last [end] touch then we fire the thrusters,


// otherwise, we fire a missile.


NSLog
(
@"Thrusters...
\
n"
);


cpVect

shipAngleVector =
cpvforangle
(
shipBody
-
>
a
);


//cpVect shipAngleVector = cpv(cos(shipBody
-
>a),sin(shipBody
-
>a));



// Note that the magnitude of the thrust needs to be based on the mass of the object


// being moved


cpFloat

thrustMagnitude =
SHIP_MASS

*
THRUST_MULTIPLIER
;


cpBodyApplyImpulse
(
shipBody
,
cpvmult
(shipAngleVector, thrustMagnitude),
cpvzero
);



}
else

{


// then fire a missle...


NSLog
(
@"Missile...
\
n"
);



[[SimpleAudioEngine sharedEngine] playEffect:MISSILE_FIRED_WAV];



fireMissile
();


}

}

CocosDenshion FAQ

Q & A to some problems that you might bump
into...


I've got some wave files but they don't work, what
can I do?


http://www.cocos2d
-
iphone.org/wiki/doku.php/cocosdenshion:faq

Background music from ipod library

You’ll need a provisioned device because the
Simulator has no access to a device’s iPod library.


Follow these instructions...

http://developer.apple.com/iphone/library/docume
ntation/Audio/Conceptual/iPodLibraryAccess_Gui
de/Introduction/Introduction.html


Adding Splash Screen

Here we will add a splash screen that will allow
the user to to turn the sound effects on/off.


This is done through scenes, layers, and
transitions.


We will also use the cocos2d
-
iphone menu
system.


http://www.cocos2d
-
iphone.org/wiki/doku.php/prog_guide:lesson_3._m
enus_and_scenes


AsteroidScene.h

// This global is set by the user from the menue

BOOL

audioEffects
;


// Here we define the startup layer

@interface

StartupLayer : CCLayer {


CCMenu
*
menu
;

}


@property

(
readwrite
,
assign
) CCMenu* menu;


-
(
id
) init;

@end

AsteroidsAppDelegete.m

//

// Called when the application is launched

-

(
void
) applicationDidFinishLaunching:(
UIApplication
*)application

{

...




//[[CCDirector sharedDirector] runWithScene: [AsteroidsScene scene]];


// Startup with the 'StartupLayer' Layer...


CCScene *scene = [CCScene node];


[scene addChild: [StartupLayer node]];


[director runWithScene: scene];

}

AsteroidsScene.m

In the 'init' method we need to:



Create the menu, and it's items



Describe how on the page they will be displayed



Attach the menu to the Layer



We also need to declare the selector method

A selector message (callback) is sent when the
user interacts with the menu.

AsteroidsScene.m

BOOL

audioEffects =
NO
;


@implementation

StartupLayer


@synthesize

menu;


-
(
id
) init {

if
( (
self
=[
super

init
])) {



CCMenuItemFont

*title1 = [
CCMenuItemFont

itemFromString
:
@"Audio Effects:"
];


[title1
setIsEnabled
:
NO
];
// It's just a title. You can't click on it.



CCMenuItemToggle

*item1 = [
CCMenuItemToggle










itemWithTarget
:
self



selector
:
@selector
(
menuSoundCallback
:)










items
:




[
CCMenuItemFont

itemFromString
:
@"Off"
],




[
CCMenuItemFont

itemFromString
:
@"On"
],











nil
];
// End the list


[item1
setSelectedIndex
:
audioEffects
];
// Sets the value for display purposes

AsteroidsScene.m



// Rather than text, we will use an image...



CCMenuItemImage

*menuItem1 =[
CCMenuItemImage

itemFromNormalImage
:
@"btn
-
play
-
normal.png"















selectedImage
:
@"btn
-
play
-
selected.png"















target
:
self



















selector
:
@selector
(
playGameCallback
)];



// Create the menu with the items...



menu

= [
CCMenu

menuWithItems
: title1, item1, menuItem1,
nil
];




// Describe the presentation on the page...



[
menu

alignItemsInColumns
:





[
NSNumber

numberWithUnsignedInt
:
2
],
// title1 & item1 on the same line






[
NSNumber

numberWithUnsignedInt
:
1
],
// play button on a line by it's self





nil
];
// End the list






// Attach the menu to the layer



[
self

addChild
:
menu
];





}


return

self
;

}

AsteroidsScene.m


-
(
void
) menuSoundCallback: (
id
) sender

{


audioEffects

= [sender
selectedIndex
];
// get the value and store it in the global


NSLog
(
@"menuSoundCallback audioEffects = %@
\
n"
,
audioEffects
?
@"On"
:
@"Off"
);

}


-

(
void
) playGameCallback {


// Here we do the scene replacement....


CCScene

*scene = [
CCScene

node
];


[scene
addChild
: [
AsteroidsScene

node
]];


[[
CCDirector

sharedDirector
]
replaceScene
:scene];
// could also use a fancy transition

}


@end